Comparison of the afw repository

Summary of Repositories

Comparison run at 01:26PM on June 09, 2015
There are 17698 differences between the two repositories

Repository /Users/nate/repos_hsc/afw/
Revision 99722d4ab29f387c1ed98717b47f29716e7ab289
Branch master
Last commit was on 2015-05-11 11:32:20 -0400

Repository /Users/nate/repos_lsst/afw/
Revision 0df57534a215ea29db1aee4d915f06dc0a894322
Branch master
Last commit was on 2015-06-08 18:17:31 -0600


Files only in /Users/nate/repos_hsc/afw/

src/math/BoundedField.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/cameraGeom/Distortion.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/cameraGeom/DetectorMosaic.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/cameraGeom/Amp.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/coord/Utils.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/image/ApCorrMap.i

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/cameraGeom/DetectorMosaic.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/testValidPolygon.py

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/cameraGeom/Raft.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/geom/polygon/Polygon.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

examples/ccd.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/math/BoundedField.i

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/geom/polygon/Polygon.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/geom/polygon.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/image/ApCorrMap.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/table/tableUtils.py

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/math/ChebyshevBoundedField.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/geom/polygon/Polygon.i

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/cameraGeom/Camera.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/cameraGeom/Ccd.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/math/detail/SrcPosFunctor.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/testChebyshevBoundedField.py

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/cameraGeom/Ccd.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/cameraGeom/FpPoint.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/testTrapezoidalPacker.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/math/detail/TrapezoidalPacker.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/cameraGeom/Camera.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/geom/polygon/__init__.py

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/cameraGeom/Raft.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/cameraGeom/Distortion.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/math/ChebyshevBoundedField.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/testApCorrMap.py

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/geom/polygon/polygonLib.i

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/distort.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/testDistortion.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/display/xpa.i

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/data/version-1-ExposureCatalog.fits

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/geom/polygon/SConscript

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/math/BoundedField.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

include/lsst/afw/cameraGeom/Id.h

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/image/ApCorrMap.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/math/detail/TrapezoidalPacker.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/display/scaling.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/data/version-0-ExposureCatalog.fits

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/math/ChebyshevBoundedField.i

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

src/cameraGeom/Amp.cc

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/cameraGeom.py

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

python/lsst/afw/math/approximate.i

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/distort.py

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

tests/testTableUtils.py

commit 99722d4ab29f387c1ed98717b47f29716e7ab289
Author: Jim Bosch 
Date:   Mon May 11 11:32:20 2015 -0400

    Fix X vs. Y typo in BoundedField::applyToImage.

Files only in /Users/nate/repos_lsst/afw/

tests/ticketDM-433.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/table/AliasMap.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/testUtils.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/detectorCollection.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/Polygon.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/geom/Polygon.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/table/AliasMap.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/display/interface.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/table/AmpInfo.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testFluxFromABMag.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testOrientation.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testDistortedTanWcs.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/table/slots.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/RadialXYTransform.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testDetector.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/MultiXYTransform.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/table/aggregates.i

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/table/FunctorKey.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/coordinates.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/InvertedXYTransform.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/cameraGeom/CameraPoint.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testFunctor.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/geom/SeparableXYTransform.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/table/AmpInfo.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testCameraTransformMap.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testDs9.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testTableAliases.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/geom/xyTransformFactory.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testCameraSys.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

examples/cameraGeomExample.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/table/arrays.i

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/cameraGeomEnumDicts.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/image/DistortedTanWcs.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/data/slotsVersion0.fits

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testTableAliases.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/table/arrays.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/cameraGeom/Orientation.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/cameraGeom/CameraPoint.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/display/virtualDevice.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testCameraGeom.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/cameraGeom/CameraSys.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/geom/Functor.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/table/aggregates.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/Functor.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/LinearFunctor.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/table/AmpInfo.i

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/cameraFactory.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/geom/TransformMap.i

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testAmpInfoTable.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/rotateBBoxBy90.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testMakePixelToTanPixel.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/math/detail/PositionFunctor.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

doc/cameraGeom.dox

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/display.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

examples/.gitignore

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/data/HSC-0908120-056-small.fits

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testCameraAmps.dat

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testFunctorKeys.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/table/arrays.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/cameraConfig.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/geom/TransformMap.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/geom/Polygon.i

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/IdentityXYTransform.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testSeparableXYTransform.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/fitsUtils.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testCamGeomFitsUtils.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/AffineXYTransform.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/assembleImage.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/table/tableEnumDicts.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/table/aggregates.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testCameraDetectors.dat

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/image/DistortedTanWcs.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

tests/testXYTransform.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/geom/TransformMapImpl.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

src/geom/SeparableXYTransform.cc

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

doc/geomOperators.dox

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/table/slots.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

examples/imageDisplay.ipynb

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/camera.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

include/lsst/afw/cameraGeom/CameraSys.h

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/cameraGeom/makePixelToTanPixel.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

python/lsst/afw/geom/transformConfig.py

commit 0df57534a215ea29db1aee4d915f06dc0a894322
Merge: 54f3f56 3a4b146
Author: Robert Lupton the Good 
Date:   Mon Jun 8 18:17:31 2015 -0600

    Merge branch 'tickets/DM-2883'

List of the files in common

Files without links do not differ

src/math/ConvolveImage.cc

Diff:

                // -*- LSST-C++ -*-
                
                /*
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 *
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 *
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 *
                 * You should have received a copy of the LSST License Statement and
                 * the GNU General Public License along with this program.  If not,
                 * see .
                 */
                
                /**
                 * @file
                 *
                 * @brief Definition of functions declared in ConvolveImage.h
                 *
                 * @author Russell Owen
                 *
                 * @ingroup afw
                 */
                #include 
                #include 
                #include 
                #include 
                #include 
                #include 
                #include 
                #include 
                
                #include "boost/cstdint.hpp"
                
                #include "lsst/pex/exceptions.h"
                #include "lsst/pex/logging/Trace.h"
                #include "lsst/afw/image/ImageUtils.h"
                #include "lsst/afw/image/MaskedImage.h"
                #include "lsst/afw/math/Kernel.h"
                #include "lsst/afw/math/detail/Convolve.h"
                
                namespace pexExcept = lsst::pex::exceptions;
                namespace pexLog = lsst::pex::logging;
                namespace afwGeom = lsst::afw::geom;
                namespace afwImage = lsst::afw::image;
                namespace afwMath = lsst::afw::math;
                namespace mathDetail = lsst::afw::math::detail;
                
                namespace {
                
                    /*
                    * @brief Set the edge pixels of a convolved Image based on size of the convolution kernel used
                    *
                    * Separate specializations for Image and MaskedImage are required to set the EDGE bit of the Mask plane
                    * (if there is one) when doCopyEdge is true.
                    */
                    template 
                    inline void setEdgePixels(
                            OutImageT& outImage,        ///< %image whose edge pixels are to be set
                            afwMath::Kernel const &kernel, ///< convolution kernel; kernel size is used to determine the edge
                            InImageT const &inImage,
                                ///< %image whose edge pixels are to be copied; ignored if doCopyEdge is false
                            bool doCopyEdge,            ///< if false (default), set edge pixels to the standard edge pixel;
                                                        ///< if true, copy edge pixels from input and set EDGE bit of mask
                            lsst::afw::image::detail::Image_tag)
                                ///< lsst::afw::image::detail::image_traits::image_category()
                
                    {
                        const unsigned int imWidth = outImage.getWidth();
                        const unsigned int imHeight = outImage.getHeight();
                        const unsigned int kWidth = kernel.getWidth();
                        const unsigned int kHeight = kernel.getHeight();
                        const unsigned int kCtrX = kernel.getCtrX();
                        const unsigned int kCtrY = kernel.getCtrY();
                
                        const typename OutImageT::SinglePixel edgePixel = afwMath::edgePixel(
                            typename lsst::afw::image::detail::image_traits::image_category()
                        );
                        std::vector bboxList;
                
                        // create a list of bounding boxes describing edge regions, in this order:
                        // bottom edge, top edge (both edge to edge),
                        // left edge, right edge (both omitting pixels already in the bottom and top edge regions)
                        int const numHeight = kHeight - (1 + kCtrY);
                        int const numWidth = kWidth - (1 + kCtrX);
                        bboxList.push_back(
                            afwGeom::Box2I(afwGeom::Point2I(0, 0), afwGeom::Extent2I(imWidth, kCtrY))
                        );
                        bboxList.push_back(
                            afwGeom::Box2I(afwGeom::Point2I(0, imHeight - numHeight), afwGeom::Extent2I(imWidth, numHeight))
                        );
                        bboxList.push_back(
                            afwGeom::Box2I(afwGeom::Point2I(0, kCtrY), afwGeom::Extent2I(kCtrX, imHeight + 1 - kHeight))
                        );
                        bboxList.push_back(
                            afwGeom::Box2I(afwGeom::Point2I(imWidth - numWidth, kCtrY), afwGeom::Extent2I(numWidth, imHeight + 1 - kHeight))
                        );
                
                        for (std::vector::const_iterator bboxIter = bboxList.begin();
                            bboxIter != bboxList.end(); ++bboxIter
                        ) {
                            OutImageT outView(outImage, *bboxIter, afwImage::LOCAL);
                            if (doCopyEdge) {
                                // note: <<= only works with data of the same type
                                // so convert the input image to output format
                                outView <<= OutImageT(InImageT(inImage, *bboxIter, afwImage::LOCAL), true);
                            } else {
                                outView = edgePixel;
                            }
                        }
                    }
                
                    /*
                    * @brief Set the edge pixels of a convolved MaskedImage based on size of the convolution kernel used
                    *
                    * Separate specializations for Image and MaskedImage are required to set the EDGE bit of the Mask plane
                    * (if there is one) when doCopyEdge is true.
                    */
                    template 
                    inline void setEdgePixels(
                            OutImageT& outImage,        ///< %image whose edge pixels are to be set
                            afwMath::Kernel const &kernel,  ///< convolution kernel; kernel size is used to determine the edge
                            InImageT const &inImage,
                                ///< %image whose edge pixels are to be copied; ignored if doCopyEdge false
                            bool doCopyEdge,            ///< if false (default), set edge pixels to the standard edge pixel;
                                                        ///< if true, copy edge pixels from input and set EDGE bit of mask
                            lsst::afw::image::detail::MaskedImage_tag)
                                ///< lsst::afw::image::detail::image_traits::image_category()
                
                    {
                        const unsigned int imWidth = outImage.getWidth();
                        const unsigned int imHeight = outImage.getHeight();
                        const unsigned int kWidth = kernel.getWidth();
                        const unsigned int kHeight = kernel.getHeight();
                        const unsigned int kCtrX = kernel.getCtrX();
                        const unsigned int kCtrY = kernel.getCtrY();
                
                        const typename OutImageT::SinglePixel edgePixel = afwMath::edgePixel(
                            typename lsst::afw::image::detail::image_traits::image_category()
                        );
                        std::vector bboxList;
                
                        // create a list of bounding boxes describing edge regions, in this order:
                        // bottom edge, top edge (both edge to edge),
                        // left edge, right edge (both omitting pixels already in the bottom and top edge regions)
                        int const numHeight = kHeight - (1 + kCtrY);
                        int const numWidth = kWidth - (1 + kCtrX);
                        bboxList.push_back(
                            afwGeom::Box2I(
                                afwGeom::Point2I(0, 0),
                                afwGeom::Extent2I(imWidth, kCtrY)
                            )
                        );
                        bboxList.push_back(
                            afwGeom::Box2I(
                                afwGeom::Point2I(0, imHeight - numHeight),
                                afwGeom::Extent2I(imWidth, numHeight)
                            )
                        );
                        bboxList.push_back(
                            afwGeom::Box2I(
                                afwGeom::Point2I(0, kCtrY),
                                afwGeom::Extent2I(kCtrX, imHeight + 1 - kHeight)
                            )
                        );
                        bboxList.push_back(
                            afwGeom::Box2I(
                                afwGeom::Point2I(imWidth - numWidth, kCtrY),
                                afwGeom::Extent2I(numWidth, imHeight + 1 - kHeight)
                            )
                        );
                
                        afwImage::MaskPixel const edgeMask = afwImage::Mask::getPlaneBitMask("EDGE");
                        for (std::vector::const_iterator bboxIter = bboxList.begin();
                            bboxIter != bboxList.end(); ++bboxIter) {
                            OutImageT outView(outImage, *bboxIter, afwImage::LOCAL);
                            if (doCopyEdge) {
                                // note: <<= only works with data of the same type
                                // so convert the input image to output format
                                outView <<= OutImageT(InImageT(inImage, *bboxIter, afwImage::LOCAL), true);
                                *(outView.getMask()) |= edgeMask;
                            } else {
                                outView = edgePixel;
                            }
                        }
                    }
                
                }   // anonymous namespace
                
                /**
                 * Compute the scaled sum of two images
                 *
                 * outImage = c1 inImage1 + c2 inImage2
                 *
                 * For example to linearly interpolate between two images set:
                 *   c1 = 1.0 - fracDist
                 *   c2 = fracDist
                 * where fracDist is the fractional distance of outImage from inImage1:
                 *              location of outImage - location of inImage1
                 *   fracDist = -------------------------------------------
                 *              location of inImage2 - location of inImage1
                 *
213 d7d666c2 - * @throw lsst::pex::exceptions::InvalidParameterException if outImage is not same dimensions
? ^^^^^^ ^
213 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if outImage is not same dimensions
? ^^ ^ * as inImage1 and inImage2. */ template void afwMath::scaledPlus( OutImageT &outImage, ///< output image double c1, ///< coefficient for image 1 InImageT const &inImage1, ///< input image 1 double c2, ///< coefficient for image 2 InImageT const &inImage2) ///< input image 2 { if (outImage.getDimensions() != inImage1.getDimensions()) { std::ostringstream os; os << "outImage dimensions = ( " << outImage.getWidth() << ", " << outImage.getHeight() << ") != (" << inImage1.getWidth() << ", " << inImage1.getHeight() << ") = inImage1 dimensions";
229 d7d666c2 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
? ^^^^^^ ^
229 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
? ^^ ^ } else if (inImage1.getDimensions() != inImage2.getDimensions()) { std::ostringstream os; os << "inImage1 dimensions = ( " << inImage1.getWidth() << ", " << inImage1.getHeight() << ") != (" << inImage2.getWidth() << ", " << inImage2.getHeight() << ") = inImage2 dimensions";
235 d7d666c2 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
? ^^^^^^ ^
235 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
? ^^ ^ } typedef typename InImageT::const_x_iterator InConstXIter; typedef typename OutImageT::x_iterator OutXIter; for (int y = 0; y != inImage1.getHeight(); ++y) { InConstXIter const end1 = inImage1.row_end(y); InConstXIter inIter1 = inImage1.row_begin(y); InConstXIter inIter2 = inImage2.row_begin(y); OutXIter outIter = outImage.row_begin(y); for (; inIter1 != end1; ++inIter1, ++inIter2, ++outIter) { *outIter = (*inIter1 * c1) + (*inIter2 * c2); } } } /** * @brief Convolve an Image or MaskedImage with a Kernel, setting pixels of an existing output %image. * * Various convolution kernels are available, including: * - FixedKernel: a kernel based on an %image * - AnalyticKernel: a kernel based on a Function * - SeparableKernel: a kernel described by the product of two one-dimensional Functions: f0(x) * f1(y) * - LinearCombinationKernel: a linear combination of a set of spatially invariant basis kernels. * - DeltaFunctionKernel: a kernel that is all zeros except one pixel whose value is 1. * Typically used as a basis kernel for LinearCombinationKernel. * * If a kernel is spatially varying, its spatial model is computed at each pixel position on the image * (pixel position, not pixel index). At present (2009-09-24) this position is computed relative * to the lower left corner of the sub-image, but it will almost certainly change to be * the lower left corner of the parent image. * * All convolution is performed in real space. This allows convolution to handle masked pixels * and spatially varying kernels. Although convolution of an Image with a spatially invariant kernel could, * in fact, be performed in Fourier space, the code does not do this. * * Note that mask bits are smeared by convolution; all nonzero pixels in the kernel smear the mask, even * pixels that have very small values. Larger kernels smear the mask more and are also slower to convolve. * Use the smallest kernel that will do the job. * * convolvedImage has a border of edge pixels which cannot be computed normally. Normally these pixels * are set to the standard edge pixel, as returned by edgePixel(). However, if your code cannot handle * nans in the %image or infs in the variance, you may set doCopyEdge true, in which case the edge pixels * are set to the corresponding pixels of the input %image and (if there is a mask) the mask EDGE bit is set. * * The border of edge pixels has size: * - kernel.getCtrX() along the left edge * - kernel.getCtrY() along the bottom edge * - kernel.getWidth() - 1 - kernel.getCtrX() along the right edge * - kernel.getHeight() - 1 - kernel.getCtrY() along the top edge * You can obtain a bounding box for the good pixels in the convolved image * from a bounding box for the entire image using the Kernel method shrinkBBox. * * Convolution has been optimized for the various kinds of kernels, as follows (listed approximately * in order of decreasing speed): * - DeltaFunctionKernel convolution is a simple %image shift. * - SeparableKernel convolution is performed by convolving the input by one of the two functions, * then the result by the other function. Thus convolution with a kernel of size nCols x nRows becomes * convolution with a kernel of size nCols x 1, followed by convolution with a kernel of size 1 x nRows. * - Convolution with spatially invariant versions of the other kernels is performed by computing * the kernel %image once and convolving with that. The code has been optimized for cache performance * and so should be fairly efficient. * - Convolution with a spatially varying LinearCombinationKernel is performed by convolving the %image * by each basis kernel and combining the result by solving the spatial model. This will be efficient * provided the kernel does not contain too many or very large basis kernels. * - Convolution with spatially varying AnalyticKernel is likely to be slow. The code simply computes * the output one pixel at a time by computing the AnalyticKernel at that point and applying it to * the input %image. This is not favorable for cache performance (especially for large kernels) * but avoids recomputing the AnalyticKernel. It is probably possible to do better. * * Additional convolution functions include: * - convolveAtAPoint(): convolve a Kernel to an Image or MaskedImage at a point. * - basicConvolve(): convolve a Kernel with an Image or MaskedImage, but do not set the edge pixels * of the output. Optimization of convolution for different types of Kernel are handled by different * specializations of basicConvolve(). * * afw/examples offers programs that time convolution including timeConvolve and timeSpatiallyVaryingConvolve. * * \note This function is able to use GPU acceleration (for spatially invariant kernels and * for LinearCombinationKernel). * There is a limit on maximum kernel size, but kernels sized at most 17x17 should be accelerated * on all supported GPU hardware (SM 1.3 and better). SM 2.x can accelerate kernels sized up to 22x22. *
318 ece036c4 - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage is not the same size as inImage
? ^^^^^^ ^
318 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage is not the same size as inImage
? ^^ ^
319 32fb2f01 - * @throw lsst::pex::exceptions::InvalidParameterException if inImage is smaller than kernel
? ^^^^^^ ^
319 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage is smaller than kernel
? ^^ ^ * in columns and/or rows.
321 d2b4aeab - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
? ^^^^^^ ^
321 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
? ^^ ^
322 d2b4aeab - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
? ^^^^^^ ^
322 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
? ^^ ^
323 d2b4aeab - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
? ---------
323 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
* * @ingroup afw */ template void afwMath::convolve( OutImageT& convolvedImage, ///< convolved %image; must be the same size as inImage InImageT const& inImage, ///< %image to convolve KernelT const& kernel, ///< convolution kernel ConvolutionControl const& convolutionControl) ///< convolution control parameters { mathDetail::basicConvolve(convolvedImage, inImage, kernel, convolutionControl); setEdgePixels(convolvedImage, kernel, inImage, convolutionControl.getDoCopyEdge(), typename lsst::afw::image::detail::image_traits::image_category() ); convolvedImage.setXY0(inImage.getXY0()); } /** * @brief Old, deprecated version of convolve. * * @deprecated This version has no ability to control interpolation parameters. */ template void afwMath::convolve( OutImageT& convolvedImage, ///< convolved %image; must be the same size as inImage InImageT const& inImage, ///< %image to convolve KernelT const& kernel, ///< convolution kernel bool doNormalize, ///< if true, normalize the kernel, else use "as is" bool doCopyEdge) ///< if false (default), set edge pixels to the standard edge pixel; ///< if true, copy edge pixels from input and set EDGE bit of mask { ConvolutionControl convolutionControl; convolutionControl.setDoNormalize(doNormalize); convolutionControl.setDoCopyEdge(doCopyEdge); afwMath::convolve(convolvedImage, inImage, kernel, convolutionControl); } /* * Explicit instantiation of all convolve functions. * * This code needs to be compiled with full optimization, and there's no reason why * it should be instantiated in the swig wrappers. */ #define IMAGE(PIXTYPE) afwImage::Image #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage // // Next a macro to generate needed instantiations for IMGMACRO (either IMAGE or MASKEDIMAGE) // and the specified pixel types // /* NL's a newline for debugging -- don't define it and say g++ -C -E -I$(eups list -s -d boost)/include Convolve.cc | perl -pe 's| *NL *|\n|g' */ #define NL /* */ // // Instantiate one kernel-specific specializations of convolution functions for Image or MaskedImage // IMGMACRO = IMAGE or MASKEDIMAGE // KERNELTYPE = a kernel class // #define INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, KERNELTYPE) \ template void afwMath::convolve( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, KERNELTYPE const&, bool, bool); NL \ template void afwMath::convolve( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, KERNELTYPE const&, ConvolutionControl const&); NL // // Instantiate Image or MaskedImage versions of all functions defined in this file. // Call INSTANTIATE_IM_OR_MI_KERNEL once for each kernel class. // IMGMACRO = IMAGE or MASKEDIMAGE // #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \ template void afwMath::scaledPlus( \ IMGMACRO(OUTPIXTYPE)&, double, IMGMACRO(INPIXTYPE) const&, double, IMGMACRO(INPIXTYPE) const&); NL \ INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, afwMath::AnalyticKernel) \ INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, afwMath::DeltaFunctionKernel) \ INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, afwMath::FixedKernel) \ INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, afwMath::LinearCombinationKernel) \ INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, afwMath::SeparableKernel) \ INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, afwMath::Kernel) \ // // Instantiate all functions defined in this file for one specific output and input pixel type // /// \cond #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE) // // Instantiate all functions defined in this file // INSTANTIATE(double, double) INSTANTIATE(double, float) INSTANTIATE(double, int) INSTANTIATE(double, boost::uint16_t) INSTANTIATE(float, float) INSTANTIATE(float, int) INSTANTIATE(float, boost::uint16_t) INSTANTIATE(int, int) INSTANTIATE(boost::uint16_t, boost::uint16_t) /// \endcond

Return to list

Commits in /Users/nate/repos_hsc/afw/

d7d666c2

commit d7d666c2df0fb12062dc69c1390aa702949f8908
Author: rowen 
Date:   Wed Apr 21 22:11:17 2010 +0000

    Mostly implemented. Still to do:
    - wire the new code up to the convolve or basicConvolve functions
    - implement brute force convolution case in convolveRegionWithRecursiveInterpolation
    - swig the new code
    - unit tests

32fb2f01

commit 32fb2f0163ebd0381ac59c9cc08ff44b388bd333
Author: rowen 
Date:   Thu Sep 24 23:37:33 2009 +0000

    Improved documentation of spatial model in kernel (including fixing an erronous outdated note).
    Shortened some (but not all) lines that were too long.

ece036c4

commit ece036c46b1193cebcba8390e23d4c0dc904f230
Author: rowen 
Date:   Tue Apr 13 22:45:43 2010 +0000

    Added KernelImagesForRegion, a helper class for convolution with linear interpolation.

d2b4aeab

commit d2b4aeab82fff0526c277614f8b85caa2aee3cda
Author: Kresimir Cosic 
Date:   Fri Mar 23 04:59:14 2012 +0100

    Should work with w2012

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

include/lsst/afw/detection/HeavyFootprint.h

Diff:

                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                #if !defined(LSST_DETECTION_HEAVY_FOOTPRINT_H)
                #define LSST_DETECTION_HEAVY_FOOTPRINT_H
                /**
                 * \file
                 * \brief Represent a set of pixels of an arbitrary shape and size,
                 *        including values for those pixels; a HeavyFootprint is a
                 *        Footprint that also not only a description of a region, but
                 *        values within that region.
                 */
                #include 
                #include 
                #include 
                #include 
                #include 
                #include "lsst/afw/detection/Footprint.h"
                
                namespace lsst {
                namespace afw { 
                namespace detection {
                
                class HeavyFootprintCtrl;
                
                /*!
                 * \brief A set of pixels in an Image, including those pixels' actual values
                 */
                template 
                class HeavyFootprint :
                    public afw::table::io::PersistableFacade< HeavyFootprint >,
                    public Footprint
                {
                public:
                
56 94770baf + /**
57 94770baf + * Create a HeavyFootprint from a regular Footprint and the image that
58 94770baf + * provides the pixel values
59 94770baf + *
60 94770baf + * \note: the HeavyFootprintCtrl is passed by const* not const& so
61 94770baf + * that we needn't provide a definition in the header.
62 94770baf + *
63 94770baf + * foot: The Footprint defining the pixels to set
64 94770baf + * mimage: The pixel values
65 94770baf + * ctrl: Control how we manipulate HeavyFootprints
66 94770baf + */
explicit HeavyFootprint( Footprint const& foot, lsst::afw::image::MaskedImage const& mimage, HeavyFootprintCtrl const* ctrl=NULL );
73 94770baf + /**
74 94770baf + * Create a HeavyFootprint from a regular Footprint, allocating space
75 94770baf + * to hold foot.getArea() pixels, but not initializing them. This is
76 94770baf + * used when unpersisting a HeavyFootprint.
77 94770baf + */
explicit HeavyFootprint(Footprint const& foot, HeavyFootprintCtrl const* ctrl=NULL);
81 94770baf + /**
82 94770baf + * Is this a HeavyFootprint (yes!)
83 94770baf + */
virtual bool isHeavy() const { return true; }
86 94770baf + /**
87 94770baf + * Replace all the pixels in the image with the values in the HeavyFootprint.
88 94770baf + */
void insert(lsst::afw::image::MaskedImage & mimage) const;
90 94770baf +
91 94770baf + /**
92 94770baf + * Replace all the pixels in the image with the values in the HeavyFootprint.
93 94770baf + */
void insert(lsst::afw::image::Image & image) const; ndarray::Array getImageArray() { return _image; } ndarray::Array getMaskArray() { return _mask; } ndarray::Array getVarianceArray() { return _variance; } ndarray::Array getImageArray() const { return _image; } ndarray::Array getMaskArray() const { return _mask; } ndarray::Array getVarianceArray() const { return _variance; } /* Returns the OR of all the mask pixels held in this HeavyFootprint. */ MaskPixelT getMaskBitsSet() const { MaskPixelT maskbits = 0; for (typename ndarray::Array::Iterator i = _mask.begin(); i != _mask.end(); ++i) { maskbits |= *i; } return maskbits; } protected: class Factory; // factory class used for persistence, public only so we can instantiate it in .cc file virtual std::string getPersistenceName() const; virtual void write(OutputArchiveHandle & handle) const; private: HeavyFootprint() {} // private constructor, only used for persistence. ndarray::Array _image; ndarray::Array _mask; ndarray::Array _variance; };
129 94770baf + /**
130 94770baf + * Create a HeavyFootprint with footprint defined by the given
131 94770baf + * Footprint and pixel values from the given MaskedImage.
132 94770baf + */
template HeavyFootprint makeHeavyFootprint( Footprint const& foot, lsst::afw::image::MaskedImage const& img, HeavyFootprintCtrl const* ctrl=NULL ) { return HeavyFootprint(foot, img, ctrl); }
143 94770baf + /**
144 94770baf + * Sum the two given HeavyFootprints *h1* and *h2*, returning a
145 94770baf + * HeavyFootprint with the union footprint, and summed pixels where
146 94770baf + * they overlap. The peak list is the union of the two inputs.
147 94770baf + */
template boost::shared_ptr > mergeHeavyFootprints( HeavyFootprint const& h1, HeavyFootprint const& h2 ); }}} #endif

Return to list

Commits in /Users/nate/repos_hsc/afw/

Commits in /Users/nate/repos_lsst/afw/

94770baf

commit 94770bafec04976204f56cf3aed80fa02bece412
Author: Dustin Lang 
Date:   Mon Jun 23 17:17:08 2014 -0500

    Address various issues from Paul Price's in-depth review.
    
    Footprint.h:
        No documentation for new methods and functions.
    
    Footprint.cc:
        Move documentation to header file.
        Indentation is inconsistent. Should always be 4.
        Don't use this-> when there is no need for it, e.g., this->addSpan should be addSpan.
        Paren following LSST_EXCEPT *must* cuddle --- it certainly may not be on the next line.
        Breaks 110 column limit.
        PixelT zero = 0; should be PixelT const zero = 0; Add const also for ix0 and iy0 --- *anywhere* the value will never change, as it helps the compiler write faster code.
        You're iterating with the postfix operator (s++) instead of prefix (++s); this can adversely affect performance in C++.
        What does the comment Ugly! refer to?
        Names foota and footb don't follow naming rules, and are a bit hard to read. Suggest aFoot and bFoot. Similarly with pka, etc.
        const Footprint::PeakList& --> Footprint::PeakList const& (throughout).
        while (1) --> while (true)
        nearestFootprint isn't documented.
        Why do you call INSTANTIATE_FLOAT on integer types???  [I renamed it -- it instantiated functions that were appropriate for *numeric*, not necessarily floating-point, types!]
        remove gratuitous 'typename'
        prefer PTR(Foo) to Foo::Ptr and CONST_PTR(Foo) to Foo:ConstPtr.
    
    HeavyFootprint?.cc:
        Some lines exceed 110 columns.
        Commented out code should be removed
    
    footprint1.py:
        Instead of self.assertTrue(a > b) use self.assertGreater(a, b). This provides a more useful message when it fails.
        Why is the trailing F required on clipToNonzeroF? It should be able to tell from the type of the image.  [fixed]
    
    Also removed stray Footprint.mergeWith() function that got messed up during rebase

Return to list

include/lsst/afw/geom/ellipses/BaseCore.h

Diff:

                // -*- lsst-c++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                
                #ifndef LSST_AFW_GEOM_ELLIPSES_BaseCore_h_INCLUDED
                #define LSST_AFW_GEOM_ELLIPSES_BaseCore_h_INCLUDED
                
                /**
                 *  @file
                 *  @brief Forward declarations, typedefs, and definitions for BaseCore.
                 *
                 *  @note Do not include directly; use the main ellipse header file.
                 */
                
                #include "boost/shared_ptr.hpp"
                #include "boost/make_shared.hpp"
                #include 
                #include "Eigen/Core"
                
                #include "lsst/pex/exceptions.h"
                #include "lsst/afw/geom/LinearTransform.h"
                
                namespace lsst { namespace afw { namespace geom { namespace ellipses {
                
                class Parametric;
                
                /**
                 *  @brief A base class for parametrizations of the "core" of an ellipse - the ellipticity and size.
                 *
                 *  A subclass of BaseCore provides a particular interpretation of the three pointing point values that
                 *  define an ellipse's size and ellipticity (including position angle).  All core subclasses
                 *  are implicitly convertible and can be assigned to from any other core.
                 */
                class BaseCore {
                public:
                #ifndef SWIG
                    class Transformer;
                    class GridTransform;
                    class Convolution;
                    template  struct Converter;
                #endif
                
                    typedef boost::shared_ptr Ptr;
                    typedef boost::shared_ptr ConstPtr;
                
                    typedef Eigen::Vector3d ParameterVector;  ///< Parameter vector type.
                    typedef Eigen::Matrix3d Jacobian; ///< Parameter Jacobian matrix type.
                
                    static Ptr make(std::string const & name);
                
                    static Ptr make(std::string const & name, ParameterVector const & parameters);
                
                    static Ptr make(std::string const & name, double v1, double v2, double v3);
                
                    static Ptr make(std::string const & name, BaseCore const & other);
                
                #ifndef SWIG
                    static Ptr make(std::string const & name, Transformer const & other);
                
                    static Ptr make(std::string const & name, Convolution const & other);
                #endif
                
                    /// @brief Return a string that identifies this parametrization.
                    virtual std::string getName() const = 0;
                
                    /// @brief Deep-copy the Core.
                    Ptr clone() const { return _clone(); }
                
                    /**
90 ce01a540 - * @brief Put the parameters into a "standard form", and throw InvalidParameterException
? ^^^^^^ ^
90 21597d88 + * @brief Put the parameters into a "standard form", and throw InvalidParameterError
? ^^ ^ * if they cannot be normalized. */ virtual void normalize() = 0; /// @brief Increase the major and minor radii of the ellipse core by the given buffer. void grow(double buffer); /// @brief Scale the size of the ellipse core by the given factor. void scale(double factor); /// @brief Return the area of the ellipse core. double getArea() const; /** * @brief Return the radius defined as the 4th root of the determinant of the quadrupole matrix. * * The determinant radius is equal to the standard radius for a circle, * and its square times pi is the area of the ellipse. */ double getDeterminantRadius() const; /** * @brief Return the radius defined as the square root of one half the trace of the quadrupole matrix. * * The trace radius is equal to the standard radius for a circle. */ double getTraceRadius() const; /** * @name Coordinate transforms * * These member functions transform the ellipse by the given LinearTransform. * The transform can be done in-place by calling inPlace() on the returned * expression object, or returned as a new shared_ptr by calling copy(). */ //@{ Transformer transform(LinearTransform const & transform); Transformer const transform(LinearTransform const & transform) const; //@} /** * @brief Return the transform that maps the ellipse to the unit circle. * * The returned proxy object is implicitly convertible to LinearTransform * and also supports differentiation. */ GridTransform const getGridTransform() const; /** * @name Convolve two bivariate Gaussians defined by their 1-sigma ellipses. */ //@{ Convolution convolve(BaseCore const & other); Convolution const convolve(BaseCore const & other) const; //@} /// @brief Return the size of the bounding box for the ellipse core. Extent2D computeDimensions() const; virtual void readParameters(double const * iter) = 0; virtual void writeParameters(double * iter) const = 0; /// @brief Return the core parameters as a vector. ParameterVector const getParameterVector() const; /// @brief Set the core parameters from a vector. void setParameterVector(ParameterVector const & vector); /** * @brief Compare two ellipse cores for equality. * * Ellipse cores are only equal if they have the same type. */ bool operator==(BaseCore const & other) const; /** * @brief Compare two ellipse cores for inequality. * * Ellipses are only equal if they have the same type. */ bool operator!=(BaseCore const & other) const { return !operator==(other); } /** * @brief Set the parameters of this ellipse core from another. * * This does not change the parametrization of the ellipse core. */ BaseCore & operator=(BaseCore const & other); /// @brief Assign other to this and return the derivative of the conversion, d(this)/d(other). Jacobian dAssign(BaseCore const & other); /** * @brief Convert this to the core type specified as a template parameter. */ template Converter as() const; virtual ~BaseCore() {} protected: #ifndef SWIG friend class Parametric; static void registerSubclass(Ptr const & example); template struct Registrar { Registrar() { registerSubclass(boost::make_shared()); } }; virtual BaseCore::Ptr _clone() const = 0; static void _assignQuadrupoleToAxes( double ixx, double iyy, double ixy, double & a, double & b, double & theta ); static Jacobian _dAssignQuadrupoleToAxes( double ixx, double iyy, double ixy, double & a, double & b, double & theta ); static void _assignAxesToQuadrupole( double a, double b, double theta, double & ixx, double & iyy, double & ixy ); static Jacobian _dAssignAxesToQuadrupole( double a, double b, double theta, double & ixx, double & iyy, double & ixy ); virtual void _assignToQuadrupole(double & ixx, double & iyy, double & ixy) const = 0; virtual void _assignFromQuadrupole(double ixx, double iyy, double ixy) = 0; virtual void _assignToAxes(double & a, double & b, double & theta) const = 0; virtual void _assignFromAxes(double a, double b, double theta) = 0; virtual Jacobian _dAssignToQuadrupole(double & ixx, double & iyy, double & ixy) const = 0; virtual Jacobian _dAssignFromQuadrupole(double ixx, double iyy, double ixy) = 0; virtual Jacobian _dAssignToAxes(double & a, double & b, double & theta) const = 0; virtual Jacobian _dAssignFromAxes(double a, double b, double theta) = 0; #endif }; #ifndef SWIG template struct BaseCore::Converter { BaseCore const & input; explicit Converter(BaseCore const & input_) : input(input_) {} operator Output() const { return Output(input); } boost::shared_ptr copy() const { return boost::shared_ptr(new Output(input)); } }; template inline BaseCore::Converter BaseCore::as() const { return Converter(*this); } #endif }}}} // namespace lsst::afw::geom::ellipses #endif // !LSST_AFW_GEOM_ELLIPSES_BaseCore_h_INCLUDED

Return to list

Commits in /Users/nate/repos_hsc/afw/

ce01a540

commit ce01a5406f327071e1701d534e563f0e75b870c4
Author: jbosch 
Date:   Wed Feb 2 01:27:08 2011 +0000

    afw #1556 - ellipses updated (#1551), but swig wrappers for ellipses now broken

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

src/math/Interpolate.cc

Diff:

                // -*- LSST-C++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                /**
                 * @brief Interpolate values for a set of x,y vector<>s
                 * @ingroup afw
                 * @author Steve Bickerton
                 */
                #include 
                #include 
                #include 
                #include "boost/format.hpp"
                #include "boost/shared_ptr.hpp"
                #include "gsl/gsl_errno.h"
                #include "gsl/gsl_interp.h"
                #include "gsl/gsl_spline.h"
38 b8578746 - #include "ndarray.h"
#include "lsst/pex/exceptions.h" #include "lsst/afw/math/Interpolate.h" namespace lsst { namespace afw { namespace math { /************************************************************************************************************/ namespace { std::pair, std::vector > recenter(std::vector const &x, std::vector const &y) { if (x.size() != y.size()) {
54 e231b4bd - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
53 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
? ^^ ^ str(boost::format("Dimensions of x and y must match; %ul != %ul") % x.size() % y.size())); } unsigned int const len = x.size(); if (len == 0) {
60 e231b4bd - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
59 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
? ^^ ^ "You must provide at least 1 point"); } else if (len == 1) { return std::make_pair(x, y); } std::vector recentered_x(len + 1); std::vector recentered_y(len + 1); int j = 0; recentered_x[j] = 0.5*(3*x[0] - x[1]); recentered_y[j] = y[0]; for (unsigned int i = 0; i < x.size(); ++i) { ++j; recentered_x[j] = 0.5*(x[i] + x[i + 1]); recentered_y[j] = 0.5*(y[i] + y[i + 1]); } recentered_x[j] = 0.5*(3*x[len - 1] - x[len - 2]); recentered_y[j] = y[len - 1]; return std::make_pair(recentered_x, recentered_y); } } class InterpolateConstant : public Interpolate { friend PTR(Interpolate) makeInterpolate(std::vector const &x, std::vector const &y, Interpolate::Style const style); public: virtual ~InterpolateConstant() {} virtual double interpolate(double const x) const; private: InterpolateConstant(std::vector const &x, ///< the x-values of points std::vector const &y, ///< the values at x[] Interpolate::Style const style ///< desired interpolator ) : Interpolate(recenter(x, y)), _old(_x.begin()) {} mutable std::vector::const_iterator _old; // last position we found xInterp at }; /// Interpolate a constant to the point \c xInterp double InterpolateConstant::interpolate(double const xInterp // the value we want to interpolate to ) const { // // Look for the interval wherein lies xInterp. We could naively use std::upper_bound, but that requires a // logarithmic time lookup so we'll cache the previous answer in _old -- this is a good idea if people // usually call this routine repeatedly for a range of x // // We start by searching up from _old // if (xInterp < *_old) { // We're to the left of the cache if (_old == _x.begin()) { // ... actually off the array return _y[0]; } _old = _x.begin(); // reset the cached point to the start of the array } else { // see if we're still in the same interval if (_old < _x.end() - 1 and xInterp < *(_old + 1)) { // we are, so we're done return _y[_old - _x.begin()]; } } // We're to the right of the cached point and not in the same inverval, so search up from _old std::vector::const_iterator low = std::upper_bound(_old, _x.end(), xInterp); // // Did that work? if (low == _old && _old != _x.begin()) { // No. Sigh. Search the entire range. low = std::upper_bound(_x.begin(), low + 1, xInterp); } // // OK, we've found the right interval. Return the desired value, being careful at the ends // if (low == _x.end()) { return _y[_y.size() - 1]; } else if (low == _x.begin()) { return _y[0]; } else { --low; _old = low; return _y[low - _x.begin()]; } } /************************************************************************************************************/ namespace { /* * Conversion function to switch an Interpolate::Style to a gsl_interp_type. */ ::gsl_interp_type const * styleToGslInterpType(Interpolate::Style const style) { switch (style) { case Interpolate::CONSTANT:
154 e231b4bd - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException, "CONSTANT interpolation not supported.");
? ^^^^^^ ^
153 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, "CONSTANT interpolation not supported.");
? ^^ ^ case Interpolate::LINEAR: return ::gsl_interp_linear; case Interpolate::CUBIC_SPLINE: return ::gsl_interp_cspline; case Interpolate::NATURAL_SPLINE: return ::gsl_interp_cspline; case Interpolate::CUBIC_SPLINE_PERIODIC: return ::gsl_interp_cspline_periodic; case Interpolate::AKIMA_SPLINE: return ::gsl_interp_akima; case Interpolate::AKIMA_SPLINE_PERIODIC: return ::gsl_interp_akima_periodic; case Interpolate::UNKNOWN:
168 e231b4bd - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
167 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
? ^^ ^ "I am unable to make an interpolator of type UNKNOWN"); case Interpolate::NUM_STYLES:
171 e231b4bd - throw LSST_EXCEPT(pex::exceptions::LogicErrorException,
? ---------
170 21597d88 + throw LSST_EXCEPT(pex::exceptions::LogicError,
str(boost::format("You can't get here: style == %") % style)); } } } class InterpolateGsl : public Interpolate { friend PTR(Interpolate) makeInterpolate(std::vector const &x, std::vector const &y, Interpolate::Style const style); public: virtual ~InterpolateGsl(); virtual double interpolate(double const x) const; private: InterpolateGsl(std::vector const &x, std::vector const &y, Interpolate::Style const style); ::gsl_interp_type const *_interpType; ::gsl_interp_accel *_acc; ::gsl_interp *_interp; }; InterpolateGsl::InterpolateGsl(std::vector const &x, ///< the x-values of points std::vector const &y, ///< the values at x[] Interpolate::Style const style ///< desired interpolator ) : Interpolate(x, y), _interpType(styleToGslInterpType(style)) { _acc = ::gsl_interp_accel_alloc(); if (!_acc) {
199 e231b4bd - throw LSST_EXCEPT(pex::exceptions::MemoryException, "gsl_interp_accel_alloc failed");
? ^^^^^^ ^
198 21597d88 + throw LSST_EXCEPT(pex::exceptions::MemoryError, "gsl_interp_accel_alloc failed");
? ^^ ^ } _interp = ::gsl_interp_alloc(_interpType, _y.size()); if (!_interp) {
204 42e36cd1 - throw LSST_EXCEPT(pex::exceptions::OutOfRangeException,
? ^^^^^^ ^
203 21597d88 + throw LSST_EXCEPT(pex::exceptions::OutOfRangeError,
? ^^ ^ str(boost::format("Failed to initialise spline for type %s, length %d") % _interpType->name % _y.size())); } // Note, "x" and "y" are vector; gsl_inter_init requires double[]. // The &(x[0]) here is valid because std::vector guarantees that the values are // stored contiguously in memory (for types other than bool); C++0X 23.3.6.1 for // those of you reading along. int const status = ::gsl_interp_init(_interp, &x[0], &y[0], _y.size()); if (status != 0) {
215 e231b4bd - throw LSST_EXCEPT(pex::exceptions::RuntimeErrorException,
? ---------
214 21597d88 + throw LSST_EXCEPT(pex::exceptions::RuntimeError,
str(boost::format("gsl_interp_init failed: %s [%d]") % ::gsl_strerror(status) % status)); } } InterpolateGsl::~InterpolateGsl() { ::gsl_interp_free(_interp); ::gsl_interp_accel_free(_acc); } double InterpolateGsl::interpolate(double const xInterp) const { // New GSL versions refuse to extrapolate. // gsl_interp_init() requires x to be ordered, so can just check // the array endpoints for out-of-bounds. if ((xInterp < _x.front() || (xInterp > _x.back()))) { // do our own quadratic extrapolation. // (GSL only provides first and second derivative functions) /* could also just fail via: throw LSST_EXCEPT(
236 e231b4bd - pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
235 21597d88 + pex::exceptions::InvalidParameterError,
? ^^ ^ (boost::format("Interpolation point %f outside range [%f, %f]") % x % _x.front() % _x.back()).str() ); */ double x0, y0; if (xInterp < _x.front()) { x0 = _x.front(); y0 = _y.front(); } else { x0 = _x.back(); y0 = _y.back(); } // first derivative at endpoint double d = ::gsl_interp_eval_deriv(_interp, &_x[0], &_y[0], x0, _acc); // second derivative at endpoint double d2 = ::gsl_interp_eval_deriv2(_interp, &_x[0], &_y[0], x0, _acc); return y0 + (xInterp - x0)*d + 0.5*(xInterp - x0)*(xInterp - x0)*d2; } assert(xInterp >= _x.front()); assert(xInterp <= _x.back()); return ::gsl_interp_eval(_interp, &_x[0], &_y[0], xInterp, _acc); } /************************************************************************************************************/ /** * @brief Conversion function to switch a string to an Interpolate::Style. * */ Interpolate::Style stringToInterpStyle(std::string const &style ///< desired type of interpolation ) { static std::map gslInterpTypeStrings; if (gslInterpTypeStrings.empty()) { gslInterpTypeStrings["CONSTANT"] = Interpolate::CONSTANT; gslInterpTypeStrings["LINEAR"] = Interpolate::LINEAR; gslInterpTypeStrings["CUBIC_SPLINE"] = Interpolate::CUBIC_SPLINE; gslInterpTypeStrings["NATURAL_SPLINE"] = Interpolate::NATURAL_SPLINE; gslInterpTypeStrings["CUBIC_SPLINE_PERIODIC"] = Interpolate::CUBIC_SPLINE_PERIODIC; gslInterpTypeStrings["AKIMA_SPLINE"] = Interpolate::AKIMA_SPLINE; gslInterpTypeStrings["AKIMA_SPLINE_PERIODIC"] = Interpolate::AKIMA_SPLINE_PERIODIC; } if ( gslInterpTypeStrings.find(style) == gslInterpTypeStrings.end()) {
280 e231b4bd - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException, "Interp style not found: "+style);
? ^^^^^^ ^
279 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, "Interp style not found: "+style);
? ^^ ^ } return gslInterpTypeStrings[style]; } /** * @brief Get the highest order Interpolation::Style available for 'n' points. */ Interpolate::Style lookupMaxInterpStyle(int const n ///< Number of points ) { if (n < 1) {
291 e231b4bd - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException, "n must be greater than 0");
? ^^^^^^ ^
290 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, "n must be greater than 0");
? ^^ ^ } else if (n > 4) { return Interpolate::AKIMA_SPLINE; } else { static std::vector styles; if (styles.empty()) { styles.resize(5); styles[0] = Interpolate::UNKNOWN; // impossible to reach as we check for n < 1 styles[1] = Interpolate::CONSTANT; styles[2] = Interpolate::LINEAR; styles[3] = Interpolate::CUBIC_SPLINE; styles[4] = Interpolate::CUBIC_SPLINE; } return styles[n]; } }
309 b8578746 - std::vector Interpolate::interpolate(std::vector const& x) const
310 b8578746 - {
311 b8578746 - size_t const num = x.size();
312 b8578746 - std::vector out(num);
313 b8578746 - for (size_t i = 0; i < num; ++i) {
314 b8578746 - out[i] = interpolate(x[i]);
315 b8578746 - }
316 b8578746 - return out;
317 b8578746 - }
318 b8578746 -
319 b8578746 - ndarray::Array Interpolate::interpolate(ndarray::Array const& x) const
320 b8578746 - {
321 b8578746 - int const num = x.getShape()[0];
322 b8578746 - ndarray::Array out = ndarray::allocate(ndarray::makeVector(num));
323 b8578746 - for (size_t i = 0; i < num; ++i) {
324 b8578746 - out[i] = interpolate(x[i]);
325 b8578746 - }
326 b8578746 - return out;
327 b8578746 - }
328 b8578746 -
/** * @brief Get the minimum number of points needed to use the requested interpolation style */ int lookupMinInterpPoints(Interpolate::Style const style ///< The style in question ) { static std::vector minPoints; if (minPoints.empty()) { minPoints.resize(Interpolate::NUM_STYLES); minPoints[Interpolate::CONSTANT] = 1; minPoints[Interpolate::LINEAR] = 2; minPoints[Interpolate::NATURAL_SPLINE] = 3; minPoints[Interpolate::CUBIC_SPLINE] = 3; minPoints[Interpolate::CUBIC_SPLINE_PERIODIC] = 3; minPoints[Interpolate::AKIMA_SPLINE] = 5; minPoints[Interpolate::AKIMA_SPLINE_PERIODIC] = 5; } if (style >= 0 && style < Interpolate::NUM_STYLES) { return minPoints[style]; } else {
349 e231b4bd - throw LSST_EXCEPT(pex::exceptions::OutOfRangeException,
? ^^^^^^ ^
328 21597d88 + throw LSST_EXCEPT(pex::exceptions::OutOfRangeError,
? ^^ ^ str(boost::format("Style %d is out of range 0..%d") % style % (Interpolate::NUM_STYLES - 1))); } } /************************************************************************************************************/ /** * Base class ctor. Note that we should use rvalue references when * available as the vectors in xy will typically be movable (although the * returned-value-optimisation might suffice for the cases we care about) * * \note this is here, not in the .h file, so as to permit the compiler * to avoid copying those vectors */ Interpolate::Interpolate( std::pair, std::vector > const xy, ///< pair (x,y) where /// x are the ordinates of points and y are the values at x[] Interpolate::Style const style ///< desired interpolator ) : _x(xy.first), _y(xy.second), _style(style) { ; } /** * A factory function to make Interpolate objects */ PTR(Interpolate) makeInterpolate(std::vector const &x, ///< the x-values of points std::vector const &y, ///< the values at x[] Interpolate::Style const style ///< desired interpolator ) { switch (style) { case Interpolate::CONSTANT: return PTR(Interpolate)(new InterpolateConstant(x, y, style)); default: // use GSL return PTR(Interpolate)(new InterpolateGsl(x, y, style)); } }
389 b8578746 - PTR(Interpolate) makeInterpolate(ndarray::Array const &x,
390 b8578746 - ndarray::Array const &y,
391 b8578746 - Interpolate::Style const style)
392 b8578746 - {
393 b8578746 - return makeInterpolate(std::vector(x.begin(), x.end()), std::vector(y.begin(), y.end()),
394 b8578746 - style);
395 b8578746 - }
396 b8578746 -
}}}

Return to list

Commits in /Users/nate/repos_hsc/afw/

42e36cd1

commit 42e36cd191dab0579a0c9bf22430fcd4328dae01
Author: Robert Lupton the Good 
Date:   Wed Mar 6 21:49:29 2013 -0500

    This isn't really a memory problem

e231b4bd

commit e231b4bd527250b31d18125eddb8947d49e41b7b
Author: Robert Lupton the Good 
Date:   Wed Mar 6 21:48:41 2013 -0500

    We're in the lsst namespace
    
    The only change in this changeset is to clean up the exception naming

b8578746

commit b8578746d69920bc1e1089cca4b4acb230f0e8d5
Author: Paul Price 
Date:   Mon Feb 24 11:25:36 2014 -0500

    Interpolate: add support for ndarray

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

examples/catTables.py

Diff:

                #!/usr/bin/env python
                
                import sys
                import lsst.afw.table as afwTable
                
6 8484cc8a - def readCatalog(catalog):
7 8484cc8a - """Read a catalog into memory"""
8 8484cc8a - return afwTable.BaseCatalog.readFits(catalog) if isinstance(catalog, basestring) else catalog
7 208700cb + def concatenate(catalogList):
8 208700cb + """Concatenate multiple catalogs (FITS tables from lsst.afw.table)"""
9 208700cb + catalogList = [afwTable.BaseCatalog.readFits(c) if isinstance(c, basestring) else c for c in catalogList]
10 8484cc8a - def getCatalogRows(catalog, hdu=1):
11 8484cc8a - """Return number of rows in a catalog"""
12 8484cc8a - if not isinstance(catalog, basestring):
13 8484cc8a - return len(catalog)
14 8484cc8a - try:
15 8484cc8a - # I believe this is significantly faster than reading the whole thing
16 8484cc8a - import pyfits
17 8484cc8a - fits = pyfits.open(catalog)
18 8484cc8a - try:
19 8484cc8a - rows = len(fits[hdu].data)
20 8484cc8a - return rows
21 8484cc8a - finally:
22 8484cc8a - fits.close()
23 8484cc8a - except ImportError:
24 8484cc8a - # We have to read the whole thing just to get the length
25 8484cc8a - return len(afwTable.BaseCatalog.readFits(catalog))
27 8484cc8a - def concatenate(catalogList, doPreallocate=True):
28 208700cb - """Concatenate multiple catalogs (FITS tables from lsst.afw.table)"""
29 208700cb -
30 8484cc8a - if doPreallocate:
31 8484cc8a - num = sum(getCatalogRows(cat) for cat in catalogList)
32 8484cc8a - print "%d rows from %d catalogs" % (num, len(catalogList))
33 8484cc8a -
34 8484cc8a - cat = readCatalog(catalogList[0])
35 8484cc8a - schema = cat.schema
11 208700cb + schema = catalogList[0].schema
? +++++++++++
12 208700cb + for i, c in enumerate(catalogList[1:]):
13 208700cb + if c.schema != schema:
14 208700cb + raise RuntimeError("Schema for catalog %d not consistent" % (i+1))
out = afwTable.BaseCatalog(schema)
38 8484cc8a - table = out.table
17 208700cb + num = reduce(lambda n, c: n + len(c), catalogList, 0)
18 208700cb + out.preallocate(num)
40 8484cc8a - if doPreallocate:
41 8484cc8a - table.preallocate(num)
42 8484cc8a - out.reserve(num)
43 8484cc8a -
44 8484cc8a - for i, cat in enumerate(catalogList):
? --- ---------- -
20 208700cb + for catalog in catalogList:
? ++++
45 8484cc8a - print cat
46 8484cc8a - cat = readCatalog(cat)
47 8484cc8a - if cat.schema != schema:
48 8484cc8a - raise RuntimeError("Schema for catalog %d not consistent" % (i+1))
49 8484cc8a - for record in cat:
21 208700cb + for record in catalog:
? ++++
50 8484cc8a - out.append(table.copyRecord(record))
22 208700cb + out.append(out.table.copyRecord(record))
? ++++
51 8484cc8a - del cat
return out if __name__ == "__main__": if len(sys.argv) < 4: print "catTables.py: Concatenate multiple FITS tables (catalogs) from lsst.afw.table" print "Usage: catTables.py OUT IN1 IN2 [IN3...]" sys.exit(1) outName = sys.argv[1] catalogList = sys.argv[2:] out = concatenate(catalogList) out.writeFits(outName)

Return to list

Commits in /Users/nate/repos_hsc/afw/

208700cb

commit 208700cb492ea968908999d5b37940436dc7cc2b
Author: Paul Price 
Date:   Thu May 17 15:27:03 2012 -0400

    Add script to concatenate multiple catalogs (FITS tables from lsst.afw.table).

8484cc8a

commit 8484cc8a6a06104dc9258dc978bb6e22f195d828
Author: Paul Price 
Date:   Fri May 31 14:09:46 2013 -0400

    catTables: don't read all catalogs into memory at once
    
    We still need the total number of rows so we can preallocate the
    output catalog; otherwise the continual reallocating causes the
    memory to grow out of control.  Count the number of rows using
    pyfits if available; otherwise we have to read everything twice.

Commits in /Users/nate/repos_lsst/afw/

208700cb

commit 208700cb492ea968908999d5b37940436dc7cc2b
Author: Paul Price 
Date:   Thu May 17 15:27:03 2012 -0400

    Add script to concatenate multiple catalogs (FITS tables from lsst.afw.table).

Return to list

tests/footprint1.py

Diff:

1 f8edfe90 - #!/usr/bin/env python
1 b80fe1d3 + #!/usr/bin/env python2
? +
2 b80fe1d3 + from __future__ import absolute_import, division
# # LSST Data Management System
5 a6d55f08 - # Copyright 2008, 2009, 2010 LSST Corporation.
? ^^^^^^^^ ^
6 c839d0f2 + # Copyright 2008-2015 LSST Corporation.
? ^ ^ # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Footprints, and FootprintSets Run with: footprint1.py or python >>> import footprint1; footprint1.run() """
35 4dda63e9 - import os
import math, sys import unittest import numpy
39 f8edfe90 - import lsst.utils.tests as tests
39 c605dfcd + import lsst.utils.tests as utilsTests
? + ++++ import lsst.pex.logging as logging import lsst.pex.exceptions as pexExcept import lsst.afw.geom as afwGeom import lsst.afw.geom.ellipses as afwGeomEllipses import lsst.afw.coord as afwCoord import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.detection as afwDetect import lsst.afw.detection.utils as afwDetectUtils import lsst.afw.display.ds9 as ds9 import lsst.afw.display.utils as displayUtils try: type(verbose) except NameError: verbose = 0 logging.Debug("afwDetect.Footprint", verbose) try: type(display) except NameError: display = False def toString(*args): """toString written in python""" if len(args) == 1: args = args[0] y, x0, x1 = args return "%d: %d..%d" % (y, x0, x1) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class Object(object):
74 c902c475 - def __init__(self, val, spans):
? ------------
74 c839d0f2 + def __init__(self, val, spans):
self.val = val self.spans = spans def __str__(self): return ", ".join([str(s) for s in self.spans]) def insert(self, im): """Insert self into an image""" for sp in self.spans: y, x0, x1 = sp for x in range(x0, x1+1): im.set(x, y, self.val) def __eq__(self, other): for osp, sp in zip(other.getSpans(), self.spans): if osp.toString() != toString(sp): return False return True #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class SpanTestCase(unittest.TestCase): def testLessThan(self): span1 = afwDetect.Span(42, 0, 100); span2 = afwDetect.Span(41, 0, 100); span3 = afwDetect.Span(43, 0, 100); span4 = afwDetect.Span(42, -100, 100); span5 = afwDetect.Span(42, 100, 200); span6 = afwDetect.Span(42, 0, 10); span7 = afwDetect.Span(42, 0, 200); span8 = afwDetect.Span(42, 0, 100); def assertOrder(x1, x2): self.assertTrue(x1 < x2) self.assertFalse(x2 < x1) assertOrder(span2, span1) assertOrder(span1, span3) assertOrder(span4, span1) assertOrder(span1, span5) assertOrder(span6, span1) assertOrder(span1, span7) self.assertFalse(span1 < span8) self.assertFalse(span8 < span1) class ThresholdTestCase(unittest.TestCase): def testThresholdFactory(self): """ Test the creation of a Threshold object This is a white-box test. -tests missing parameters -tests mal-formed parameters """ try: afwDetect.createThreshold(3.4) except: self.fail("Failed to build Threshold with proper parameters")
135 63a74dc6 -
135 c839d0f2 +
try: afwDetect.createThreshold(3.4, "foo bar") except: pass else: self.fail("Threhold parameters not properly validated") try: afwDetect.createThreshold(3.4, "variance") except: self.fail("Failed to build Threshold with proper parameters") try: afwDetect.createThreshold(3.4, "stdev") except: self.fail("Failed to build Threshold with proper parameters") try: afwDetect.createThreshold(3.4, "value") except: self.fail("Failed to build Threshold with proper parameters")
157 5adfee0e -
157 c839d0f2 +
try: afwDetect.createThreshold(3.4, "value", False) except: self.fail("Failed to build Threshold with VALUE, False parameters") try: afwDetect.createThreshold(0x4, "bitmask") except: self.fail("Failed to build Threshold with BITMASK parameters")
167 5adfee0e -
167 c839d0f2 +
try: afwDetect.createThreshold(5, "pixel_stdev") except: self.fail("Failed to build Threshold with PIXEL_STDEV parameters")
172 5390e1df -
172 c839d0f2 +
173 5d1934cc - class FootprintTestCase(tests.TestCase):
173 c605dfcd + class FootprintTestCase(utilsTests.TestCase):
? + ++++ """A test case for Footprint""" def setUp(self): self.foot = afwDetect.Footprint() def tearDown(self): del self.foot def testToString(self): y, x0, x1 = 10, 100, 101 s = afwDetect.Span(y, x0, x1) self.assertEqual(s.toString(), toString(y, x0, x1)) def testGC(self): """Check that Footprints are automatically garbage collected (when MemoryTestCase runs)"""
188 f8edfe90 -
188 c839d0f2 +
f = afwDetect.Footprint() def testId(self): """Test uniqueness of IDs"""
193 f8edfe90 -
self.assertNotEqual(self.foot.getId(), afwDetect.Footprint().getId()) def testIntersectMask(self): bbox = afwGeom.BoxI(afwGeom.PointI(0,0), afwGeom.ExtentI(10)) fp = afwDetect.Footprint(bbox) maskBBox = afwGeom.BoxI(bbox) maskBBox.grow(-2) mask = afwImage.MaskU(maskBBox) innerBBox = afwGeom.BoxI(maskBBox) innerBBox.grow(-2)
204 5cdd6a3d - subMask = mask.Factory(mask, innerBBox, afwImage.PARENT)
? -----------------
203 93994d54 + subMask = mask.Factory(mask, innerBBox)
subMask.set(1) fp.intersectMask(mask) fpBBox = fp.getBBox() self.assertEqual(fpBBox.getMinX(), maskBBox.getMinX()) self.assertEqual(fpBBox.getMinY(), maskBBox.getMinY()) self.assertEqual(fpBBox.getMaxX(), maskBBox.getMaxX()) self.assertEqual(fpBBox.getMaxY(), maskBBox.getMaxY()) self.assertEqual(fp.getArea(), maskBBox.getArea() - innerBBox.getArea()) def testTablePersistence(self): ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(8, 6, 0.25), afwGeom.Point2D(9,15)) fp1 = afwDetect.Footprint(ellipse) fp1.addPeak(6, 7, 2) fp1.addPeak(8, 9, 3)
221 4dda63e9 - filename = "testFootprintTablePersistence.fits"
220 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
222 4dda63e9 - fp1.writeFits(filename)
? ^ ----
221 c605dfcd + fp1.writeFits(tmpFile)
? ++++ ^^^^
223 4dda63e9 - fp2 = afwDetect.Footprint.readFits(filename)
? ^ ----
222 c605dfcd + fp2 = afwDetect.Footprint.readFits(tmpFile)
? ++++ ^^^^
224 4dda63e9 - self.assertEqual(fp1.getArea(), fp2.getArea())
223 c605dfcd + self.assertEqual(fp1.getArea(), fp2.getArea())
? ++++
225 4dda63e9 - self.assertEqual(list(fp1.getSpans()), list(fp2.getSpans()))
224 c605dfcd + self.assertEqual(list(fp1.getSpans()), list(fp2.getSpans()))
? ++++
225 c605dfcd + # can't use Peak operator== for comparison because it compares IDs, not positions/values
226 e0d7f5b9 - self.assertEqual(len(fp1.getPeaks()), len(fp2.getPeaks()))
226 c605dfcd + self.assertEqual(len(fp1.getPeaks()), len(fp2.getPeaks()))
? ++++
227 e0d7f5b9 - for peak1, peak2 in zip(fp1.getPeaks(), fp2.getPeaks()):
227 c605dfcd + for peak1, peak2 in zip(fp1.getPeaks(), fp2.getPeaks()):
? ++++
228 e0d7f5b9 - self.assertEqual(peak1.getIx(), peak2.getIx())
228 c605dfcd + self.assertEqual(peak1.getIx(), peak2.getIx())
? ++++
229 e0d7f5b9 - self.assertEqual(peak1.getIy(), peak2.getIy())
229 c605dfcd + self.assertEqual(peak1.getIy(), peak2.getIy())
? ++++
230 e0d7f5b9 - self.assertEqual(peak1.getFx(), peak2.getFx())
230 c605dfcd + self.assertEqual(peak1.getFx(), peak2.getFx())
? ++++
231 e0d7f5b9 - self.assertEqual(peak1.getFy(), peak2.getFy())
231 c605dfcd + self.assertEqual(peak1.getFy(), peak2.getFy())
? ++++
232 e0d7f5b9 - self.assertEqual(peak1.getPeakValue(), peak2.getPeakValue())
232 c605dfcd + self.assertEqual(peak1.getPeakValue(), peak2.getPeakValue())
? ++++
233 4dda63e9 - os.remove(filename)
def testAddSpans(self): """Add spans to a Footprint""" for y, x0, x1 in [(10, 100, 105), (11, 99, 104)]: self.foot.addSpan(y, x0, x1) sp = self.foot.getSpans()
241 f8edfe90 -
240 c839d0f2 +
self.assertEqual(sp[-1].toString(), toString(y, x0, x1)) def testBbox(self): """Add Spans and check bounding box""" foot = afwDetect.Footprint() for y, x0, x1 in [(10, 100, 105), (11, 99, 104)]: foot.addSpan(y, x0, x1) bbox = foot.getBBox() self.assertEqual(bbox.getWidth(), 7) self.assertEqual(bbox.getHeight(), 2) self.assertEqual(bbox.getMinX(), 99) self.assertEqual(bbox.getMinY(), 10) self.assertEqual(bbox.getMaxX(), 105) self.assertEqual(bbox.getMaxY(), 11) # clip with a bbox that doesn't overlap at all bbox2 = afwGeom.Box2I(afwGeom.Point2I(5, 90), afwGeom.Extent2I(1, 2)) foot.clipTo(bbox2) self.assert_(foot.getBBox().isEmpty()) self.assertEqual(foot.getArea(), 0) def testSpanShift(self): """Test our ability to shift spans"""
266 90219c90 -
span = afwDetect.Span(10, 100, 105) foot = afwDetect.Footprint() foot.addSpan(span, 1, 2) bbox = foot.getBBox() self.assertEqual(bbox.getWidth(), 6) self.assertEqual(bbox.getHeight(), 1) self.assertEqual(bbox.getMinX(), 101) self.assertEqual(bbox.getMinY(), 12) # # Shift that span using Span.shift # foot = afwDetect.Footprint() span.shift(-1, -2) foot.addSpan(span) bbox = foot.getBBox() self.assertEqual(bbox.getWidth(), 6) self.assertEqual(bbox.getHeight(), 1) self.assertEqual(bbox.getMinX(), 99) self.assertEqual(bbox.getMinY(), 8) def testFootprintFromBBox1(self): """Create a rectangular Footprint""" x0, y0, w, h = 9, 10, 7, 4 foot = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(w, h))) bbox = foot.getBBox() self.assertEqual(bbox.getWidth(), w) self.assertEqual(bbox.getHeight(), h) self.assertEqual(bbox.getMinX(), x0) self.assertEqual(bbox.getMinY(), y0) self.assertEqual(bbox.getMaxX(), x0 + w - 1) self.assertEqual(bbox.getMaxY(), y0 + h - 1)
304 f8edfe90 -
305 f8edfe90 -
if False: idImage = afwImage.ImageU(w, h)
308 17d1d529 - idImage.set(0)
? --------
304 c839d0f2 + idImage.set(0)
foot.insertIntoImage(idImage, foot.getId(), bbox) ds9.mtv(idImage, frame=2) def testGetBBox(self): """Check that Footprint.getBBox() returns a copy"""
314 92c7d358 -
x0, y0, w, h = 9, 10, 7, 4 foot = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(w, h))) bbox = foot.getBBox() dx, dy = 10, 20 bbox.shift(afwGeom.Extent2I(dx, dy)) self.assertEqual(bbox.getMinX(), x0 + dx) self.assertEqual(foot.getBBox().getMinX(), x0) def testFootprintFromCircle(self): """Create an elliptical Footprint"""
327 f8edfe90 -
328 46f3a3a0 - ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(6, 6, 0),
322 c839d0f2 + ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(6, 6, 0), afwGeom.Point2D(9,15))
? ++++++++++++++++++++++
329 20c2c467 - afwGeom.Point2D(9,15))
330 3263f939 - foot = afwDetect.Footprint(
331 3263f939 - ellipse,
332 c9c89e06 - afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(20, 30)))
? ^^^^^^^
323 c839d0f2 + foot = afwDetect.Footprint(ellipse, afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(20, 30)))
? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ idImage = afwImage.ImageU(afwGeom.Extent2I(foot.getRegion().getWidth(), foot.getRegion().getHeight())) idImage.set(0)
336 f8edfe90 -
327 c839d0f2 +
foot.insertIntoImage(idImage, foot.getId()) if False: ds9.mtv(idImage, frame=2) def testFootprintFromEllipse(self): """Create an elliptical Footprint"""
344 102a5edd -
cen = afwGeom.Point2D(23, 25) a, b, theta = 25, 15, 30 ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(a, b, math.radians(theta)), cen)
348 102a5edd - foot = afwDetect.Footprint(
349 102a5edd - ellipse,
350 102a5edd - afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(50, 60)))
? ^^^^^^^
338 c839d0f2 + foot = afwDetect.Footprint(ellipse, afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(50, 60)))
? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ idImage = afwImage.ImageU(afwGeom.Extent2I(foot.getRegion().getWidth(), foot.getRegion().getHeight())) idImage.set(0)
354 102a5edd -
342 c839d0f2 +
foot.insertIntoImage(idImage, foot.getId()) if display: ds9.mtv(idImage, frame=2) displayUtils.drawFootprint(foot, frame=2)
360 102a5edd - shape = foot.getShape(cen)
? ---
348 97c3b722 + shape = foot.getShape()
shape.scale(2) # = 1/2 for a disk ds9.dot(shape, *cen, frame=2, ctype=ds9.RED) shape = foot.getShape() shape.scale(2) # = 1/2 for a disk ds9.dot(shape, *cen, frame=2, ctype=ds9.MAGENTA) axes = afwGeom.ellipses.Axes(foot.getShape()) axes.scale(2) # = 1/2 for a disk
370 102a5edd -
358 c839d0f2 +
self.assertEqual(foot.getCentroid(), cen) self.assertTrue(abs(a - axes.getA()) < 0.15, "a: %g v. %g" % (a, axes.getA())) self.assertTrue(abs(b - axes.getB()) < 0.02, "b: %g v. %g" % (b, axes.getB())) self.assertTrue(abs(theta - math.degrees(axes.getTheta())) < 0.2, "theta: %g v. %g" % (theta, math.degrees(axes.getTheta()))) def testCopy(self): bbox = afwGeom.BoxI(afwGeom.PointI(0,2), afwGeom.PointI(5,6)) fp = afwDetect.Footprint(bbox, bbox) #test copy construct fp2 = afwDetect.Footprint(fp) self.assertEqual(fp2.getBBox(), bbox) self.assertEqual(fp2.getRegion(), bbox) self.assertEqual(fp2.getArea(), bbox.getArea()) self.assertEqual(fp2.isNormalized(), True) y = bbox.getMinY() for s in fp2.getSpans(): self.assertEqual(s.getY(), y) self.assertEqual(s.getX0(), bbox.getMinX()) self.assertEqual(s.getX1(), bbox.getMaxX()) y+=1
396 b635df09 -
384 c839d0f2 +
#test assignment fp3 = afwDetect.Footprint() fp3.assign(fp) self.assertEqual(fp3.getBBox(), bbox) self.assertEqual(fp3.getRegion(), bbox) self.assertEqual(fp3.getArea(), bbox.getArea()) self.assertEqual(fp3.isNormalized(), True) y = bbox.getMinY() for s in fp3.getSpans(): self.assertEqual(s.getY(), y) self.assertEqual(s.getX0(), bbox.getMinX()) self.assertEqual(s.getX1(), bbox.getMaxX()) y+=1
400 ae20e2b5 + def testShrink(self):
401 ae20e2b5 + width, height = 5, 10 # Size of footprint
402 ae20e2b5 + x0, y0 = 50, 50 # Position of footprint
403 ae20e2b5 + imwidth, imheight = 100, 100 # Size of image
404 ae20e2b5 +
405 ae20e2b5 + foot = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(width, height)),
406 ecb01ab8 + afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(imwidth, imheight)))
407 ae20e2b5 + self.assertEqual(foot.getNpix(), width*height)
408 ae20e2b5 +
409 ecb01ab8 + # Add some peaks to the original footprint and check that those lying outside
410 ecb01ab8 + # the shrunken footprint are omitted from the returned shrunken footprint.
411 ecb01ab8 + foot.addPeak(50, 50, 1) # should be omitted in shrunken footprint
412 ecb01ab8 + foot.addPeak(52, 52, 2) # should be kept in shrunken footprint
413 ecb01ab8 + foot.addPeak(50, 59, 3) # should be omitted in shrunken footprint
414 ecb01ab8 + self.assertEqual(len(foot.getPeaks()), 3) # check that all three peaks were added
415 ecb01ab8 +
416 ae20e2b5 + # Shrinking by one pixel makes each dimension *two* pixels shorter.
417 ae20e2b5 + shrunk = afwDetect.shrinkFootprint(foot, 1, True)
418 ae20e2b5 + self.assertEqual(3*8, shrunk.getNpix())
419 ae20e2b5 +
420 ecb01ab8 + # Shrunken footprint should now only contain one peak at (52, 52)
421 ecb01ab8 + self.assertEqual(len(shrunk.getPeaks()), 1)
422 ecb01ab8 + peak = shrunk.getPeaks()[0]
423 ecb01ab8 + self.assertEqual((peak.getIx(), peak.getIy()), (52, 52))
424 ecb01ab8 +
425 ae20e2b5 + # Without shifting the centroid
426 ae20e2b5 + self.assertEqual(shrunk.getCentroid(), foot.getCentroid())
427 ae20e2b5 +
428 ae20e2b5 + # Get the same result from a Manhattan shrink
429 ae20e2b5 + shrunk = afwDetect.shrinkFootprint(foot, 1, False)
430 ae20e2b5 + self.assertEqual(3*8, shrunk.getNpix())
431 ae20e2b5 + self.assertEqual(shrunk.getCentroid(), foot.getCentroid())
432 ae20e2b5 +
433 ae20e2b5 + # Shrinking by a large amount leaves nothing.
434 ae20e2b5 + self.assertEqual(afwDetect.shrinkFootprint(foot, 100, True).getNpix(), 0)
435 ae20e2b5 +
436 ae20e2b5 + def testShrinkIsoVsManhattan(self):
437 ae20e2b5 + # Demonstrate that isotropic and Manhattan shrinks are different.
438 ae20e2b5 + radius = 8
439 ae20e2b5 + imwidth, imheight = 100, 100
440 ae20e2b5 + x0, y0 = imwidth//2, imheight//2
441 ae20e2b5 + nshrink = 4
442 ae20e2b5 +
443 ae20e2b5 + ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(1.5*radius, 2*radius, 0),
444 ae20e2b5 + afwGeom.Point2D(x0,y0))
445 ae20e2b5 + foot = afwDetect.Footprint(ellipse, afwGeom.Box2I(afwGeom.Point2I(0, 0),
446 ae20e2b5 + afwGeom.Extent2I(imwidth, imheight)))
447 ae20e2b5 + self.assertNotEqual(afwDetect.shrinkFootprint(foot, nshrink, False),
448 ae20e2b5 + afwDetect.shrinkFootprint(foot, nshrink, True))
449 ae20e2b5 +
450 ae20e2b5 + def _fig8Test(self, x1, y1, x2, y2):
451 ad62cd6e + # Construct a "figure of 8" consisting of two circles touching at the
452 ad62cd6e + # centre of an image, then demonstrate that it shrinks correctly.
453 ae20e2b5 + # (Helper method for tests below.)
454 ad62cd6e + radius = 3
455 ad62cd6e + imwidth, imheight = 100, 100
456 ad62cd6e + nshrink = 1
457 ad62cd6e +
458 ad62cd6e + # These are the correct values for footprint sizes given the paramters
459 ad62cd6e + # above.
460 ad62cd6e + circle_npix = 29
461 ad62cd6e + initial_npix = circle_npix * 2 - 1 # touch at one pixel
462 ad62cd6e + shrunk_npix = 26
463 ad62cd6e +
464 ad62cd6e + box = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(imwidth, imheight))
465 ad62cd6e +
466 ad62cd6e + e1 = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(radius, radius, 0),
467 ad62cd6e + afwGeom.Point2D(x1, y1))
468 ad62cd6e + f1 = afwDetect.Footprint(e1,box)
469 ad62cd6e + self.assertEqual(f1.getNpix(), circle_npix)
470 ad62cd6e +
471 ad62cd6e + e2 = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(radius, radius, 0),
472 ad62cd6e + afwGeom.Point2D(x2, y2))
473 ad62cd6e + f2 = afwDetect.Footprint(e2,box)
474 ad62cd6e + self.assertEqual(f2.getNpix(), circle_npix)
475 ad62cd6e +
476 ad62cd6e + initial = afwDetect.mergeFootprints(f1, f2)
477 ad62cd6e + initial.setRegion(f2.getRegion()) # merge does not propagate the region
478 ad62cd6e + self.assertEqual(initial_npix, initial.getNpix())
479 ad62cd6e +
480 ae20e2b5 + shrunk = afwDetect.shrinkFootprint(initial, nshrink, True)
481 ad62cd6e + self.assertEqual(shrunk_npix, shrunk.getNpix())
482 ad62cd6e +
483 ad62cd6e + if display:
484 ad62cd6e + idImage = afwImage.ImageU(imwidth, imheight)
485 ad62cd6e + for i, foot in enumerate([initial, shrunk]):
486 ad62cd6e + print foot.getNpix()
487 ad62cd6e + foot.insertIntoImage(idImage, i+1);
488 ad62cd6e + ds9.mtv(idImage)
489 ad62cd6e +
490 ad62cd6e + def testShrinkEightVertical(self):
491 ad62cd6e + # Test a "vertical" figure of 8.
492 ad62cd6e + radius = 3
493 ad62cd6e + imwidth, imheight = 100, 100
494 ae20e2b5 + self._fig8Test(imwidth//2, imheight//2-radius, imwidth//2, imheight//2+radius)
495 ad62cd6e +
496 ad62cd6e + def testShrinkEightHorizontal(self):
497 ad62cd6e + # Test a "horizontal" figure of 8.
498 ad62cd6e + radius = 3
499 ad62cd6e + imwidth, imheight = 100, 100
500 ae20e2b5 + self._fig8Test(imwidth//2-radius, imheight//2, imwidth//2+radius, imheight//2)
def testGrow(self): """Test growing a footprint""" x0, y0 = 20, 20 width, height = 20, 30 foot1 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(width, height)), afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(100, 100)))
508 ecb01ab8 +
509 ecb01ab8 + # Add some peaks and check that they get copied into the new grown footprint
510 ecb01ab8 + foot1.addPeak(20, 20, 1)
511 ecb01ab8 + foot1.addPeak(30, 35, 2)
512 ecb01ab8 + foot1.addPeak(25, 45, 3)
513 ecb01ab8 + self.assertEqual(len(foot1.getPeaks()), 3)
514 ecb01ab8 +
bbox1 = foot1.getBBox() self.assertEqual(bbox1.getMinX(), x0) self.assertEqual(bbox1.getMaxX(), x0 + width - 1) self.assertEqual(bbox1.getWidth(), width) self.assertEqual(bbox1.getMinY(), y0) self.assertEqual(bbox1.getMaxY(), y0 + height - 1) self.assertEqual(bbox1.getHeight(), height) ngrow = 5 for isotropic in (True, False): foot2 = afwDetect.growFootprint(foot1, ngrow, isotropic)
528 ecb01ab8 +
529 ca6bfc5f + # Check that the grown footprint is normalized
530 ca6bfc5f + self.assertTrue(foot2.isNormalized())
531 ca6bfc5f +
532 ca6bfc5f + # Check that the grown footprint is bigger than the original
533 ca6bfc5f + self.assertGreater(foot2.getArea(), foot1.getArea())
534 ca6bfc5f +
535 ecb01ab8 + # Check that peaks got copied into grown footprint
536 ecb01ab8 + self.assertEqual(len(foot2.getPeaks()), 3)
537 ecb01ab8 + for peak in foot2.getPeaks():
538 ecb01ab8 + self.assertTrue((peak.getIx(), peak.getIy()) in [(20, 20), (30, 35), (25, 45)])
539 ecb01ab8 +
bbox2 = foot2.getBBox() if False and display: idImage = afwImage.ImageU(width, height) idImage.set(0) i = 1 for foot in [foot1, foot2]: foot.insertIntoImage(idImage, i) i += 1 metricImage = afwImage.ImageF("foo.fits") ds9.mtv(metricImage, frame=1) ds9.mtv(idImage) # check bbox2 self.assertEqual(bbox2.getMinX(), x0 - ngrow) self.assertEqual(bbox2.getWidth(), width + 2*ngrow) self.assertEqual(bbox2.getMinY(), y0 - ngrow) self.assertEqual(bbox2.getHeight(), height + 2*ngrow) # Check that region was preserved self.assertEqual(foot1.getRegion(), foot2.getRegion()) def testFootprintToBBoxList(self): """Test footprintToBBoxList""" region = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(12,10)) foot = afwDetect.Footprint(0, region) for y, x0, x1 in [(3, 3, 5), (3, 7, 7), (4, 2, 3), (4, 5, 7), (5, 2, 3), (5, 5, 8),
463 a716b827 - (6, 3, 5),
? -
571 c839d0f2 + (6, 3, 5),
]: foot.addSpan(y, x0, x1)
466 17d1d529 -
574 c839d0f2 +
idImage = afwImage.ImageU(region.getDimensions()) idImage.set(0) foot.insertIntoImage(idImage, 1) if display: ds9.mtv(idImage) idImageFromBBox = idImage.Factory(idImage, True) idImageFromBBox.set(0) bboxes = afwDetect.footprintToBBoxList(foot) for bbox in bboxes: x0, y0, x1, y1 = bbox.getMinX(), bbox.getMinY(), bbox.getMaxX(), bbox.getMaxY() for y in range(y0, y1 + 1): for x in range(x0, x1 + 1): idImageFromBBox.set(x, y, 1) if display: x0 -= 0.5 y0 -= 0.5 x1 += 0.5 y1 += 0.5 ds9.line([(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)], ctype=ds9.RED) idImageFromBBox -= idImage # should be blank stats = afwMath.makeStatistics(idImageFromBBox, afwMath.MAX) self.assertEqual(stats.getValue(), 0) def testWriteDefect(self): """Write a Footprint as a set of Defects""" region = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(12,10)) foot = afwDetect.Footprint(0, region) for y, x0, x1 in [(3, 3, 5), (3, 7, 7), (4, 2, 3), (4, 5, 7), (5, 2, 3), (5, 5, 8),
504 0d3a98b4 - (6, 3, 5),
? -
612 c839d0f2 + (6, 3, 5),
]: foot.addSpan(y, x0, x1)
507 0d3a98b4 -
615 c839d0f2 +
if True: fd = open("/dev/null", "w") else: fd = sys.stdout
512 ce2846bf -
620 c839d0f2 +
afwDetectUtils.writeFootprintAsDefects(fd, foot) def testNormalize(self): """Test Footprint.normalize"""
518 6b20a59c -
519 17d1d529 -
w, h = 12, 10 region = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(w,h)) im = afwImage.ImageU(afwGeom.Extent2I(w, h)) im.set(0) # # Create a footprint; note that these Spans overlap # for spans, box in (([(3, 5, 6), (4, 7, 7), ], afwGeom.Box2I(afwGeom.Point2I(5,3), afwGeom.Point2I(7,4))), ([(3, 3, 5), (3, 6, 9), (4, 2, 3), (4, 5, 7), (4, 8, 8), (5, 2, 3), (5, 5, 8), (5, 6, 7),
532 38eea4c1 - (6, 3, 5),
? -
638 c839d0f2 + (6, 3, 5),
], afwGeom.Box2I(afwGeom.Point2I(2,3), afwGeom.Point2I(9,6))) ): foot = afwDetect.Footprint(0, region) for y, x0, x1 in spans: foot.addSpan(y, x0, x1) for x in range(x0, x1 + 1): # also insert into im im.set(x, y, 1) idImage = afwImage.ImageU(afwGeom.Extent2I(w, h)) idImage.set(0) foot.insertIntoImage(idImage, 1) if display: # overlaping pixels will be > 1 ds9.mtv(idImage) # # Normalise the Footprint, removing overlapping spans # foot.normalize() idImage.set(0) foot.insertIntoImage(idImage, 1) if display: ds9.mtv(idImage, frame=1) idImage -= im self.assertTrue(box == foot.getBBox()) self.assertEqual(afwMath.makeStatistics(idImage, afwMath.MAX).getValue(), 0) def testSetFromFootprint(self): """Test setting mask/image pixels from a Footprint list"""
566 c902c475 -
mi = afwImage.MaskedImageF(afwGeom.Extent2I(12, 8)) im = mi.getImage() # # Objects that we should detect # self.objects = [] self.objects += [Object(10, [(1, 4, 4), (2, 3, 5), (3, 4, 4)])] self.objects += [Object(20, [(5, 7, 8), (5, 10, 10), (6, 8, 9)])] self.objects += [Object(20, [(6, 3, 3)])] im.set(0) # clear image for obj in self.objects: obj.insert(im) if False and display: ds9.mtv(mi, frame=0) ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(15)) objects = ds.getFootprints() afwDetect.setMaskFromFootprintList(mi.getMask(), objects, 0x1) self.assertEqual(mi.getMask().get(4, 2), 0x0) self.assertEqual(mi.getMask().get(3, 6), 0x1)
591 c902c475 -
696 c839d0f2 +
self.assertEqual(mi.getImage().get(3, 6), 20) afwDetect.setImageFromFootprintList(mi.getImage(), objects, 5.0) self.assertEqual(mi.getImage().get(4, 2), 10) self.assertEqual(mi.getImage().get(3, 6), 5)
596 c902c475 -
701 c839d0f2 +
if display: ds9.mtv(mi, frame=1) # # Check Footprint.contains() while we are about it # self.assertTrue(objects[0].contains(afwGeom.Point2I(7, 5))) self.assertFalse(objects[0].contains(afwGeom.Point2I(10, 6))) self.assertFalse(objects[0].contains(afwGeom.Point2I(7, 6))) self.assertFalse(objects[0].contains(afwGeom.Point2I(4, 2))) self.assertTrue(objects[1].contains(afwGeom.Point2I(3, 6))) def testMakeFootprintSetXY0(self): """Test setting mask/image pixels from a Footprint list"""
611 f24557ac -
mi = afwImage.MaskedImageF(afwGeom.Extent2I(12, 8)) im = mi.getImage() im.set(100) mi.setXY0(afwGeom.PointI(2, 2)) ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(1), "DETECTED") bitmask = mi.getMask().getPlaneBitMask("DETECTED") for y in range(im.getHeight()): for x in range(im.getWidth()): self.assertEqual(mi.getMask().get(x, y), bitmask) def testTransform(self): dims = afwGeom.Extent2I(512, 512) bbox = afwGeom.Box2I(afwGeom.Point2I(0,0), dims) radius = 5 offset = afwGeom.Extent2D(123, 456) crval = afwCoord.Coord(0*afwGeom.degrees, 0*afwGeom.degrees) crpix = afwGeom.Point2D(0, 0) cdMatrix = [1.0e-5, 0.0, 0.0, 1.0e-5] source = afwImage.makeWcs(crval, crpix, *cdMatrix) target = afwImage.makeWcs(crval, crpix + offset, *cdMatrix) fpSource = afwDetect.Footprint(afwGeom.Point2I(12, 34), radius, bbox) fpTarget = fpSource.transform(source, target, bbox) self.assertEqual(len(fpSource.getSpans()), len(fpTarget.getSpans())) self.assertEqual(fpSource.getNpix(), fpTarget.getNpix()) self.assertEqual(fpSource.getArea(), fpTarget.getArea()) imSource = afwImage.ImageU(dims) fpSource.insertIntoImage(imSource, 1) imTarget = afwImage.ImageU(dims) fpTarget.insertIntoImage(imTarget, 1) subSource = imSource.Factory(imSource, fpSource.getBBox()) subTarget = imTarget.Factory(imTarget, fpTarget.getBBox()) self.assertTrue(numpy.all(subSource.getArray() == subTarget.getArray())) # make a bbox smaller than the target footprint bbox2 = afwGeom.Box2I(fpTarget.getBBox()) bbox2.grow(-1) fpTarget2 = fpSource.transform(source, target, bbox2) # this one clips fpTarget3 = fpSource.transform(source, target, bbox2, False) # this one doesn't self.assertTrue(bbox2.contains(fpTarget2.getBBox())) self.assertFalse(bbox2.contains(fpTarget3.getBBox())) self.assertNotEqual(fpTarget.getArea(), fpTarget2.getArea()) self.assertEqual(fpTarget.getArea(), fpTarget3.getArea()) def testCopyWithinFootprintImage(self): W,H = 10,10 dims = afwGeom.Extent2I(W,H) source = afwImage.ImageF(dims) dest = afwImage.ImageF(dims) sa = source.getArray() for i in range(H): for j in range(W): sa[i,j] = 100 * i + j self.foot.addSpan(4, 3, 6) self.foot.addSpan(5, 2, 4) afwDetect.copyWithinFootprintImage(self.foot, source, dest) da = dest.getArray() self.assertEqual(da[4,2], 0) self.assertEqual(da[4,3], 403) self.assertEqual(da[4,4], 404) self.assertEqual(da[4,5], 405) self.assertEqual(da[4,6], 406) self.assertEqual(da[4,7], 0) self.assertEqual(da[5,1], 0) self.assertEqual(da[5,2], 502) self.assertEqual(da[5,3], 503) self.assertEqual(da[5,4], 504) self.assertEqual(da[5,5], 0) self.assertTrue(numpy.all(da[:4,:] == 0)) self.assertTrue(numpy.all(da[6:,:] == 0))
692 76f3706f - def testCopyWithinFootprintOutside(self):
693 76f3706f - """Copy a footprint that is larger than the image"""
694 76f3706f - target = afwImage.ImageF(100, 100)
695 76f3706f - target.set(0)
696 76f3706f - subTarget = afwImage.ImageF(target, afwGeom.Box2I(afwGeom.Point2I(40, 40), afwGeom.Extent2I(20, 20)))
697 76f3706f - source = afwImage.ImageF(10, 30)
698 76f3706f - source.setXY0(45, 45)
699 76f3706f - source.set(1.0)
700 76f3706f -
701 76f3706f - foot = afwDetect.Footprint()
702 76f3706f - foot.addSpan(50, 50, 60) # Oversized on the source image, right; only some pixels overlap
703 76f3706f - foot.addSpan(60, 0, 100) # Oversized on the source, left and right; and on sub-target image, top
704 76f3706f - foot.addSpan(99, 0, 1000) # Oversized on the source image, top, left and right; aiming for segfault
705 76f3706f -
706 76f3706f - afwDetect.copyWithinFootprintImage(foot, source, subTarget)
707 76f3706f -
708 76f3706f - expected = numpy.zeros((100, 100))
709 76f3706f - expected[50,50:55] = 1.0
710 76f3706f -
711 76f3706f - self.assertTrue(numpy.all(target.getArray() == expected))
712 76f3706f -
def testCopyWithinFootprintMaskedImage(self): W,H = 10,10 dims = afwGeom.Extent2I(W,H) source = afwImage.MaskedImageF(dims) dest = afwImage.MaskedImageF(dims) sa = source.getImage().getArray() sv = source.getVariance().getArray() sm = source.getMask().getArray() for i in range(H): for j in range(W): sa[i,j] = 100 * i + j sv[i,j] = 100 * j + i sm[i,j] = 1 self.foot.addSpan(4, 3, 6) self.foot.addSpan(5, 2, 4) afwDetect.copyWithinFootprintMaskedImage(self.foot, source, dest) da = dest.getImage().getArray() dv = dest.getVariance().getArray() dm = dest.getMask().getArray() self.assertEqual(da[4,2], 0) self.assertEqual(da[4,3], 403) self.assertEqual(da[4,4], 404) self.assertEqual(da[4,5], 405) self.assertEqual(da[4,6], 406) self.assertEqual(da[4,7], 0) self.assertEqual(da[5,1], 0) self.assertEqual(da[5,2], 502) self.assertEqual(da[5,3], 503) self.assertEqual(da[5,4], 504) self.assertEqual(da[5,5], 0) self.assertTrue(numpy.all(da[:4,:] == 0)) self.assertTrue(numpy.all(da[6:,:] == 0)) self.assertEqual(dv[4,2], 0) self.assertEqual(dv[4,3], 304) self.assertEqual(dv[4,4], 404) self.assertEqual(dv[4,5], 504) self.assertEqual(dv[4,6], 604) self.assertEqual(dv[4,7], 0) self.assertEqual(dv[5,1], 0) self.assertEqual(dv[5,2], 205) self.assertEqual(dv[5,3], 305) self.assertEqual(dv[5,4], 405) self.assertEqual(dv[5,5], 0) self.assertTrue(numpy.all(dv[:4,:] == 0)) self.assertTrue(numpy.all(dv[6:,:] == 0)) self.assertTrue(numpy.all(dm[4, 3:7] == 1)) self.assertTrue(numpy.all(dm[5, 2:5] == 1)) self.assertTrue(numpy.all(dm[:4,:] == 0)) self.assertTrue(numpy.all(dm[6:,:] == 0)) self.assertTrue(numpy.all(dm[4, :3] == 0)) self.assertTrue(numpy.all(dm[4, 7:] == 0))
771 5d1934cc - def testInclude(self):
772 5d1934cc - """Test that we can expand a Footprint to include its neighbors."""
773 5d1934cc - region = afwGeom.Box2I(afwGeom.Point2I(-6, -6), afwGeom.Point2I(6, 6))
774 5d1934cc - parent = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-2, -2), afwGeom.Point2I(2, 2)), region)
775 6ac35e07 - parent.addPeak(0, 0, float("NaN"))
776 5d1934cc - child1 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-3, 0), afwGeom.Point2I(0, 3)), region)
777 6ac35e07 - child1.addPeak(-1, 1, float("NaN"))
778 5d1934cc - child2 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-4, -3), afwGeom.Point2I(-1, 0)), region)
779 5d1934cc - child3 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(4, -1), afwGeom.Point2I(6, 1)))
780 0d1ab12d - merge123 = afwDetect.Footprint(parent)
781 0d1ab12d - merge123.include([child1, child2, child3])
782 0d1ab12d - self.assertTrue(merge123.getBBox().contains(parent.getBBox()))
783 0d1ab12d - self.assertTrue(merge123.getBBox().contains(child1.getBBox()))
784 0d1ab12d - self.assertTrue(merge123.getBBox().contains(child2.getBBox()))
785 0d1ab12d - self.assertTrue(merge123.getBBox().contains(child3.getBBox()))
786 0d1ab12d - mask123a = afwImage.MaskU(region)
787 0d1ab12d - mask123b = afwImage.MaskU(region)
788 0d1ab12d - afwDetect.setMaskFromFootprint(mask123a, parent, 1)
789 0d1ab12d - afwDetect.setMaskFromFootprint(mask123a, child1, 1)
790 0d1ab12d - afwDetect.setMaskFromFootprint(mask123a, child2, 1)
791 0d1ab12d - afwDetect.setMaskFromFootprint(mask123a, child3, 1)
792 0d1ab12d - afwDetect.setMaskFromFootprint(mask123b, merge123, 1)
793 0d1ab12d - self.assertEqual(mask123a.getArray().sum(), merge123.getArea())
794 0d1ab12d - self.assertClose(mask123a.getArray(), mask123b.getArray(), rtol=0, atol=0)
795 5d1934cc -
796 ddb75eb2 - # Test that ignoreSelf=True works for include
797 ddb75eb2 - ignoreParent = True
798 ddb75eb2 - childOnly = afwDetect.Footprint()
799 ddb75eb2 - childOnly.include([child1, child2, child3])
800 ddb75eb2 - merge123 = afwDetect.Footprint(parent)
801 ddb75eb2 - merge123.include([child1, child2, child3], ignoreParent)
802 ddb75eb2 - maskChildren = afwImage.MaskU(region)
803 ddb75eb2 - mask123 = afwImage.MaskU(region)
804 ddb75eb2 - afwDetect.setMaskFromFootprint(maskChildren, childOnly, 1)
805 ddb75eb2 - afwDetect.setMaskFromFootprint(mask123, merge123, 1)
806 ddb75eb2 - self.assertTrue(numpy.all(maskChildren.getArray() == mask123.getArray()))
807 ddb75eb2 -
def testMergeFootprints(self): f1 = self.foot f2 = afwDetect.Footprint() f1.addSpan(10, 10, 20) f1.addSpan(10, 30, 40) f1.addSpan(10, 50, 60) f1.addSpan(11, 30, 50) f1.addSpan(12, 30, 50) f1.addSpan(13, 10, 20) f1.addSpan(13, 30, 40) f1.addSpan(13, 50, 60) f1.addSpan(15, 10,20) f1.addSpan(15, 31,40) f1.addSpan(15, 51,60) f2.addSpan(8, 10, 20) f2.addSpan(9, 20, 30) f2.addSpan(10, 0, 9) f2.addSpan(10, 35, 65) f2.addSpan(10, 70, 80) f2.addSpan(13, 49, 54) f2.addSpan(14, 10, 30) f2.addSpan(15, 21,30) f2.addSpan(15, 41,50) f2.addSpan(15, 61,70) f1.normalize() f2.normalize() fA = afwDetect.mergeFootprints(f1, f2) fB = afwDetect.mergeFootprints(f2, f1) ims = [] for i,f in enumerate([f1,f2,fA,fB]): im1 = afwImage.ImageU(100, 100) im1.set(0)
850 5016c432 - imbb = im1.getBBox(afwImage.PARENT)
? ---------------
896 93994d54 + imbb = im1.getBBox()
f.setRegion(imbb) f.insertIntoImage(im1, 1) ims.append(im1) for i,merged in enumerate([ims[2],ims[3]]): m = merged.getArray() a1 = ims[0].getArray() a2 = ims[1].getArray() # Slightly looser tests to start... # Every pixel in f1 is in f[AB] self.assertTrue(numpy.all(m.flat[numpy.flatnonzero(a1)] == 1)) # Every pixel in f2 is in f[AB] self.assertTrue(numpy.all(m.flat[numpy.flatnonzero(a2)] == 1)) # merged == a1 | a2. self.assertTrue(numpy.all(m == numpy.maximum(a1, a2))) if False: import matplotlib matplotlib.use('Agg') import pylab as plt plt.clf() for i,im1 in enumerate(ims): plt.subplot(4,1, i+1) plt.imshow(im1.getArray(), interpolation='nearest', origin='lower') plt.axis([0, 100, 0, 20]) plt.savefig('merge2.png')
878 4dface89 - def testPeakSort(self):
879 4dface89 - footprint = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Point2I(10, 10)))
880 4dface89 - footprint.addPeak(4, 5, 1)
881 4dface89 - footprint.addPeak(3, 2, 5)
882 4dface89 - footprint.addPeak(7, 8, -2)
883 4dface89 - footprint.addPeak(5, 7, 4)
884 4dface89 - footprint.sortPeaks()
885 4dface89 - self.assertEqual([peak.getIx() for peak in footprint.getPeaks()],
886 4dface89 - [3, 5, 4, 7])
def testClipToNonzero(self):
889 99dc4b86 -
# create a circular footprint
891 99dc4b86 - ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(6, 6, 0),
927 c839d0f2 + ellipse = afwGeomEllipses.Ellipse(afwGeomEllipses.Axes(6, 6, 0), afwGeom.Point2D(9,15))
? ++++++++++++++++++++++
892 99dc4b86 - afwGeom.Point2D(9,15))
bb = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(20, 30)) foot = afwDetect.Footprint(ellipse, bb) a0 = foot.getArea() plots = False if plots: import matplotlib matplotlib.use('Agg') import pylab as plt
903 99dc4b86 -
938 c839d0f2 +
plt.clf() img = afwImage.ImageU(bb) foot.insertIntoImage(img, 1) ima = dict(interpolation='nearest', origin='lower', cmap='gray') plt.imshow(img.getArray(), **ima) plt.savefig('clipnz1.png') source = afwImage.ImageF(bb) source.getArray()[:,:] = 1. source.getArray()[:,0:10] = 0.
915 99dc4b86 - foot.clipToNonzeroF(source)
? -
950 94770baf + foot.clipToNonzero(source)
foot.normalize() a1 = foot.getArea()
918 25e434a1 - self.assertTrue(a1 < a0)
? ^^^ ^^
953 94770baf + self.assertLess(a1, a0)
? ^ ++ ^ img = afwImage.ImageU(bb) foot.insertIntoImage(img, 1) self.assertTrue(numpy.all(img.getArray()[source.getArray() == 0] == 0)) if plots: plt.clf() plt.subplot(1,2,1) plt.imshow(source.getArray(), **ima) plt.subplot(1,2,2) plt.imshow(img.getArray(), **ima) plt.savefig('clipnz2.png') source.getArray()[:12,:] = 0.
933 99dc4b86 - foot.clipToNonzeroF(source)
? -
968 94770baf + foot.clipToNonzero(source)
foot.normalize() a2 = foot.getArea()
937 25e434a1 - self.assertTrue(a2 < a1)
? ^^^ ^^
972 94770baf + self.assertLess(a2, a1)
? ^ ++ ^ img = afwImage.ImageU(bb) foot.insertIntoImage(img, 1) self.assertTrue(numpy.all(img.getArray()[source.getArray() == 0] == 0)) if plots: plt.clf() plt.subplot(1,2,1) plt.imshow(source.getArray(), **ima) plt.subplot(1,2,2) img = afwImage.ImageU(bb) foot.insertIntoImage(img, 1) plt.imshow(img.getArray(), **ima) plt.savefig('clipnz3.png')
988 0b2457bc + def testInclude(self):
989 c839d0f2 + """Test that we can expand a Footprint to include the union of itself and all others
990 de65f62a + provided (must be non-disjoint).
991 de65f62a + """
992 0b2457bc + region = afwGeom.Box2I(afwGeom.Point2I(-6, -6), afwGeom.Point2I(6, 6))
993 0b2457bc + parent = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-2, -2), afwGeom.Point2I(2, 2)), region)
994 97aa2220 + parent.addPeak(0, 0, float("NaN"))
995 0b2457bc + child1 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-3, 0), afwGeom.Point2I(0, 3)), region)
996 97aa2220 + child1.addPeak(-1, 1, float("NaN"))
997 0b2457bc + child2 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-4, -3), afwGeom.Point2I(-1, 0)), region)
998 0b2457bc + child3 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(4, -1), afwGeom.Point2I(6, 1)))
999 0b2457bc + merge12 = afwDetect.Footprint(parent)
1000 0b2457bc + merge12.include([child1, child2])
1001 0b2457bc + self.assertTrue(merge12.getBBox().contains(parent.getBBox()))
1002 0b2457bc + self.assertTrue(merge12.getBBox().contains(child1.getBBox()))
1003 0b2457bc + self.assertTrue(merge12.getBBox().contains(child2.getBBox()))
1004 0b2457bc + mask12a = afwImage.MaskU(region)
1005 0b2457bc + mask12b = afwImage.MaskU(region)
1006 0b2457bc + afwDetect.setMaskFromFootprint(mask12a, parent, 1)
1007 0b2457bc + afwDetect.setMaskFromFootprint(mask12a, child1, 1)
1008 0b2457bc + afwDetect.setMaskFromFootprint(mask12a, child2, 1)
1009 0b2457bc + afwDetect.setMaskFromFootprint(mask12b, merge12, 1)
1010 0b2457bc + self.assertEqual(mask12a.getArray().sum(), merge12.getArea())
1011 0b2457bc + self.assertClose(mask12a.getArray(), mask12b.getArray(), rtol=0, atol=0)
1012 d19772f0 + self.assertRaisesLsstCpp(pexExcept.RuntimeError, parent.include, [child1, child2, child3])
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class FootprintSetTestCase(unittest.TestCase): """A test case for FootprintSet""" def setUp(self): self.ms = afwImage.MaskedImageF(afwGeom.Extent2I(12, 8)) im = self.ms.getImage() # # Objects that we should detect # self.objects = [] self.objects += [Object(10, [(1, 4, 4), (2, 3, 5), (3, 4, 4)])] self.objects += [Object(20, [(5, 7, 8), (5, 10, 10), (6, 8, 9)])] self.objects += [Object(20, [(6, 3, 3)])] self.ms.set((0, 0x0, 4.0)) # clear image; set variance for obj in self.objects: obj.insert(im) if False and display: ds9.mtv(im, frame=0)
976 f8edfe90 -
1036 c839d0f2 +
def tearDown(self): del self.ms def testGC(self): """Check that FootprintSets are automatically garbage collected (when MemoryTestCase runs)"""
982 f8edfe90 -
ds = afwDetect.FootprintSet(afwImage.MaskedImageF(afwGeom.Extent2I(10, 20)), afwDetect.Threshold(10)) def testFootprints(self): """Check that we found the correct number of objects and that they are correct""" ds = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10)) objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i])
994 f8edfe90 -
1053 c839d0f2 +
def testFootprints2(self): """Check that we found the correct number of objects using FootprintSet""" ds = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10)) objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i])
1004 8e0d1821 -
1063 c839d0f2 +
def testFootprints3(self): """Check that we found the correct number of objects using FootprintSet and PIXEL_STDEV""" threshold = 4.5 # in units of sigma self.ms.set(2, 4, (10, 0x0, 36)) # not detected (high variance) y, x = self.objects[2].spans[0][0:2] self.ms.set(x, y, (threshold, 0x0, 1.0)) ds = afwDetect.FootprintSet(self.ms, afwDetect.createThreshold(threshold, "pixel_stdev"), "OBJECT") objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i])
1022 5390e1df -
1081 c839d0f2 +
def testFootprintsMasks(self): """Check that detectionSets have the proper mask bits set""" ds = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10), "OBJECT") objects = ds.getFootprints() if display: ds9.mtv(self.ms, frame=1) mask = self.ms.getMask() for i in range(len(objects)): for sp in objects[i].getSpans(): for x in range(sp.getX0(), sp.getX1() + 1): self.assertEqual(mask.get(x, sp.getY()), mask.getPlaneBitMask("OBJECT")) def testFootprintsImageId(self): """Check that we can insert footprints into an Image""" ds = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10)) objects = ds.getFootprints() idImage = afwImage.ImageU(self.ms.getDimensions()) idImage.set(0)
1044 f8edfe90 -
1103 c839d0f2 +
for foot in objects: foot.insertIntoImage(idImage, foot.getId()) if False: ds9.mtv(idImage, frame=2) for i in range(len(objects)): for sp in objects[i].getSpans(): for x in range(sp.getX0(), sp.getX1() + 1): self.assertEqual(idImage.get(x, sp.getY()), objects[i].getId()) def testFootprintSetImageId(self): """Check that we can insert a FootprintSet into an Image, setting relative IDs""" ds = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10)) objects = ds.getFootprints() idImage = ds.insertIntoImage(True) if display: ds9.mtv(idImage, frame=2) for i in range(len(objects)): for sp in objects[i].getSpans(): for x in range(sp.getX0(), sp.getX1() + 1): self.assertEqual(idImage.get(x, sp.getY()), i + 1) def testFootprintsImage(self): """Check that we can search Images as well as MaskedImages""" ds = afwDetect.FootprintSet(self.ms.getImage(), afwDetect.Threshold(10)) objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i])
1080 1b170877 -
1139 c839d0f2 +
def testGrow2(self): """Grow some more interesting shaped Footprints. Informative with display, but no numerical tests"""
1083 5b637e27 -
ds = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10), "OBJECT") idImage = afwImage.ImageU(self.ms.getDimensions()) idImage.set(0) i = 1 for foot in ds.getFootprints()[0:1]: gfoot = afwDetect.growFootprint(foot, 3, False) gfoot.insertIntoImage(idImage, i) i += 1 if display: ds9.mtv(self.ms, frame=0) ds9.mtv(idImage, frame=1) def testFootprintPeaks(self): """Test that we can extract the peaks from a Footprint""" fs = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10), "OBJECT") foot = fs.getFootprints()[0] self.assertEqual(len(foot.getPeaks()), 5) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class MaskFootprintSetTestCase(unittest.TestCase): """A test case for generating FootprintSet from Masks""" def setUp(self): self.mim = afwImage.MaskedImageF(afwGeom.ExtentI(12, 8)) # # Objects that we should detect # self.objects = [] self.objects += [Object(0x2, [(1, 4, 4), (2, 3, 5), (3, 4, 4)])] self.objects += [Object(0x41, [(5, 7, 8), (6, 8, 8)])] self.objects += [Object(0x42, [(5, 10, 10)])] self.objects += [Object(0x82, [(6, 3, 3)])] self.mim.set((0, 0, 0)) # clear image for obj in self.objects: obj.insert(self.mim.getImage()) obj.insert(self.mim.getMask()) if display: ds9.mtv(self.mim, frame=0)
1130 517a3e45 -
1188 c839d0f2 +
def tearDown(self): del self.mim def testFootprints(self): """Check that we found the correct number of objects using FootprintSet""" level = 0x2 ds = afwDetect.FootprintSet(self.mim.getMask(), afwDetect.createThreshold(level, "bitmask")) objects = ds.getFootprints() if 0 and display: ds9.mtv(self.mim, frame=0) self.assertEqual(len(objects), len([o for o in self.objects if (o.val & level)])) i = 0 for o in self.objects: if o.val & level: self.assertEqual(o, objects[i]) i += 1
1151 517a3e45 -
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class NaNFootprintSetTestCase(unittest.TestCase): """A test case for FootprintSet when the image contains NaNs""" def setUp(self): self.ms = afwImage.MaskedImageF(afwGeom.Extent2I(12, 8)) im = self.ms.getImage() # # Objects that we should detect # self.objects = [] self.objects += [Object(10, [(1, 4, 4), (2, 3, 5), (3, 4, 4)])] self.objects += [Object(20, [(5, 7, 8), (6, 8, 8)])] self.objects += [Object(20, [(5, 10, 10)])] self.objects += [Object(30, [(6, 3, 3)])] im.set(0) # clear image for obj in self.objects: obj.insert(im) self.NaN = float("NaN") im.set(3, 7, self.NaN) im.set(0, 0, self.NaN) im.set(8, 2, self.NaN) im.set(9, 6, self.NaN) # connects the two objects with value==20 together if NaN is detected if False and display: ds9.mtv(im, frame=0)
1183 0ca4ec93 -
1240 c839d0f2 +
def tearDown(self): del self.ms def testFootprints(self): """Check that we found the correct number of objects using FootprintSet""" ds = afwDetect.FootprintSet(self.ms, afwDetect.Threshold(10), "DETECTED") objects = ds.getFootprints() if display: ds9.mtv(self.ms, frame=0) self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i]) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module."""
1204 f8edfe90 - tests.init()
1261 c605dfcd + utilsTests.init()
? + ++++ suites = [] suites += unittest.makeSuite(ThresholdTestCase) suites += unittest.makeSuite(SpanTestCase) suites += unittest.makeSuite(FootprintTestCase) suites += unittest.makeSuite(FootprintSetTestCase) suites += unittest.makeSuite(NaNFootprintSetTestCase) suites += unittest.makeSuite(MaskFootprintSetTestCase)
1213 f8edfe90 - suites += unittest.makeSuite(tests.MemoryTestCase)
1270 c605dfcd + suites += unittest.makeSuite(utilsTests.MemoryTestCase)
? + ++++ return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests"""
1219 38d0390b - tests.run(suite(), shouldExit)
1276 c605dfcd + utilsTests.run(suite(), shouldExit)
? + ++++ if __name__ == "__main__": run(True)

Return to list

Commits in /Users/nate/repos_hsc/afw/

46f3a3a0

commit 46f3a3a0facb4c1fd788d3b26b1548cb6fed60ab
Author: Robert Lupton the Good 
Date:   Wed Jan 23 18:20:51 2013 -0500

    Replaced tab by spaces

90219c90

commit 90219c902f2d7e3c89b3b4964d379ff3b65f65c9
Author: rhl 
Date:   Mon Dec 1 14:37:03 2008 +0000

    Allow us to offset Spans #505; Fix some problems with subimages #507; Fix bug in setting Footprint's BBox

76f3706f

commit 76f3706f6688b23d5b0c71e66af3e94095a9f821
Author: Paul Price 
Date:   Wed Sep 17 12:30:21 2014 -0400

    copyWithinFootprint: respect image size
    
    copyWithinFootprint could produce a segfault (or at least corrupt
    memory) when copying a Footprint that is larger than either of the
    images.  Changed so that pixels outside either image are ignored
    (i.e., it copies every pixel it is able to).  Added test of this
    behaviour and documented the function's behaviour.

f24557ac

commit f24557ac9181e23c505a02ab6457670144e65461
Author: Robert Lupton the Good 
Date:   Mon Dec 5 12:16:02 2011 -0500

    Add test that illustrates the problem in #1830

4dface89

commit 4dface89496957978717e5a72752ca15609287a6
Author: Jim Bosch 
Date:   Thu Apr 16 11:48:49 2015 -0400

    Add method to sort Peaks within a Footprint.
    
    Peaks should almost always be sorted from most positive to most negative.
    While Footprint doesn't enforce that condition, we need to make it easier
    for external code to do so.

1b170877

commit 1b17087762b74039f8eaade08449fc92c2db7b25
Author: rhl 
Date:   Mon Nov 9 22:20:43 2009 +0000

    Allow detection to run on Images, not just MaskedImages; #1013

92c7d358

commit 92c7d358b8fd8def981c4f920ad2bfd946145f37
Author: rhl 
Date:   Wed Dec 16 16:31:25 2009 +0000

    Make getBBox return a copy so it'll be immutable in python too; #1096

5016c432

commit 5016c432d57dddf844446ec0f5d05c03776c3d20
Author: Dustin Lang 
Date:   Fri Mar 7 12:39:34 2014 -0500

    mergeFootprints() is passing tests, with overly complex algorithm

63a74dc6

commit 63a74dc64ceb22835d0f09779136fd622f3cb1bb
Author: dubcovsky 
Date:   Mon Feb 23 18:50:13 2009 +0000

    #657 Policy constructor added to class Threshold. Tested

c902c475

commit c902c47592d44ba8aeeb3d329e340f1f32c0e5d9
Author: rhl 
Date:   Wed Mar 25 12:46:19 2009 +0000

    Added setImageFromFootprint(List)?; #0

20c2c467

commit 20c2c46776ad69164993f9837f347800a80f245b
Author: jbosch 
Date:   Fri Mar 4 01:19:01 2011 +0000

    afw #1556 - fixed all python unit tests with trivial syntax-related failures, plus a few others

6ac35e07

commit 6ac35e07a70a600e59ed290a1b8fb3173bdbf21d
Author: Jim Bosch 
Date:   Thu Nov 13 16:22:23 2014 -0500

    Replace Peak with PeakRecord
    
    By using afw::table objects to store Peaks, we allow additional
    information to be added to Peaks without requiring further changes
    to persistence.

5cdd6a3d

commit 5cdd6a3d782a7a8c37764d4494e3408312cdcb3a
Author: dubcovsky 
Date:   Fri Apr 29 23:26:39 2011 +0000

    #1659 correcting the behavor of footprintAndMask. closing ticket

b635df09

commit b635df0908f570c1c3c371b687a581da61f0be1f
Author: dubcovsky 
Date:   Wed Apr 27 21:32:08 2011 +0000

    Added swap functions for Point, Extent, and Box. Added Copy constructors to Peak and Footprint

99dc4b86

commit 99dc4b86974566e73f34c9eaa0347969c46831a1
Author: Dustin Lang 
Date:   Tue Mar 11 11:13:43 2014 -0400

    add test case for Footprint.clipToNonzero and find the bug (was making a copy of spanlist -- ugh!)

ce2846bf

commit ce2846bf8ec45a86f5a74cd920ba7ec5560496e0
Author: rhl 
Date:   Sat Mar 7 02:18:13 2009 +0000

    Turn off output to the screen

8e0d1821

commit 8e0d1821d1c2132eef169a69ba9381f69609b046
Author: rhl 
Date:   Wed Mar 11 21:01:43 2009 +0000

    Provide makeDetectionSet

4dda63e9

commit 4dda63e90091f78c019ff63e6e8a2ed7c66463d6
Author: Jim Bosch 
Date:   Mon Jun 3 21:56:18 2013 -0400

    Add table-based persistence for Footprint (#2917)

5adfee0e

commit 5adfee0e2b9465c1e746632e85a1c9f0eac96de4
Author: dubcovsky 
Date:   Tue Feb 24 00:40:41 2009 +0000

    #657 Refactored at RHL's suggestion. Instead of a constructor, desired functionality achieved through factory method lsst::afw::detection::createThreshold

0d1ab12d

commit 0d1ab12db604d5e42a5d72f028411a64294283ce
Author: Jim Bosch 
Date:   Sun Apr 20 21:44:20 2014 -0400

    When merging footprints, support noncontiguous inputs

0ca4ec93

commit 0ca4ec935ffe49fc44ac12fe8b91a2f98e7d7ce3
Author: rhl 
Date:   Fri Oct 2 01:59:36 2009 +0000

    Treat NaN pixels as being below threshold; ticket #912

102a5edd

commit 102a5eddfb6779ab597b1d94e115822822830a50
Author: Robert Lupton the Good 
Date:   Mon Jan 21 14:56:52 2013 -0500

    Implement Footprint.get{Centroid,Shape}; #2578

a716b827

commit a716b8278e46b783bd31b9781f12a51761041a1e
Author: rhl 
Date:   Wed Mar 4 17:58:23 2009 +0000

    Add footprintToBBoxList (#681).  As part of writing its test, make Statistics understand unsigned short images, and allow getValue() to return single requested statistic

ddb75eb2

commit ddb75eb2dc0ce9b2871dc265597db934b75531e5
Author: Bob Armstrong 
Date:   Fri May 1 14:03:26 2015 -0400

    Footprint: modify include method to ignore itself.
    
    This modification allows you to modify a footprint in-place to be the union
    of a list of footprints that are not necessarily contiguous.

c9c89e06

commit c9c89e060322883ace8599bf9b3584a73ac25d7b
Author: jbosch 
Date:   Tue Mar 8 23:14:46 2011 +0000

    afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms

38d0390b

commit 38d0390b408369593d8a0adfcb8b9b3ad3945075
Author: bick 
Date:   Thu Jan 7 21:29:28 2010 +0000

    #1113 more clean up on afw.

e0d7f5b9

commit e0d7f5b9c03e26b95545bf34bc99f21f06e62354
Author: Jim Bosch 
Date:   Tue Jun 4 19:48:15 2013 -0400

    Updates from #2917 review
    
    add peaks to test of footprint persistence
    
    add doxygen comment for fwd.h
    
    add brief comments explaining footprint helper classes

0d3a98b4

commit 0d3a98b4557980b17981b43abc6bf12435293c08
Author: rhl 
Date:   Sat Mar 7 01:30:04 2009 +0000

    Turned tests back on; added afwDetection.writeFootprintAsDefects

3263f939

commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
Author: dubcovsky 
Date:   Thu Feb 24 00:56:41 2011 +0000

    #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet

38eea4c1

commit 38eea4c1ae2e62ff37fe36c4a3f6a0508bed275c
Author: price 
Date:   Fri May 6 14:33:17 2011 +0000

    Expanding testNormalize to catch bug fixed by r21450.

f8edfe90

commit f8edfe90d99d004aca1819ef00099ce827e44343
Author: rhl 
Date:   Sat Nov 15 15:18:25 2008 +0000

    Merged from new-image-api branch at [6341]

25e434a1

commit 25e434a11cb5ce52998978bf511bd81769d71705
Author: Dustin Lang 
Date:   Tue Mar 11 14:13:04 2014 -0400

    argh, footprint.clipToNonzero denormalizes!

517a3e45

commit 517a3e4575ad2710d91c76efde70a4d00873e3ef
Author: rhl 
Date:   Fri Apr 29 21:10:40 2011 +0000

    Initial implementation

5d1934cc

commit 5d1934cc9fe7d8c43aa8f9318a1ac9a3ce85e94e
Author: Jim Bosch 
Date:   Wed Apr 16 17:20:02 2014 -0400

    Add Footprint method to merge with neighbors

17d1d529

commit 17d1d529ed63e98f98e5d1a7a7da4811e95fc26c
Author: dubcovsky 
Date:   Tue Feb 15 00:00:43 2011 +0000

    #1556 Split Footprint.h into Threshold.h, FootprintSet.h, and FootprintFunctor.h, to correspond with class names. Added a constructors to Footprint which use geom objects (BoxI and Ellipse) to construct footprints. Footprints now exclusively use geom::PointI and geom::BoxI internally. (but still accept image::PointI and image::BBox for backwards compatibility wherever possible). FootprintArray.h contains a static functions to flatten and expand ndarrays using a Footprint to map between 2-d and 1-d indices.

5b637e27

commit 5b637e2745f46bf04e106bfeffc807b4b8716ec4
Author: rhl 
Date:   Fri Feb 27 02:59:00 2009 +0000

    Add option to growFootprint to speed up operation by using a Manhattan metric to define the distance to grow; #0

5390e1df

commit 5390e1dffd98c9074131bfc2f4f6cdcd4dba767a
Author: rhl 
Date:   Mon Aug 15 13:31:59 2011 +0000

    Allow per-pixel detection thresholds via "PIXEL_STDEV"

6b20a59c

commit 6b20a59ce012c2846eb4dbe73d5ac5f87afb72b5
Author: rhl 
Date:   Thu Feb 12 16:43:41 2009 +0000

    I was failing to initialise the idImage (#639).  footprintGrow was also failing ro preserve the region, and disallowing ngrow=0

a6d55f08

commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
Author: dgehrig 
Date:   Mon Jul 12 00:24:33 2010 +0000

    adding copyright notices

Commits in /Users/nate/repos_lsst/afw/

de65f62a

commit de65f62aca09357adaa7952610f62167077ede34
Author: Lauren MacArthur 
Date:   Mon Mar 16 14:12:56 2015 -0400

    Clarify comments describing include function and homogenize variable names

d19772f0

commit d19772f08869b4990e56eed3825d4550a1830b98
Author: Lauren MacArthur 
Date:   Wed Mar 4 18:25:31 2015 -0500

    Update Exception in Footprint and tests/footprint1.py to new name

b80fe1d3

commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
Author: Russell Owen 
Date:   Mon Oct 27 18:01:15 2014 -0700

    Support from __future__ import division
    for classes such as Extension that support operator/ and/or operator/=
    and change unit tests to use it

93994d54

commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
Author: Russell Owen 
Date:   Wed Sep 10 13:46:23 2014 -0700

    Change default image origin to PARENT and use the default where possible.

ad62cd6e

commit ad62cd6ef911c0213ddbcbdb5ffb0154966b7dec
Author: John Swinbank 
Date:   Fri Nov 28 16:38:37 2014 -0600

    Test cases for shrinking

ae20e2b5

commit ae20e2b580e6d2a9e785dc0d4f471b7ebed2fb45
Author: John Swinbank 
Date:   Fri Nov 28 17:10:45 2014 -0600

    Support shrinks with a Manhattan metric

ca6bfc5f

commit ca6bfc5f93a0fa247ac9dad1a5997f3dc97e6edb
Author: John Swinbank 
Date:   Mon May 11 21:26:56 2015 -0400

    Fix performance regression in Footprint dilation.
    
    The earlier RLE-based Footprint dilation routine relied on
    Footprint::normalize() to weed out duplicate and overlapping Spans. Although
    good performance was obtained for small Footprints and structuring elements,
    this could result in a significant performance regression when a large number
    of Spans were created during dilation.
    
    Here, the algorithm is adjusted so that the list of (proto-)Spans is
    maintained in a normalized state as the Footprint is grown, thereby avoiding
    the bottleneck.

c605dfcd

commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
Author: Russell Owen 
Date:   Wed Apr 8 15:30:37 2015 -0700

    Use getTempFilePath to avoid temp file name collisions
    
    Using the same file name for temp files for different tests
    was causing occasional test failures due to collisions (one test
    would read another test's temporary file). Using the new context manager
    lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
    of accidentally picking like names in the future (e.g. from careless copy/paste),
    and handles file clean up on success.
    
    Use lsst.utils.tests.getTempFilePath where appropriate
    
    Remove old uses of os.remove, os.unlink and manually creating temporary file names
    and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
    since this automatically creates a name that is unique to a particular test method
    (and can easily create names that are unique within a test) and deletes the file at the end.
    
    Remove the only use of temporaryFile that I could find

94770baf

commit 94770bafec04976204f56cf3aed80fa02bece412
Author: Dustin Lang 
Date:   Mon Jun 23 17:17:08 2014 -0500

    Address various issues from Paul Price's in-depth review.
    
    Footprint.h:
        No documentation for new methods and functions.
    
    Footprint.cc:
        Move documentation to header file.
        Indentation is inconsistent. Should always be 4.
        Don't use this-> when there is no need for it, e.g., this->addSpan should be addSpan.
        Paren following LSST_EXCEPT *must* cuddle --- it certainly may not be on the next line.
        Breaks 110 column limit.
        PixelT zero = 0; should be PixelT const zero = 0; Add const also for ix0 and iy0 --- *anywhere* the value will never change, as it helps the compiler write faster code.
        You're iterating with the postfix operator (s++) instead of prefix (++s); this can adversely affect performance in C++.
        What does the comment Ugly! refer to?
        Names foota and footb don't follow naming rules, and are a bit hard to read. Suggest aFoot and bFoot. Similarly with pka, etc.
        const Footprint::PeakList& --> Footprint::PeakList const& (throughout).
        while (1) --> while (true)
        nearestFootprint isn't documented.
        Why do you call INSTANTIATE_FLOAT on integer types???  [I renamed it -- it instantiated functions that were appropriate for *numeric*, not necessarily floating-point, types!]
        remove gratuitous 'typename'
        prefer PTR(Foo) to Foo::Ptr and CONST_PTR(Foo) to Foo:ConstPtr.
    
    HeavyFootprint?.cc:
        Some lines exceed 110 columns.
        Commented out code should be removed
    
    footprint1.py:
        Instead of self.assertTrue(a > b) use self.assertGreater(a, b). This provides a more useful message when it fails.
        Why is the trailing F required on clipToNonzeroF? It should be able to tell from the type of the image.  [fixed]
    
    Also removed stray Footprint.mergeWith() function that got messed up during rebase

c839d0f2

commit c839d0f28287875df3e43b674f1da3f140a33250
Author: Lauren MacArthur 
Date:   Mon Mar 16 16:34:35 2015 -0400

    Update copyright and remove whitespace

ecb01ab8

commit ecb01ab81744139491981fb406fcc634181cbf5b
Author: Lauren MacArthur 
Date:   Thu Apr 23 16:58:48 2015 -0400

    Copy Peaks into grown and shrunken Footprints
    
    Peaks from the original Footprint need to be copied into the new
    Footprints returned by the growFootprint and shrinkFootprint
    functions.  For the latter, only those Peaks lying within the
    shrunken Footprint get added.
    
    The unittest code was updated to test these changes.

97aa2220

commit 97aa222066406079e53b7be9d271a0201e7d013e
Author: Lauren MacArthur 
Date:   Thu Apr 2 18:11:37 2015 -0400

    Update test for compatibility with PeakRecord

0b2457bc

commit 0b2457bc72484e8cfb78f471f6d6d7e7fc1f6437
Author: Jim Bosch 
Date:   Wed Apr 16 17:20:02 2014 -0400

    Add Footprint method to merge with neighbors
    
    Conflicts:
        tests/footprint1.py

97c3b722

commit 97c3b72271f9a15e6859146c1e77752993fe22a4
Author: John Swinbank 
Date:   Tue Nov 18 09:55:58 2014 -0600

    Footprint.getShape() takes no arguments

Return to list

src/math/GaussianProcess.cc

Diff:

                //  - * -  LSST - C++   - * -
                
                /*
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 *
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 *
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 *
                 * You should have received a copy of the LSST License Statement and
                 * the GNU General Public License along with this program.  If not,
                 * see  < http://www.lsstcorp.org/LegalNotices/ > .
                 */
                
                #include  
                #include  
                
                #include "lsst/afw/math/GaussianProcess.h"
                
                using namespace std;
                
                
                namespace lsst {
                namespace afw {
                namespace math {
                
                GaussianProcessTimer::GaussianProcessTimer()
                {
                    _interpolationCount = 0;
                    _iterationTime = 0.0;
                    _eigenTime = 0.0;
                    _searchTime = 0.0;
                    _varianceTime = 0.0;
                    _totalTime = 0.0;
                
                }
                
                void GaussianProcessTimer::reset()
                {
                    _interpolationCount = 0;
                    _iterationTime = 0.0;
                    _eigenTime = 0.0;
                    _searchTime = 0.0;
                    _varianceTime = 0.0;
                    _totalTime = 0.0;
                
                }
                
                void GaussianProcessTimer::start()
                {
                    _before = double(lsst::daf::base::DateTime::now().get()*24*60*60);
                    _beginning = _before;
                }
                
                void GaussianProcessTimer::addToEigen()
                {
                    double after;
                    after = double(lsst::daf::base::DateTime::now().get()*24*60*60);
                    _eigenTime += after - _before;
                    _before = after;
                }
                
                void GaussianProcessTimer::addToVariance()
                {
                    double after;
                    after = double(lsst::daf::base::DateTime::now().get()*24*60*60);
                    _varianceTime += after - _before;
                    _before = after;
                }
                
                void GaussianProcessTimer::addToSearch()
                {
                    double after;
                    after = double(lsst::daf::base::DateTime::now().get()*24*60*60);
                    _searchTime += after - _before;
                    _before = after;
                }
                
                void GaussianProcessTimer::addToIteration()
                {
                    double after;
                    after = double(lsst::daf::base::DateTime::now().get()*24*60*60);
                    _iterationTime += after - _before;
                    _before = after;
                }
                
                void GaussianProcessTimer::addToTotal(int i)
                {
                    double after;
                    after = double(lsst::daf::base::DateTime::now().get()*24*60*60);
                    _totalTime += after - _beginning;
                    _interpolationCount += i;
                }
                
                void GaussianProcessTimer::display(){
                    std::cout << "\nSearch time " << _searchTime << "\n";
                    std::cout << "Eigen time " << _eigenTime << "\n";
                    std::cout << "Variance time " << _varianceTime << "\n";
                    std::cout << "Iteration time " << _iterationTime << "\n";
                    std::cout << "Total time " << _totalTime << "\n";
                    std::cout << "Number of interpolations " << _interpolationCount << "\n";
                }
                
                template  < typename T >
                void KdTree < T > ::Initialize(ndarray::Array < T,2,2 >  const &dt)
                {
                    int i;
                
                    _pts = dt.template getSize < 0 > ();
                    _dimensions = dt.template getSize < 1 > ();
                
                    //a buffer to use when first building the tree
                    _inn = allocate(ndarray::makeVector(_pts));
                
                    _roomStep = 5000;
                    _room = _pts;
                
                    _data = allocate(ndarray::makeVector(_room,_dimensions));
                
                    _data.deep() = dt;
                
                    _tree = allocate(ndarray::makeVector(_room,4));
                
                    for (i = 0 ; i < _pts ; i++ ) {
                      _inn[i] = i;
                    }
                
                    _organize(_inn,_pts, -1, -1);
                
                
                    i = _testTree();
                    if (i == 0) {
143 63df72f1 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
143 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Failed to properly initialize KdTree\n"); } } template < typename T > void KdTree < T > ::findNeighbors(ndarray::Array < int,1,1 > neighdex, ndarray::Array < double,1,1 > dd, ndarray::Array < const T,1,1 > const &v, int n_nn) const { int i,start; _neighborCandidates = allocate(ndarray::makeVector(n_nn)); _neighborDistances = allocate(ndarray::makeVector(n_nn)); _neighborsFound = 0; _neighborsWanted = n_nn; for (i = 0; i < n_nn; i++ ) _neighborDistances[i] = -1.0; start = _findNode(v); _neighborDistances[0] = _distance(v,_data[start]); _neighborCandidates[0] = start; _neighborsFound = 1; for (i = 1; i < 4; i++ ) { if(_tree[start][i] >= 0){ _lookForNeighbors(v,_tree[start][i], start); } } for (i = 0 ; i < n_nn ; i++ ) { neighdex[i] = _neighborCandidates[i]; dd[i] = _neighborDistances[i]; } } template < typename T > T KdTree < T > ::getData(int ipt, int idim) const { return _data[ipt][idim]; } template < typename T > ndarray::Array < T,1,1 > KdTree < T > ::getData(int ipt) const { return _data[ipt]; } template < typename T > void KdTree < T > ::addPoint(ndarray::Array < const T,1,1 > const &v) { int i,j,node,dim,dir; node = _findNode(v); dim = _tree[node][DIMENSION] + 1; if(dim == _dimensions)dim = 0; if(_pts == _room){ ndarray::Array < T,2,2 > dbuff = allocate(ndarray::makeVector(_pts, _dimensions)); ndarray::Array < int,2,2 > tbuff = allocate(ndarray::makeVector(_pts, 4)); dbuff.deep() = _data; tbuff.deep() = _tree; _room += _roomStep; _tree = allocate(ndarray::makeVector(_room, 4)); _data = allocate(ndarray::makeVector(_room, _dimensions)); for (i = 0; i < _pts; i++ ) { for (j = 0; j < _dimensions; j++ ) _data[i][j] = dbuff[i][j]; for (j = 0; j < 4; j++ ) _tree[i][j] = tbuff[i][j]; } } _tree[_pts][DIMENSION] = dim; _tree[_pts][PARENT] = node; i = _tree[node][DIMENSION]; if(_data[node][i] > v[i]){ if(_tree[node][LT] >= 0){
231 63df72f1 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
231 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Trying to add to KdTree in a node that is already occupied\n"); } _tree[node][LT] = _pts; dir=LT; } else{ if(_tree[node][GEQ] >= 0){
239 63df72f1 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
239 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Trying to add to KdTree in a node that is already occupied\n"); } _tree[node][GEQ] = _pts; dir=GEQ; } _tree[_pts][LT] = -1; _tree[_pts][GEQ] = -1; for (i = 0; i < _dimensions; i++ ) { _data[_pts][i] = v[i]; } _pts++; i = _walkUpTree(_tree[_pts-1][PARENT], dir, _pts-1); if (i != _masterParent){
256 63df72f1 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
256 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Adding to KdTree failed\n"); } } template < typename T > int KdTree < T > ::getPoints() const { return _pts; } template < typename T > void KdTree < T > ::getTreeNode(ndarray::Array < int,1,1 > const &v, int dex) const { v[0] = _tree[dex][DIMENSION]; v[1] = _tree[dex][LT]; v[2] = _tree[dex][GEQ]; v[3] = _tree[dex][PARENT]; } template < typename T > int KdTree < T > ::_testTree() const{ int i,j,output; std::vector < int > isparent; output=1; for (i = 0; i < _pts; i++ ) isparent.push_back(0); j = 0; for (i = 0; i < _pts; i++ ) { if(_tree[i][PARENT] < 0)j++; } if(j != 1){ std::cout << "_tree FAILURE " << j << " _masterParents\n"; return 0; } for (i = 0; i < _pts; i++ ) { if(_tree[i][PARENT] >= 0){ isparent[_tree[i][PARENT]]++; } } for (i = 0; i < _pts; i++ ) { if(isparent[i] > 2){ std::cout << "_tree FAILURE " << i << " is parent to " << isparent[i] << "\n"; return 0; } } for (i = 0; i < _pts; i++ ) { if(_tree[i][PARENT] >= 0) { if(_tree[_tree[i][PARENT]][LT] == i)j = LT; else j = GEQ; output = _walkUpTree(_tree[i][PARENT], j, i); if(output != _masterParent){ return 0; } } } if(output != _masterParent) return 0; else return 1; } template < typename T > void KdTree < T > ::_organize(ndarray::Array < int,1,1 > const &use, int ct, int parent, int dir ) { int i,j,k,l,idim,daughter; T mean,var,varbest; std::vector < std::vector < T > > toSort; std::vector < T > toSortElement; if(ct > 1){ //below is code to choose the dimension on which the available points //have the greates variance. This will be the dimension on which //the daughter node splits the data idim=0; varbest=-1.0; for (i = 0; i < _dimensions; i++ ) { mean = 0.0; var = 0.0; for (j = 0; j < ct; j++ ) { mean += _data[use[j]][i]; var += _data[use[j]][i]*_data[use[j]][i]; } mean = mean/double(ct); var = var/double(ct) - mean*mean; if(i == 0 || var > varbest || (var == varbest && parent >= 0 && i > _tree[parent][DIMENSION])) { idim = i; varbest = var; } }//for(i = 0;i < _dimensions;i++ ) //we need to sort the available data points according to their idim - th element //but we need to keep track of their original indices, so we can refer back to //their positions in _data. Therefore, the code constructs a 2 - dimensional //std::vector. The first dimension contains the element to be sorted. //The second dimension contains the original index information. //After sorting, the (rearranged) index information will be stored back in the //ndarray use[] toSortElement.push_back(_data[use[0]][idim]); toSortElement.push_back(T(use[0])); toSort.push_back(toSortElement); for(i = 1; i < ct; i++ ) { toSortElement[0] = _data[use[i]][idim]; toSortElement[1] = T(use[i]); toSort.push_back(toSortElement); } std::stable_sort(toSort.begin(), toSort.end()); k = ct/2; l = ct/2; while(k > 0 && toSort[k][0] == toSort[k - 1][0]) k--; while(l < ct - 1 && toSort[l][0] == toSort[ct/2][0]) l++; if((ct/2 - k) < (l - ct/2) || l == ct - 1) j = k; else j = l; for(i = 0; i < ct; i++ ) { use[i] = int(toSort[i][1]); } daughter = use[j]; if(parent >= 0)_tree[parent][dir] = daughter; _tree[daughter][DIMENSION] = idim; _tree[daughter][PARENT] = parent; if(j < ct - 1){ _organize(use[ndarray::view(j + 1,use.getSize < 0 > ())], ct - j - 1, daughter, GEQ); } else _tree[daughter][GEQ] = -1; if(j > 0){ _organize(use, j, daughter, LT); } else _tree[daughter][LT] = -1; }//if(ct > 1) else{ daughter = use[0]; if(parent >= 0) _tree[parent][dir] = daughter; idim = _tree[parent][DIMENSION] + 1; if(idim >= _dimensions)idim = 0; _tree[daughter][DIMENSION] = idim; _tree[daughter][LT] = - 1; _tree[daughter][GEQ] = - 1; _tree[daughter][PARENT] = parent; } if(parent == - 1){ _masterParent = daughter; } } template < typename T > int KdTree < T > ::_findNode(ndarray::Array < const T,1,1 > const &v) const { int consider,next,dim; dim = _tree[_masterParent][DIMENSION]; if(v[dim] < _data[_masterParent][dim]) consider = _tree[_masterParent][LT]; else consider = _tree[_masterParent][GEQ]; next = consider; while(next >= 0){ consider = next; dim = _tree[consider][DIMENSION]; if(v[dim] < _data[consider][dim]) next = _tree[consider][LT]; else next = _tree[consider][GEQ]; } return consider; } template < typename T > void KdTree < T > ::_lookForNeighbors(ndarray::Array < const T,1,1 > const &v, int consider, int from) const { int i,j,going; double dd; dd = _distance(v, _data[consider]); if(_neighborsFound < _neighborsWanted || dd < _neighborDistances[_neighborsWanted -1]) { for(j = 0; j < _neighborsFound && _neighborDistances[j] < dd; j++ ); for(i = _neighborsWanted - 1; i > j; i-- ){ _neighborDistances[i] = _neighborDistances[i - 1]; _neighborCandidates[i] = _neighborCandidates[i - 1]; } _neighborDistances[j] = dd; _neighborCandidates[j] = consider; if(_neighborsFound < _neighborsWanted) _neighborsFound++; } if(_tree[consider][PARENT] == from){ //you came here from the parent i = _tree[consider][DIMENSION]; dd = v[i] - _data[consider][i]; if((dd <= _neighborDistances[_neighborsFound - 1] || _neighborsFound < _neighborsWanted) && _tree[consider][LT] >= 0){ _lookForNeighbors(v, _tree[consider][LT], consider); } dd = _data[consider][i] - v[i]; if((dd <= _neighborDistances[_neighborsFound - 1] || _neighborsFound < _neighborsWanted) && _tree[consider][GEQ] >= 0){ _lookForNeighbors(v, _tree[consider][GEQ], consider); } } else{ //you came here from one of the branches //descend the other branch if(_tree[consider][LT] == from){ going = GEQ; } else{ going = LT; } j = _tree[consider][going]; if(j >= 0){ i = _tree[consider][DIMENSION]; if(going == 1) dd = v[i] - _data[consider][i]; else dd = _data[consider][i] - v[i]; if(dd <= _neighborDistances[_neighborsFound - 1] || _neighborsFound < _neighborsWanted) { _lookForNeighbors(v, j, consider); } } //ascend to the parent if(_tree[consider][PARENT] >= 0) { _lookForNeighbors(v, _tree[consider][PARENT], consider); } } } template < typename T > int KdTree < T > ::_walkUpTree(int target, int dir, int root) const { //target is the node that you are examining now //dir is where you came from //root is the ultimate point from which you started int i,output; output = 1; if(dir == LT){ if(_data[root][_tree[target][DIMENSION]] >= _data[target][_tree[target][DIMENSION]]){ return 0; } } else{ if(_data[root][_tree[target][DIMENSION]] < _data[target][_tree[target][DIMENSION]]) { return 0; } } if(_tree[target][PARENT] >= 0){ if(_tree[_tree[target][PARENT]][LT] == target)i = LT; else i = GEQ; output = output*_walkUpTree(_tree[target][PARENT],i,root); } else{ output = output*target; //so that it will return _masterParent //make sure everything is connected to _masterParent } return output; } template < typename T > void KdTree < T > ::removePoint(int target) { int nl,nr,i,j,k,side; int root; nl = 0; nr = 0; if(_tree[target][LT] >= 0){ nl++ ; _count(_tree[target][LT], &nl); } if(_tree[target][GEQ] >= 0){ nr++; _count(_tree[target][GEQ], &nr); } if(nl == 0 && nr == 0){ k = _tree[target][PARENT]; if(_tree[k][LT] == target) _tree[k][LT] = - 1; else if(_tree[k][GEQ] == target) _tree[k][GEQ] = - 1; }//if target is terminal else if((nl == 0 && nr > 0) || (nr == 0 && nl > 0)){ if(nl == 0) side = GEQ; else side = LT; k = _tree[target][PARENT]; if(k >= 0){ if(_tree[k][LT] == target){ _tree[k][LT] = _tree[target][side]; _tree[_tree[k][LT]][PARENT] = k; } else{ _tree[k][GEQ] = _tree[target][side]; _tree[_tree[k][GEQ]][PARENT] = k; } } else{ _masterParent = _tree[target][side]; _tree[_tree[target][side]][PARENT] = - 1; } }//if only one side is populated else{ if(nl > nr)side = LT; else side = GEQ; k = _tree[target][PARENT]; if(k < 0){ _masterParent = _tree[target][side]; _tree[_masterParent][PARENT] = - 1; } else{ if(_tree[k][LT] == target){ _tree[k][LT] = _tree[target][side]; _tree[_tree[k][LT]][PARENT] = k; } else{ _tree[k][GEQ] = _tree[target][side]; _tree[_tree[k][GEQ]][PARENT] = k; } } root = _tree[target][3 - side]; _descend(root); }//if both sides are populated if(target < _pts - 1){ for(i = target + 1;i < _pts;i++ ){ for(j = 0; j < 4; j++ ) _tree[i - 1][j] = _tree[i][j]; for(j = 0; j < _dimensions; j++ ) _data[i - 1][j] = _data[i][j]; } for(i = 0; i < _pts; i++ ){ for(j = 1; j < 4; j++ ){ if(_tree[i][j] > target) _tree[i][j]--; } } if(_masterParent > target)_masterParent-- ; } _pts--; i = _testTree(); if (i == 0) {
668 63df72f1 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
668 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Subtracting from KdTree failed\n"); } } template < typename T > void KdTree < T > ::_count(int where, int *ct) const { //a way to count the number of vital elements on a given branch if(_tree[where][LT] >= 0) { ct[0]++; _count(_tree[where][LT], ct); } if(_tree[where][GEQ] >= 0) { ct[0]++; _count(_tree[where][GEQ], ct); } } template < typename T > void KdTree < T > ::_reassign(int target) { int where,dir,k; where = _masterParent; if(_data[target][_tree[where][DIMENSION]] < _data[where][_tree[where][DIMENSION]]) dir = LT; else dir = GEQ; k = _tree[where][dir]; while(k >= 0) { where = k; if(_data[target][_tree[where][DIMENSION]] < _data[where][_tree[where][DIMENSION]]) dir = LT; else dir = GEQ; k = _tree[where][dir]; } _tree[where][dir] = target; _tree[target][PARENT] = where; _tree[target][LT] = - 1; _tree[target][GEQ] = - 1; _tree[target][DIMENSION] = _tree[where][DIMENSION] + 1; if(_tree[target][DIMENSION] == _dimensions) _tree[target][DIMENSION] = 0; } template < typename T > void KdTree < T > ::_descend(int root) { if(_tree[root][LT] >= 0) _descend(_tree[root][LT]); if(_tree[root][GEQ] >= 0) _descend(_tree[root][GEQ]); _reassign(root); } template < typename T > double KdTree < T > ::_distance(ndarray::Array < const T,1,1 > const &p1, ndarray::Array < const T,1,1 > const &p2) const { int i,dd; double ans; ans = 0.0; dd = p1.template getSize< 0 >(); for(i = 0;i < dd;i++ ) ans += (p1[i] - p2[i])*(p1[i] - p2[i]); return ::sqrt(ans); } template < typename T > GaussianProcess < T > ::GaussianProcess(ndarray::Array < T,2,2 > const &dataIn, ndarray::Array < T,1,1 > const &ff, boost::shared_ptr < Covariogram < T > > const &covarIn) { int i; _covariogram = covarIn; _pts = dataIn.template getSize < 0 > (); _dimensions = dataIn.template getSize < 1 > (); _room = _pts; _roomStep = 5000; _nFunctions = 1; _function = allocate(ndarray::makeVector(_pts,1)); for(i = 0; i < _pts; i++ ) _function[i][0] = ff[i]; _krigingParameter = T(1.0); _lambda = T(1.0e-5); _useMaxMin = 0; _kdTree.Initialize(dataIn); _pts = _kdTree.getPoints(); } template < typename T > GaussianProcess < T > ::GaussianProcess(ndarray::Array < T,2,2 > const &dataIn, ndarray::Array < T,1,1 > const &mn, ndarray::Array < T,1,1 > const &mx, ndarray::Array < T,1,1 > const &ff, boost::shared_ptr < Covariogram < T > > const &covarIn ) { int i,j; ndarray::Array < T,2,2 > normalizedData; _covariogram = covarIn; _pts = dataIn.template getSize < 0 > (); _dimensions = dataIn.template getSize < 1 > (); _room = _pts; _roomStep = 5000; _krigingParameter = T(1.0); _lambda = T(1.0e-5); _krigingParameter = T(1.0); _max = allocate(ndarray::makeVector(_dimensions)); _min = allocate(ndarray::makeVector(_dimensions)); _max.deep() = mx; _min.deep() = mn; _useMaxMin = 1; normalizedData = allocate(ndarray::makeVector(_pts, _dimensions)); for(i = 0; i < _pts; i++ ) { for(j = 0; j < _dimensions; j++ ) { normalizedData[i][j] = (dataIn[i][j] - _min[j])/(_max[j] - _min[j]); //note the normalization by _max - _min in each dimension } } _kdTree.Initialize(normalizedData); _pts = _kdTree.getPoints(); _nFunctions = 1; _function = allocate(ndarray::makeVector(_pts, 1)); for(i = 0; i < _pts; i++ )_function[i][0] = ff[i]; } template < typename T > GaussianProcess < T > ::GaussianProcess(ndarray::Array < T,2,2 > const &dataIn, ndarray::Array < T,2,2 > const &ff, boost::shared_ptr > const &covarIn) { _covariogram = covarIn; _pts = dataIn.template getSize < 0 > (); _dimensions = dataIn.template getSize < 1 > (); _room = _pts; _roomStep = 5000; _nFunctions = ff.template getSize < 1 > (); _function = allocate(ndarray::makeVector(_pts, _nFunctions)); _function.deep() = ff; _krigingParameter = T(1.0); _lambda = T(1.0e-5); _useMaxMin = 0; _kdTree.Initialize(dataIn); _pts = _kdTree.getPoints(); } template < typename T > GaussianProcess < T > ::GaussianProcess(ndarray::Array < T,2,2 > const &dataIn, ndarray::Array < T,1,1 > const &mn, ndarray::Array < T,1,1 > const &mx, ndarray::Array < T,2,2 > const &ff, boost::shared_ptr > const &covarIn ) { int i,j; ndarray::Array < T,2,2 > normalizedData; _covariogram = covarIn; _pts = dataIn.template getSize < 0 > (); _dimensions = dataIn.template getSize < 1 > (); _room = _pts; _roomStep = 5000; _krigingParameter = T(1.0); _lambda = T(1.0e-5); _krigingParameter = T(1.0); _max = allocate(ndarray::makeVector(_dimensions)); _min = allocate(ndarray::makeVector(_dimensions)); _max.deep() = mx; _min.deep() = mn; _useMaxMin = 1; normalizedData = allocate(ndarray::makeVector(_pts,_dimensions)); for(i = 0; i < _pts; i++ ) { for(j = 0; j < _dimensions; j++ ) { normalizedData[i][j] = (dataIn[i][j] - _min[j])/(_max[j] - _min[j]); //note the normalization by _max - _min in each dimension } } _kdTree.Initialize(normalizedData); _pts = _kdTree.getPoints(); _nFunctions = ff.template getSize < 1 > (); _function = allocate(ndarray::makeVector(_pts, _nFunctions)); _function.deep() = ff; } template < typename T > T GaussianProcess < T > ::interpolate(ndarray::Array < T,1,1 > variance, ndarray::Array < T,1,1 > const &vin, int numberOfNeighbors) const { if(numberOfNeighbors <= 0){
905 bf63375f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
905 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked for zero or negative number of neighbors\n"); } if(numberOfNeighbors > _kdTree.getPoints()){
910 bf63375f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
910 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked for more neighbors than you have data points\n"); } int i,j; T fbar,mu; ndarray::Array < T,1,1 > covarianceTestPoint; ndarray::Array < int,1,1 > neighbors; ndarray::Array < double,1,1 > neighborDistances,vv; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > covariance,bb,xx; Eigen::LDLT < Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > > ldlt; _timer.start(); bb.resize(numberOfNeighbors, 1); xx.resize(numberOfNeighbors, 1); covariance.resize(numberOfNeighbors,numberOfNeighbors); covarianceTestPoint = allocate(ndarray::makeVector(numberOfNeighbors)); neighbors = allocate(ndarray::makeVector(numberOfNeighbors)); neighborDistances = allocate(ndarray::makeVector(numberOfNeighbors)); vv = allocate(ndarray::makeVector(_dimensions)); if(_useMaxMin == 1){ //if you constructed this Gaussian process with minimum and maximum //values for the dimensions of your parameter space, //the point you are interpolating must be scaled to match the data so //that the selected nearest neighbors are appropriate for(i = 0; i < _dimensions; i++ ) vv[i] = (vin[i] - _min[i])/(_max[i] - _min[i]); } else{ vv = vin; } _kdTree.findNeighbors(neighbors, neighborDistances, vv, numberOfNeighbors); _timer.addToSearch(); fbar = 0.0; for(i = 0; i < numberOfNeighbors; i++ )fbar += _function[neighbors[i]][0]; fbar = fbar/double(numberOfNeighbors); for(i = 0; i < numberOfNeighbors; i++ ){ covarianceTestPoint[i] = (*_covariogram)(vv, _kdTree.getData(neighbors[i])); covariance(i,i) = (*_covariogram)(_kdTree.getData(neighbors[i]), _kdTree.getData(neighbors[i])) + _lambda; for(j = i + 1; j < numberOfNeighbors; j++ ){ covariance(i,j) = (*_covariogram)(_kdTree.getData(neighbors[i]), _kdTree.getData(neighbors[j])); covariance(j,i) = covariance(i, j); } } _timer.addToIteration(); //use Eigen's ldlt solver in place of matrix inversion (for speed purposes) ldlt.compute(covariance); for(i = 0; i < numberOfNeighbors; i++) bb(i,0) = _function[neighbors[i]][0] - fbar; xx = ldlt.solve(bb); _timer.addToEigen(); mu = fbar; for(i = 0; i < numberOfNeighbors; i++ ){ mu += covarianceTestPoint[i]*xx(i, 0); } _timer.addToIteration(); variance(0) = (*_covariogram)(vv, vv) + _lambda; for(i = 0; i < numberOfNeighbors; i++ ) bb(i) = covarianceTestPoint[i]; xx = ldlt.solve(bb); for(i = 0; i < numberOfNeighbors; i++ ){ variance(0) -= covarianceTestPoint[i]*xx(i, 0); } variance(0) = variance(0)*_krigingParameter; _timer.addToVariance(); _timer.addToTotal(1); return mu; } template < typename T > void GaussianProcess < T > ::interpolate(ndarray::Array < T,1,1 > mu, ndarray::Array < T,1,1 > variance, ndarray::Array < T,1,1 > const &vin, int numberOfNeighbors) const { if(numberOfNeighbors <= 0){
1018 bf63375f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1018 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked for zero or negative number of neighbors\n"); } if(numberOfNeighbors > _kdTree.getPoints()){
1023 bf63375f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1023 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked for more neighbors than you have data points\n"); } int i,j,ii; T fbar; ndarray::Array < T,1,1 > covarianceTestPoint; ndarray::Array < int,1,1 > neighbors; ndarray::Array < double,1,1 > neighborDistances,vv; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > covariance,bb,xx; Eigen::LDLT < Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > > ldlt; _timer.start(); bb.resize(numberOfNeighbors,1); xx.resize(numberOfNeighbors,1); covariance.resize(numberOfNeighbors,numberOfNeighbors); covarianceTestPoint = allocate(ndarray::makeVector(numberOfNeighbors)); neighbors = allocate(ndarray::makeVector(numberOfNeighbors)); neighborDistances = allocate(ndarray::makeVector(numberOfNeighbors)); vv = allocate(ndarray::makeVector(_dimensions)); if(_useMaxMin == 1) { //if you constructed this Gaussian process with minimum and maximum //values for the dimensions of your parameter space, //the point you are interpolating must be scaled to match the data so //that the selected nearest neighbors are appropriate for(i = 0; i < _dimensions; i++ )vv[i] = (vin[i] - _min[i])/(_max[i] - _min[i]); } else { vv = vin; } _kdTree.findNeighbors(neighbors, neighborDistances, vv, numberOfNeighbors); _timer.addToSearch(); for(i = 0; i < numberOfNeighbors; i++ ) { covarianceTestPoint[i] = (*_covariogram)(vv, _kdTree.getData(neighbors[i])); covariance(i,i) = (*_covariogram)(_kdTree.getData(neighbors[i]), _kdTree.getData(neighbors[i])) + _lambda; for(j = i + 1; j < numberOfNeighbors; j++ ){ covariance(i,j) = (*_covariogram)(_kdTree.getData(neighbors[i]), _kdTree.getData(neighbors[j])); covariance(j,i) = covariance(i, j); } } _timer.addToIteration(); //use Eigen's ldlt solver in place of matrix inversion (for speed purposes) ldlt.compute(covariance); for(ii = 0; ii < _nFunctions; ii++ ) { fbar = 0.0; for(i = 0; i < numberOfNeighbors; i++ )fbar += _function[neighbors[i]][ii]; fbar = fbar/double(numberOfNeighbors); for(i = 0; i < numberOfNeighbors; i++ )bb(i,0) = _function[neighbors[i]][ii] - fbar; xx = ldlt.solve(bb); mu[ii] = fbar; for(i = 0; i < numberOfNeighbors; i++ ) { mu[ii] += covarianceTestPoint[i]*xx(i, 0); } }//ii = 0 through _nFunctions _timer.addToEigen(); variance[0] = (*_covariogram)(vv, vv) + _lambda; for(i = 0; i < numberOfNeighbors; i++ )bb(i) = covarianceTestPoint[i]; xx = ldlt.solve(bb); for(i = 0; i < numberOfNeighbors; i++ ) { variance[0] -= covarianceTestPoint[i]*xx(i, 0); } variance[0] = variance[0]*_krigingParameter; for(i = 1; i < _nFunctions; i++ )variance[i] = variance[0]; _timer.addToVariance(); _timer.addToTotal(1); } template < typename T > T GaussianProcess < T > ::selfInterpolate(ndarray::Array < T,1,1 > variance, int dex, int numberOfNeighbors) const { if(numberOfNeighbors <= 0){
1131 bf63375f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1131 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked for zero or negative number of neighbors\n"); } if(numberOfNeighbors > _kdTree.getPoints()){
1136 bf63375f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1136 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked for more neighbors than you have data points\n"); } int i,j; T fbar,mu; ndarray::Array < T,1,1 > covarianceTestPoint; ndarray::Array < int,1,1 > selfNeighbors; ndarray::Array < double,1,1 > selfDistances; ndarray::Array < int,1,1 > neighbors; ndarray::Array < double,1,1 > neighborDistances; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > covariance,bb,xx; Eigen::LDLT < Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > > ldlt; _timer.start(); bb.resize(numberOfNeighbors, 1); xx.resize(numberOfNeighbors, 1); covariance.resize(numberOfNeighbors,numberOfNeighbors); covarianceTestPoint = allocate(ndarray::makeVector(numberOfNeighbors)); neighbors = allocate(ndarray::makeVector(numberOfNeighbors)); neighborDistances = allocate(ndarray::makeVector(numberOfNeighbors)); selfNeighbors = allocate(ndarray::makeVector(numberOfNeighbors + 1)); selfDistances = allocate(ndarray::makeVector(numberOfNeighbors + 1)); //we don't use _useMaxMin because the data has already been normalized _kdTree.findNeighbors(selfNeighbors, selfDistances, _kdTree.getData(dex), numberOfNeighbors + 1); _timer.addToSearch(); if(selfNeighbors[0]!= dex) {
1173 63df72f1 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1173 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Nearest neighbor search in selfInterpolate did not find self\n"); } //SelfNeighbors[0] will be the point itself (it is its own nearest neighbor) //We discard that for the interpolation calculation // //If you do not wish to do this, simply call the usual ::interpolate() method instead of //::selfInterpolate() for(i = 0; i < numberOfNeighbors; i++ ){ neighbors[i] = selfNeighbors[i + 1]; neighborDistances[i] = selfDistances[i + 1]; } fbar = 0.0; for(i = 0; i < numberOfNeighbors; i++ ) fbar += _function[neighbors[i]][0]; fbar = fbar/double(numberOfNeighbors); for(i = 0; i < numberOfNeighbors; i++ ){ covarianceTestPoint[i] = (*_covariogram)(_kdTree.getData(dex), _kdTree.getData(neighbors[i])); covariance(i, i) = (*_covariogram)(_kdTree.getData(neighbors[i]), _kdTree.getData(neighbors[i])) + _lambda; for(j = i + 1; j < numberOfNeighbors; j++ ) { covariance(i, j) = (*_covariogram)(_kdTree.getData(neighbors[i]), _kdTree.getData(neighbors[j])); covariance(j, i) = covariance(i ,j); } } _timer.addToIteration(); //use Eigen's ldlt solver in place of matrix inversion (for speed purposes) ldlt.compute(covariance); for(i = 0; i < numberOfNeighbors;i++ ) bb(i, 0) = _function[neighbors[i]][0] - fbar; xx = ldlt.solve(bb); _timer.addToEigen(); mu = fbar; for(i = 0; i < numberOfNeighbors; i++ ) { mu += covarianceTestPoint[i]*xx(i, 0); } variance(0) = (*_covariogram)(_kdTree.getData(dex), _kdTree.getData(dex)) + _lambda; for(i = 0; i < numberOfNeighbors; i++ )bb(i) = covarianceTestPoint[i]; xx = ldlt.solve(bb); for(i = 0; i < numberOfNeighbors; i++ ){ variance(0) -= covarianceTestPoint[i]*xx(i,0); } variance(0) = variance(0)*_krigingParameter; _timer.addToVariance(); _timer.addToTotal(1); return mu; } template < typename T > void GaussianProcess < T > ::selfInterpolate(ndarray::Array < T,1,1 > mu, ndarray::Array < T,1,1 > variance, int dex, int numberOfNeighbors) const{ if(numberOfNeighbors <= 0){
1245 bf63375f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1245 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked for zero or negative number of neighbors\n"); } if(numberOfNeighbors + 1 > _kdTree.getPoints()){
1250 bf63375f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1250 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked for more neighbors than you have data points\n"); } if(dex < 0 || dex >=_kdTree.getPoints()){
1255 c7028ce7 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1255 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Asked to self interpolate on a point that does not exist\n"); } int i,j,ii; T fbar; ndarray::Array < T,1,1 > covarianceTestPoint; ndarray::Array < int,1,1 > selfNeighbors; ndarray::Array < double,1,1 > selfDistances; ndarray::Array < int,1,1 > neighbors; ndarray::Array < double,1,1 > neighborDistances; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > covariance,bb,xx; Eigen::LDLT < Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > > ldlt; _timer.start(); bb.resize(numberOfNeighbors, 1); xx.resize(numberOfNeighbors, 1); covariance.resize(numberOfNeighbors,numberOfNeighbors); covarianceTestPoint = allocate(ndarray::makeVector(numberOfNeighbors)); neighbors = allocate(ndarray::makeVector(numberOfNeighbors)); neighborDistances = allocate(ndarray::makeVector(numberOfNeighbors)); selfNeighbors = allocate(ndarray::makeVector(numberOfNeighbors + 1)); selfDistances = allocate(ndarray::makeVector(numberOfNeighbors + 1)); //we don't use _useMaxMin because the data has already been normalized _kdTree.findNeighbors(selfNeighbors, selfDistances, _kdTree.getData(dex), numberOfNeighbors + 1); _timer.addToSearch(); if(selfNeighbors[0]!= dex) {
1293 63df72f1 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1293 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"Nearest neighbor search in selfInterpolate did not find self\n"); } //SelfNeighbors[0] will be the point itself (it is its own nearest neighbor) //We discard that for the interpolation calculation // //If you do not wish to do this, simply call the usual ::interpolate() method instead of //::selfInterpolate() for(i = 0; i < numberOfNeighbors; i++ ) { neighbors[i] = selfNeighbors[i + 1]; neighborDistances[i] = selfDistances[i + 1]; } for(i = 0; i < numberOfNeighbors; i++ ) { covarianceTestPoint[i] = (*_covariogram)(_kdTree.getData(dex),_kdTree.getData(neighbors[i])); covariance(i, i) = (*_covariogram)(_kdTree.getData(neighbors[i]), _kdTree.getData(neighbors[i])) + _lambda; for(j = i + 1; j < numberOfNeighbors; j++ ) { covariance(i, j) = (*_covariogram)(_kdTree.getData(neighbors[i]), _kdTree.getData(neighbors[j])); covariance(j, i) = covariance(i, j); } } _timer.addToIteration(); //use Eigen's ldlt solver in place of matrix inversion (for speed purposes) ldlt.compute(covariance); for(ii = 0; ii < _nFunctions; ii++ ) { fbar = 0.0; for(i = 0; i < numberOfNeighbors; i++ )fbar += _function[neighbors[i]][ii]; fbar = fbar/double(numberOfNeighbors); for(i = 0; i < numberOfNeighbors; i++ )bb(i,0) = _function[neighbors[i]][ii] - fbar; xx = ldlt.solve(bb); mu[ii] = fbar; for(i = 0; i < numberOfNeighbors; i++ ){ mu[ii] += covarianceTestPoint[i]*xx(i,0); } }//ii = 0 through _nFunctions _timer.addToEigen(); variance[0] = (*_covariogram)(_kdTree.getData(dex), _kdTree.getData(dex)) + _lambda; for(i = 0; i < numberOfNeighbors; i++ )bb(i) = covarianceTestPoint[i]; xx = ldlt.solve(bb); for(i = 0; i < numberOfNeighbors; i++ ) { variance[0] -= covarianceTestPoint[i]*xx(i,0); } variance[0] = variance[0]*_krigingParameter; for(i = 1; i < _nFunctions; i++ )variance[i] = variance[0]; _timer.addToVariance(); _timer.addToTotal(1); } template < typename T > void GaussianProcess < T > ::batchInterpolate(ndarray::Array < T,1,1 > mu, ndarray:: Array < T,1,1 > variance, ndarray::Array < T,2,2 > const &queries) const { int i,j,ii,nQueries; T fbar; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > batchCovariance,batchbb,batchxx; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > queryCovariance; Eigen::LDLT < Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > > ldlt; ndarray::Array < T,1,1 > v1; _timer.start(); nQueries = queries.template getSize < 0 > (); v1 = allocate(ndarray::makeVector(_dimensions)); batchbb.resize(_pts, 1); batchxx.resize(_pts, 1); batchCovariance.resize(_pts, _pts); queryCovariance.resize(_pts, 1); for(i = 0; i < _pts; i++ ) { batchCovariance(i, i) = (*_covariogram)(_kdTree.getData(i), _kdTree.getData(i)) + _lambda; for(j = i + 1; j < _pts; j++ ) { batchCovariance(i, j) = (*_covariogram)(_kdTree.getData(i), _kdTree.getData(j)); batchCovariance(j, i) = batchCovariance(i, j); } } _timer.addToIteration(); ldlt.compute(batchCovariance); fbar = 0.0; for(i = 0; i < _pts; i++ ) { fbar += _function[i][0]; } fbar = fbar/T(_pts); for(i = 0; i < _pts; i++ ){ batchbb(i, 0) = _function[i][0] - fbar; } batchxx = ldlt.solve(batchbb); _timer.addToEigen(); for(ii = 0; ii < nQueries; ii++ ) { for(i = 0; i < _dimensions; i++ )v1[i] = queries[ii][i]; if(_useMaxMin == 1) { for(i = 0; i < _dimensions; i++ )v1[i] = (v1[i] - _min[i])/(_max[i] - _min[i]); } mu(ii) = fbar; for(i = 0; i < _pts; i++ ){ mu(ii) += batchxx(i)*(*_covariogram)(v1, _kdTree.getData(i)); } } _timer.addToIteration(); for(ii = 0; ii < nQueries; ii++ ) { for(i = 0; i < _dimensions; i++ )v1[i] = queries[ii][i]; if(_useMaxMin == 1) { for(i = 0; i < _dimensions; i++ )v1[i] = (v1[i] - _min[i])/(_max[i] - _min[i]); } for(i = 0; i < _pts; i++ ) { batchbb(i, 0) = (*_covariogram)(v1, _kdTree.getData(i)); queryCovariance(i, 0) = batchbb(i, 0); } batchxx = ldlt.solve(batchbb); variance[ii] = (*_covariogram)(v1, v1) + _lambda; for(i = 0; i < _pts; i++ ){ variance[ii] -= queryCovariance(i, 0)*batchxx(i); } variance[ii] = variance[ii]*_krigingParameter; } _timer.addToVariance(); _timer.addToTotal(nQueries); } template < typename T > void GaussianProcess < T > ::batchInterpolate(ndarray::Array < T,2,2 > mu, ndarray:: Array < T,2,2 > variance, ndarray::Array < T,2,2 > const &queries) const { int i,j,ii,nQueries,ifn; T fbar; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > batchCovariance,batchbb,batchxx; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > queryCovariance; Eigen::LDLT < Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > > ldlt; ndarray::Array < T,1,1 > v1; _timer.start(); nQueries = queries.template getSize < 0 > (); v1 = allocate(ndarray::makeVector(_dimensions)); batchbb.resize(_pts, 1); batchxx.resize(_pts, 1); batchCovariance.resize(_pts, _pts); queryCovariance.resize(_pts, 1); for(i = 0; i < _pts; i++ ){ batchCovariance(i, i) = (*_covariogram)(_kdTree.getData(i), _kdTree.getData(i)) + _lambda; for(j = i + 1; j < _pts; j++ ) { batchCovariance(i, j) = (*_covariogram)(_kdTree.getData(i), _kdTree.getData(j)); batchCovariance(j, i) = batchCovariance(i, j); } } _timer.addToIteration(); ldlt.compute(batchCovariance); _timer.addToEigen(); for(ifn = 0; ifn < _nFunctions; ifn++ ) { fbar = 0.0; for(i = 0; i < _pts; i++ ){ fbar += _function[i][ifn]; } fbar = fbar/T(_pts); _timer.addToIteration(); for(i = 0; i < _pts; i++ ){ batchbb(i,0) = _function[i][ifn] - fbar; } batchxx = ldlt.solve(batchbb); _timer.addToEigen(); for(ii = 0; ii < nQueries; ii++ ){ for(i = 0; i < _dimensions; i++ ) v1[i] = queries[ii][i]; if(_useMaxMin == 1) { for(i = 0; i < _dimensions; i++ ) v1[i] = (v1[i] - _min[i])/(_max[i] - _min[i]); } mu[ii][ifn] = fbar; for(i = 0; i < _pts; i++ ){ mu[ii][ifn] += batchxx(i)*(*_covariogram)(v1, _kdTree.getData(i)); } } }//ifn = 0 to _nFunctions _timer.addToIteration(); for(ii = 0; ii < nQueries; ii++ ){ for(i = 0; i < _dimensions; i++ ) v1[i] = queries[ii][i]; if(_useMaxMin == 1){ for(i = 0; i < _dimensions; i++ ) v1[i] = (v1[i] - _min[i])/(_max[i] - _min[i]); } for(i = 0;i < _pts;i++ ) { batchbb(i,0) = (*_covariogram)(v1,_kdTree.getData(i)); queryCovariance(i,0) = batchbb(i,0); } batchxx = ldlt.solve(batchbb); variance[ii][0] = (*_covariogram)(v1, v1) + _lambda; for(i = 0; i < _pts; i++ ) { variance[ii][0] -= queryCovariance(i, 0)*batchxx(i); } variance[ii][0] = variance[ii][0]*_krigingParameter; for(i = 1; i < _nFunctions; i++ ) variance[ii][i] = variance[ii][0]; } _timer.addToVariance(); _timer.addToTotal(nQueries); } template < typename T > void GaussianProcess < T > ::batchInterpolate(ndarray::Array < T,1,1 > mu, ndarray::Array < T,2,2 > const &queries) const { int i,j,ii,nQueries; T fbar; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > batchCovariance,batchbb,batchxx; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > queryCovariance; Eigen::LDLT < Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > > ldlt; ndarray::Array < T,1,1 > v1; _timer.start(); nQueries = queries.template getSize < 0 > (); v1 = allocate(ndarray::makeVector(_dimensions)); batchbb.resize(_pts, 1); batchxx.resize(_pts, 1); batchCovariance.resize(_pts, _pts); queryCovariance.resize(_pts, 1); for(i = 0; i < _pts; i++ ) { batchCovariance(i, i) = (*_covariogram)(_kdTree.getData(i), _kdTree.getData(i)) + _lambda; for(j = i + 1; j < _pts; j++ ) { batchCovariance(i, j) = (*_covariogram)(_kdTree.getData(i), _kdTree.getData(j)); batchCovariance(j, i) = batchCovariance(i, j); } } _timer.addToIteration(); ldlt.compute(batchCovariance); fbar = 0.0; for(i = 0; i < _pts; i++ ) { fbar += _function[i][0]; } fbar = fbar/T(_pts); for(i = 0; i < _pts; i++ ) { batchbb(i, 0) = _function[i][0] - fbar; } batchxx = ldlt.solve(batchbb); _timer.addToEigen(); for(ii = 0; ii < nQueries; ii++ ) { for(i = 0; i < _dimensions; i++ ) v1[i] = queries[ii][i]; if(_useMaxMin == 1) { for(i = 0; i < _dimensions; i++ )v1[i] = (v1[i] - _min[i])/(_max[i] - _min[i]); } mu(ii) = fbar; for(i = 0; i < _pts; i++ ) { mu(ii) += batchxx(i)*(*_covariogram)(v1, _kdTree.getData(i)); } } _timer.addToIteration(); _timer.addToTotal(nQueries); } template < typename T > void GaussianProcess < T > ::batchInterpolate(ndarray::Array < T,2,2 > mu, ndarray::Array < T,2,2 > const &queries) const { int i,j,ii,nQueries,ifn; T fbar; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > batchCovariance,batchbb,batchxx; Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > queryCovariance; Eigen::LDLT < Eigen::Matrix < T,Eigen::Dynamic,Eigen::Dynamic > > ldlt; ndarray::Array < T,1,1 > v1; _timer.start(); nQueries = queries.template getSize < 0 > (); v1 = allocate(ndarray::makeVector(_dimensions)); batchbb.resize(_pts, 1); batchxx.resize(_pts, 1); batchCovariance.resize(_pts, _pts); queryCovariance.resize(_pts, 1); for(i = 0; i < _pts; i++ ){ batchCovariance(i, i) = (*_covariogram)(_kdTree.getData(i), _kdTree.getData(i)) + _lambda; for(j = i + 1; j < _pts; j++ ){ batchCovariance(i, j) = (*_covariogram)(_kdTree.getData(i), _kdTree.getData(j)); batchCovariance(j, i) = batchCovariance(i, j); } } _timer.addToIteration(); ldlt.compute(batchCovariance); _timer.addToEigen(); for(ifn = 0; ifn < _nFunctions; ifn++ ){ fbar = 0.0; for(i = 0; i < _pts; i++ ){ fbar += _function[i][ifn]; } fbar = fbar/T(_pts); _timer.addToIteration(); for(i = 0; i < _pts; i++ ){ batchbb(i, 0) = _function[i][ifn] - fbar; } batchxx = ldlt.solve(batchbb); _timer.addToEigen(); for(ii = 0; ii < nQueries; ii++ ){ for(i = 0; i < _dimensions; i++ )v1[i] = queries[ii][i]; if(_useMaxMin == 1){ for(i = 0;i < _dimensions;i++ )v1[i] = (v1[i] - _min[i])/(_max[i] - _min[i]); } mu[ii][ifn] = fbar; for(i = 0; i < _pts; i++ ){ mu[ii][ifn] += batchxx(i)*(*_covariogram)(v1, _kdTree.getData(i)); } } }//ifn = 0 through _nFunctions _timer.addToTotal(nQueries); } template < typename T > void GaussianProcess < T > ::addPoint(ndarray::Array < T,1,1 > const &vin, T f) { int i,j; if(_nFunctions!= 1){
1704 63df72f1 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
? ---------
1704 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
"You are calling the wrong addPoint; you need a vector of functions\n"); } ndarray::Array < T,1,1 > v; v = allocate(ndarray::makeVector(_dimensions)); for(i = 0; i < _dimensions; i++ ){ v[i] = vin[i]; if(_useMaxMin == 1){ v[i] = (v[i] - _min[i])/(_max[i] - _min[i]); } } if(_pts == _room){ ndarray::Array < T,2,2 > buff; buff = allocate(ndarray::makeVector(_pts, _nFunctions)); buff.deep() = _function; _room += _roomStep; _function = allocate(ndarray::makeVector(_room, _nFunctions)); for(i = 0; i < _pts; i++ ) { for(j = 0; j < _nFunctions; j++ ) { _function[i][j] = buff[i][j]; } } } _function[_pts][0] = f; _kdTree.addPoint(v); _pts = _kdTree.getPoints(); } template < typename T > void GaussianProcess < T > ::addPoint(ndarray::Array < T,1,1 > const &vin, ndarray::Array < T,1,1 > const &f) { int i,j; ndarray::Array < T,1,1 > v; v = allocate(ndarray::makeVector(_dimensions)); for(i = 0; i < _dimensions; i++ ) { v[i] = vin[i]; if(_useMaxMin == 1) { v[i] = (v[i] - _min[i])/(_max[i] - _min[i]); } } if(_pts == _room) { ndarray::Array < T,2,2 > buff; buff = allocate(ndarray::makeVector(_pts, _nFunctions)); buff.deep() = _function; _room += _roomStep; _function = allocate(ndarray::makeVector(_room, _nFunctions)); for(i = 0; i < _pts; i++ ) { for(j = 0; j < _nFunctions; j++ ) { _function[i][j] = buff[i][j]; } } } for(i = 0; i < _nFunctions; i++ )_function[_pts][i] = f[i]; _kdTree.addPoint(v); _pts = _kdTree.getPoints(); } template < typename T > void GaussianProcess < T > ::removePoint(int dex) { int i,j; _kdTree.removePoint(dex); for(i = dex; i < _pts; i++ ) { for(j = 0; j < _nFunctions; j++ ) { _function[i][j] = _function[i + 1][j]; } } _pts = _kdTree.getPoints(); } template < typename T > void GaussianProcess < T > ::setKrigingParameter(T kk) { _krigingParameter = kk; } template < typename T > void GaussianProcess < T > ::setCovariogram(boost::shared_ptr < Covariogram < T > > const &covar){ _covariogram = covar; } template < typename T > void GaussianProcess < T > ::setLambda(T lambda){ _lambda = lambda; } template < typename T > GaussianProcessTimer& GaussianProcess < T > ::getTimes() const { return _timer; } template < typename T > Covariogram < T > ::~Covariogram(){}; template < typename T > T Covariogram < T > ::operator()(ndarray::Array < const T,1,1 > const &p1, ndarray::Array < const T,1,1 > const &p2) const { std::cout << "by the way, you are calling the wrong operator\n"; exit(1); return T(1.0); } template < typename T > SquaredExpCovariogram < T > ::~SquaredExpCovariogram(){} template < typename T > SquaredExpCovariogram < T > ::SquaredExpCovariogram() { _ellSquared = 1.0; } template < typename T > void SquaredExpCovariogram < T > ::setEllSquared(double ellSquared) { _ellSquared = ellSquared; } template < typename T > T SquaredExpCovariogram < T > ::operator()(ndarray::Array < const T,1,1 > const &p1, ndarray::Array < const T,1,1 > const &p2) const { int i; T d; d = 0.0; for(i = 0; i < p1.template getSize < 0 > (); i++ ){ d += (p1[i] - p2[i])*(p1[i] - p2[i]); } d = d/_ellSquared; return T(exp( - 0.5*d)); } template < typename T > NeuralNetCovariogram < T > ::~NeuralNetCovariogram(){} template < typename T > NeuralNetCovariogram < T > ::NeuralNetCovariogram(){ _sigma0 = 1.0; _sigma1 = 1.0; } template < typename T > T NeuralNetCovariogram < T > ::operator()(ndarray::Array < const T,1,1 > const &p1, ndarray::Array < const T,1,1 > const &p2 ) const { int i,dim; double num,denom1,denom2,arg; dim = p1.template getSize < 0 > (); num = 2.0*_sigma0; denom1 = 1.0 + 2.0*_sigma0; denom2 = 1.0 + 2.0*_sigma0; for(i = 0; i < dim; i++ ) { num += 2.0*p1[i]*p2[i]*_sigma1; denom1 += 2.0*p1[i]*p1[i]*_sigma1; denom2 += 2.0*p2[i]*p2[i]*_sigma1; } arg = num/::sqrt(denom1*denom2); return T(2.0*(::asin(arg))/3.141592654); } template < typename T > void NeuralNetCovariogram < T > ::setSigma0(double sigma0) { _sigma0 = sigma0; } template < typename T > void NeuralNetCovariogram < T > ::setSigma1(double sigma1) { _sigma1 = sigma1; } }}} #define gpn lsst::afw::math #define INSTANTIATEGP(T) \ template class gpn::KdTree < T > ; \ template class gpn::GaussianProcess < T > ; \ template class gpn::Covariogram < T > ; \ template class gpn::SquaredExpCovariogram < T > ;\ template class gpn::NeuralNetCovariogram < T > ; INSTANTIATEGP(double);

Return to list

Commits in /Users/nate/repos_hsc/afw/

63df72f1

commit 63df72f125543b4ce078cf2fa9b9392445d1cca1
Author: danielsf 
Date:   Thu Apr 25 15:01:53 2013 -0700

    I have implemented all of the functionality requested in the code review
    (except that GaussianProcessTimer remains)
    
    When I compile, I get a warning to the effect that I have not declared a shared_ptr
    for boost::noncopyable (from which Covariogram inherits)
    
    I still need to edit for style

bf63375f

commit bf63375f961e7ae959cdc980d099512e1742744e
Author: danielsf 
Date:   Thu Jan 9 10:48:41 2014 -0800

    added checks on numberOfNeighbors to the various interpolate methods

c7028ce7

commit c7028ce7248f6770d82d0c9fde2afdbb20ba8a7b
Author: danielsf 
Date:   Thu Jan 9 11:42:31 2014 -0800

    added check to selfInterpolate so that it tells you if you are asking to interpolate at a point that does not exist; also expanded the new unit test so that it checks all of the interpolation routines

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

include/lsst/afw/table/BaseTable.h

Diff:

                // -*- lsst-c++ -*-
                #ifndef AFW_TABLE_BaseTable_h_INCLUDED
                #define AFW_TABLE_BaseTable_h_INCLUDED
                
                #include "boost/enable_shared_from_this.hpp"
                
                #include "lsst/base.h"
                #include "lsst/daf/base/Citizen.h"
                #include "ndarray/Manager.h"
                #include "lsst/afw/table/fwd.h"
                #include "lsst/afw/table/Schema.h"
                
                namespace lsst { namespace afw {
                
                namespace fits {
                
                class Fits;
                
                } // namespace fits
                
                namespace table {
                
                /**
                 *  @brief Base class for all tables.
                 *
                 *  Tables have two largely distinct purposes:
                 *   - They serve as factories for records, allocating their field data in blocks.
                 *   - They carry additional information (such as the schema) that should be shared by multiple records.
                 *
                 *  It's mostly a matter of convenience that we use the same class to serve both needs.
                 *
                 *  Tables do not actually maintain a list of all the records they have allocated - but those records
                 *  hold a pointer back to the table.  This allows the work of holding and iterating over records to
                 *  be delegated to templated container classes (such as CatalogT) while allowing tables to be polymorphic,
                 *  non-template classes.  In some sense, then, it may make more sense to think of a table as a combination
                 *  factory and "container header".
                 *
                 *  Tables are always created in shared_ptrs (a requirement of enable_shared_from_this).  BaseTable provides
                 *  a make static member function to create a new table, and most derived table classes should do the same.
                 *
                 *  Each table class should be associated with a particular record class (1-to-1).  Each table instance may
                 *  be associated with many record instances.
                 */
                class BaseTable 
                #ifndef SWIG // swig complains about these not being %shared_ptrs, but it doesn't need to know about them
                : public boost::enable_shared_from_this,
                  public daf::base::Citizen
                #endif
                {
                public:
                
                    /// The associated record class.
                    typedef BaseRecord Record;
                    
                    /// The associated ColumnView class.
                    typedef BaseColumnView ColumnView;
                
                    /// Template of CatalogT used to hold records of the associated type.
                    typedef CatalogT Catalog;
                
                    /// Template of CatalogT used to hold const records of the associated type.
                    typedef CatalogT ConstCatalog;
                
                    /// @brief Number of records in each memory block.
                    static int nRecordsPerBlock;
                
                    /// @brief Return the flexible metadata associated with the table.  May be null.
                    PTR(daf::base::PropertyList) getMetadata() const { return _metadata; }
                
                    /// @brief Set the flexible metadata associated with the table.  May be null.
                    void setMetadata(PTR(daf::base::PropertyList) const & metadata) { _metadata = metadata; }
                
                    /// @brief Return the metadata and set the internal metadata to a null pointer.
                    PTR(daf::base::PropertyList) popMetadata() {
                        PTR(daf::base::PropertyList) tmp;
                        _metadata.swap(tmp);
                        return tmp;
                    }
                
                    /**
                     *  @brief Return a polymorphic deep copy of the table.
                     *
                     *  Derived classes should reimplement by static-casting the output of _clone to a
                     *  pointer-to-derived to simulate covariant return types.
                     *
                     *  Cloning a table does not clone its associated records; the new table produced by clone()
                     *  does not have any associated records.
                     */
                    PTR(BaseTable) clone() const { return _clone(); }
                
                    /**
                     *  @brief Default-construct an associated record.
                     *
                     *  Derived classes should reimplement by static-casting the output of _makeRecord to the
                     *  appropriate BaseRecord subclass to simulate covariant return types.
                     */
                    PTR(BaseRecord) makeRecord() { return _makeRecord(); }
                
                    /**
                     *  @brief Deep-copy a record, requiring that it have the same schema as this table.
                     *
                     *  Regardless of the type or associated table of the input record, the type of the output record
                     *  will be the type associated with this table and the record instance will be associated with
                     *  this table.
                     *
                     *  Allowing derived-class records to be constructed from base-class records could be considered
                     *  a form of type-slicing, but because we already demand that all records be constructable from
                     *  nothing but a table, this isn't anything new.
                     *
                     *  Derived classes should reimplement by static-casting the output of BaseTable::copyRecord to the
                     *  appropriate BaseRecord subclass.
                     *
                     *  This is implemented using makeRecord and calling record.assign on the results; override those
                     *  to change the behavior.
                     */
                    PTR(BaseRecord) copyRecord(BaseRecord const & input);
                
                    /**
                     *  @brief Deep-copy a record, using a mapper to relate two schemas.
                     *
                     *  @copydetails BaseTable::copyRecord(BaseRecord const &)
                     */
                    PTR(BaseRecord) copyRecord(BaseRecord const & input, SchemaMapper const & mapper);
124 12eb4fe1 -
124 4ff18d60 +
125 4ff18d60 + /// @brief Return the table's version.
126 bd692192 + int getVersion() const { return _schema.getVersion(); }
127 bd692192 +
/// @brief Return the table's schema. Schema getSchema() const { return _schema; } /** * @brief Allocate contiguous space for new records in advance. * * If a contiguous memory block for at least n additional records has already been allocated, * this is a no-op. If not, a new block will be allocated, and any remaining space on the old * block will go to waste; this ensures the new records will be allocated contiguously. Note * that "wasted" memory is not leaked; it will be deallocated along with any records * created from that block when those records go out of scope. * * Note that unlike std::vector::reserve, this does not factor in existing records in any way; * nRecords refers to a number of new records to reserve space for. */ void preallocate(std::size_t nRecords); /** * @brief Return the number of additional records space has been already been allocated for. * * Unlike std::vector::capacity, this does not factor in existing records in any way. */ std::size_t getBufferSize() const; /** * @brief Construct a new table. * * Because BaseTable is an abstract class, this actually returns a hidden trivial subclass * (which is associated with a hidden trivial subclass of BaseRecord). * * Hiding concrete table and record classes in anonymous namespaces is not required, but it * makes it easier to ensure instances are always created within shared_ptrs, * and it eliminates some multilateral friending that would otherwise be necessary. * In some cases it may also serve as a form of pimpl, keeping class implementation details * out of header files. */ static PTR(BaseTable) make(Schema const & schema);
163 3785bfe2 - virtual ~BaseTable() {}
? ^^^
166 028f751f + virtual ~BaseTable();
? ^ protected: /// @brief Convenience function for static-casting shared_from_this for use by derived classes. template PTR(Derived) getSelf() { return boost::static_pointer_cast(shared_from_this()); } /// @brief Convenience function for static-casting shared_from_this for use by derived classes. template CONST_PTR(Derived) getSelf() const { return boost::static_pointer_cast(shared_from_this()); }
181 03ea6486 +
182 028f751f + virtual void handleAliasChange(std::string const & alias) {}
/// @brief Clone implementation with noncovariant return types. virtual PTR(BaseTable) _clone() const = 0; /// @brief Default-construct an associated record (protected implementation). virtual PTR(BaseRecord) _makeRecord() = 0; /// @brief Construct from a schema. explicit BaseTable(Schema const & schema); /// @brief Copy construct. BaseTable(BaseTable const & other) : daf::base::Citizen(other), _schema(other._schema), _metadata(other._metadata) { if (_metadata) _metadata = boost::static_pointer_cast(_metadata->deepCopy()); } private:
198 12eb4fe1 -
203 028f751f +
friend class BaseRecord; friend class io::FitsWriter;
206 028f751f + friend class AliasMap;
// Called by BaseRecord ctor to fill in its _data, _table, and _manager members. void _initialize(BaseRecord & record); /* * Called by BaseRecord dtor to notify the table when it is about to be destroyed. * * This could allow the table to reclaim that space, but that requires more bookkeeping than * it's presently worth unless this was the most recently allocated record. * * The motivation for attempting to reclaim even some memory is not because we're paranoid * about using every last bit of allocated memory efficiently - it's so we can keep * records contiguous as much as possible to allow ColumnView to be used. */ void _destroy(BaseRecord & record); // Tables are not assignable to prevent type slicing; this is intentionally not implemented, // so we get linker errors if we do try to use the assignment operator. void operator=(BaseTable const & other); // Return a writer object that knows how to save in FITS format. See also FitsWriter. virtual PTR(io::FitsWriter) makeFitsWriter(fits::Fits * fitsfile, int flags) const; // All these are definitely private, not protected - we don't want derived classes mucking with them. Schema _schema; // schema that defines the table's fields ndarray::Manager::Ptr _manager; // current memory block to use for new records PTR(daf::base::PropertyList) _metadata; // flexible metadata; may be null }; }}} // namespace lsst::afw::table #endif // !AFW_TABLE_BaseTable_h_INCLUDED

Return to list

Commits in /Users/nate/repos_hsc/afw/

12eb4fe1

commit 12eb4fe1168de7f45068342d279e5c85f679bd33
Author: Jim Bosch 
Date:   Mon Jan 23 18:54:33 2012 -0500

    started rewrite of RecordBase/TableBase with aim of fixing constness and inheritance with an extra layer of indirection

3785bfe2

commit 3785bfe2fcf2a4e19fa033b0bbda944576064f03
Author: Jim Bosch 
Date:   Fri Jan 27 11:17:18 2012 -0500

    renamed TableBase, RecordBase to BaseTable, BaseRecord for symmetry

Commits in /Users/nate/repos_lsst/afw/

028f751f

commit 028f751fa3d0fe5101d2467942ea2e5229ba5200
Author: Jim Bosch 
Date:   Wed Jul 9 18:13:59 2014 -0400

    Notify owning tables when schema aliases are modified.

4ff18d60

commit 4ff18d602c2e595e9c8569d78a2fd5246c4145ce
Author: Perry Gee 
Date:   Fri Apr 4 00:24:27 2014 -0500

    Changes to create a versioning scheme for AFW_TABLE, and to save it to disk

03ea6486

commit 03ea6486684bf284f7428c2f7cec0fc15b7c6172
Author: Jim Bosch 
Date:   Thu Jan 26 18:11:15 2012 -0500

    afw now building successfully, but with limited SWIG for table and corresponding unit test failures

bd692192

commit bd692192367d33bb64a79ca008bff10eb9b41932
Author: pgee 
Date:   Mon Aug 18 15:06:04 2014 -0700

    Move API version number from BaseTable to Schema
    
    In FitsReader, move reading the AFW_TABLE_VERSION header key into the
    Schema-from-metadata constructor.
    In FitsWriter, use the version attached to the table schema to write the
    metadata.

Return to list

src/table/FieldBase.cc

Diff:

                // -*- lsst-c++ -*-
                
                #include 
                
                #include "boost/format.hpp"
                #include "boost/preprocessor/seq/for_each.hpp"
                #include "boost/preprocessor/tuple/to_seq.hpp"
                
                #include "lsst/afw/table/FieldBase.h"
                #include "lsst/afw/table/Flag.h"
                
                namespace lsst { namespace afw { namespace table {
                
                namespace {
                
                template  struct TypeTraits;
                
                template <> struct TypeTraits {
                    static char const * getName() { return "U"; }
                };
                template <> struct TypeTraits {
                    static char const * getName() { return "I"; }
                };
                template <> struct TypeTraits {
                    static char const * getName() { return "L"; }
                };
                template <> struct TypeTraits {
                    static char const * getName() { return "F"; }
                };
                template <> struct TypeTraits {
                    static char const * getName() { return "D"; }
                };
                template <> struct TypeTraits {
                    static char const * getName() { return "Angle"; }
                };
                template <> struct TypeTraits {
                    static char const * getName() { return "Coord"; }
                };
                
                } // anonyomous
                
                //----- POD scalars -----------------------------------------------------------------------------------------
                
                template 
                std::string FieldBase::getTypeString() {
                    return TypeTraits::getName();
                }
                
                //----- Point scalar ----------------------------------------------------------------------------------------
                
                template 
                std::string FieldBase< Point >::getTypeString() {
                    return (boost::format("Point%s") % TypeTraits::getName()).str();
                }
                
                //----- Point scalar ----------------------------------------------------------------------------------------
                
                std::string FieldBase< Coord >::getTypeString() { return "Coord"; }
                
                //----- Moments scalar --------------------------------------------------------------------------------------
                
                template 
                std::string FieldBase< Moments >::getTypeString() {
                    return (boost::format("Moments%s") % TypeTraits::getName()).str();
                }
                
                //----- POD array -------------------------------------------------------------------------------------------
                
                template 
                std::string FieldBase< Array >::getTypeString() {
                    return (boost::format("Array%s") % TypeTraits::getName()).str();
                }
                
                //----- POD covariance --------------------------------------------------------------------------------------
                
                template 
                std::string FieldBase< Covariance >::getTypeString() {
                    return (boost::format("Cov%s") % TypeTraits::getName()).str();
                }
                
                //----- Point covariance ------------------------------------------------------------------------------------
                
                template 
                std::string FieldBase< Covariance< Point > >::getTypeString() {
                    return (boost::format("CovPoint%s") % TypeTraits::getName()).str();
                }
                
                //----- Moments covariance ----------------------------------------------------------------------------------
                
                template 
                std::string FieldBase< Covariance< Moments > >::getTypeString() {
                    return (boost::format("CovMoments%s") % TypeTraits::getName()).str();
                }
                
                //----- String ----------------------------------------------------------------------------------------------
                
                FieldBase< std::string >::FieldBase(int size) : _size(size) {
                    if (size < 0) throw LSST_EXCEPT(
99 99ffef18 - lsst::pex::exceptions::LengthErrorException,
? ---------
99 21597d88 + lsst::pex::exceptions::LengthError,
"Size must be provided when constructing a string field." ); } std::string FieldBase< std::string >::getTypeString() { return "String"; } std::string FieldBase< std::string >::getValue(Element const * p, ndarray::Manager::Ptr const & m) const { Element const * end = p + _size; end = std::find(p, end, 0); return std::string(p, end); } void FieldBase< std::string >::setValue( Element * p, ndarray::Manager::Ptr const &, std::string const & value ) const { if (value.size() > std::size_t(_size)) { throw LSST_EXCEPT(
117 99ffef18 - lsst::pex::exceptions::LengthErrorException,
? ---------
117 21597d88 + lsst::pex::exceptions::LengthError,
(boost::format("String (%d) is too large for field (%d).") % value.size() % _size).str() ); } std::copy(value.begin(), value.end(), p); std::fill(p + value.size(), p + _size, char(0)); } //----- Explicit instantiation ------------------------------------------------------------------------------ #define INSTANTIATE_FIELD_BASE(r, data, elem) \ template struct FieldBase< elem >; BOOST_PP_SEQ_FOR_EACH( INSTANTIATE_FIELD_BASE, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_FIELD_TYPE_N, AFW_TABLE_FIELD_TYPE_TUPLE) ) }}} // namespace lsst::afw::table

Return to list

Commits in /Users/nate/repos_hsc/afw/

99ffef18

commit 99ffef18edcb18e8d841ec58b508bbd345f223b8
Author: Jim Bosch 
Date:   Sat Nov 24 23:37:19 2012 -0500

    Add support for string fields in afw::table, not including column arrays.  Also fixed botched merge of tableLib.i.

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

tests/ticket2026.py

Diff:

1 b057a671 - #!/usr/bin/env python
1 b80fe1d3 + #!/usr/bin/env python2
? +
2 b80fe1d3 + from __future__ import absolute_import, division
2 b057a671 -
3 b057a671 - import sys
4 b057a671 - import os
import unittest import lsst.utils.tests import lsst.afw.table as afwTable # Subtract 1 so that ids == indices def getids(c): return [s.getId()-1 for s in c] def printids(c): print getids(c) class IndexingCatalogTestCase(unittest.TestCase): def testSimpleCatalogType(self): schema = afwTable.SourceTable.makeMinimalSchema() table = afwTable.SourceTable.make(schema) catalog = afwTable.SourceCatalog(table) catalog.addNew() catcopy = catalog.copy() catsub = catalog[:] catsub2 = catalog.subset(0, 1, 1) print 'catalog', catalog print 'catcopy', catcopy print 'catsub', catsub print 'catsub2', catsub2 self.assertEqual(type(catalog), type(catcopy)) self.assertEqual(type(catalog), type(catsub)) self.assertEqual(type(catalog), type(catsub2)) def testMinusOne(self): schema = afwTable.SourceTable.makeMinimalSchema() table = afwTable.SourceTable.make(schema) catalog = afwTable.SourceCatalog(table) catalog.addNew() self.assertEqual(len(catalog), 1) catalog[-1] catalog.addNew() catalog.addNew() catalog[1] = catalog[2] del catalog[2] print catalog for src in catalog: print src.getId() self.assertEqual(len(catalog), 2) self.assertEqual(catalog[0].getId(), 1) self.assertEqual(catalog[1].getId(), 3) self.assertEqual(catalog[-1].getId(), 3) self.assertEqual(catalog[-2].getId(), 1) def assertSlice(self, cat, start, stop, step=None): if step is None: c = cat[start:stop] tru = range(10)[start:stop] else: c = cat[start:stop:step] tru = range(10)[start:stop:step] printids(c) self.assertEqual(getids(c), tru) def testSlice(self): schema = afwTable.SourceTable.makeMinimalSchema() table = afwTable.SourceTable.make(schema) catalog = afwTable.SourceCatalog(table) for i in range(10): catalog.addNew() print 'Catalog:', printids(catalog) print 'Empty range (4,4)' self.assertSlice(catalog, 4, 4) print 'Count by 2 (1,7,2)' self.assertSlice(catalog, 1, 7, 2) print 'Normal range (4,7)' self.assertSlice(catalog, 4, 7) print 'Normal range 2 (4,10)' self.assertSlice(catalog, 4, 10) print 'Normal range 3 (4,15)' self.assertSlice(catalog, 4, 15) print 'Negative indexed range (-20,-1)' self.assertSlice(catalog, -20, -1) print 'Negative end (1,-3)' self.assertSlice(catalog, 1, -3) print 'Negative step (6:1:-2)' self.assertSlice(catalog, 6, 1, -2) print 'Negative step (6:0:-2)' self.assertSlice(catalog, 6, 0 ,-2) print 'Negative step (-1:-12:-2)' self.assertSlice(catalog, -1, -12, -2) print 'Negative step (6:0:-1)' self.assertSlice(catalog, 6, 0, -1) print 'Negative step (6:-20:-1)' self.assertSlice(catalog, 6, -20, -1) print 'Negative step (6:-20:-2)' self.assertSlice(catalog, 6, -20, -2) print 'Negative step (5:-20:-2)' self.assertSlice(catalog, 5, -20, -2) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" lsst.utils.tests.init() suites = [] suites += unittest.makeSuite(IndexingCatalogTestCase) suites += unittest.makeSuite(lsst.utils.tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" lsst.utils.tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

Return to list

Commits in /Users/nate/repos_hsc/afw/

b057a671

commit b057a671c11eae19becd5e9a1818e641e20ea02e
Author: Dustin Lang 
Date:   Fri Apr 6 16:57:57 2012 -0500

    add failing test case demonstrating the ticket

Commits in /Users/nate/repos_lsst/afw/

b80fe1d3

commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
Author: Russell Owen 
Date:   Mon Oct 27 18:01:15 2014 -0700

    Support from __future__ import division
    for classes such as Extension that support operator/ and/or operator/=
    and change unit tests to use it

Return to list

src/geom/ellipses/Distortion.cc

Diff:

                // -*- lsst-c++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                #include "lsst/afw/geom/ellipses/Distortion.h"
                #include "lsst/afw/geom/ellipses/ReducedShear.h"
                #include "lsst/afw/geom/ellipses/ConformalShear.h"
                #include "lsst/afw/geom/ellipses/BaseCore.h"
                
                namespace lsst { namespace afw { namespace geom { namespace ellipses {
                
                double Distortion::getAxisRatio() const {
                    double e = getE();
                    return std::sqrt((1.0 - e) / (1.0 + e));
                }
                
                Distortion & Distortion::operator=(ConformalShear const & other) {
                    double eta = other.getE();
                    if (eta < 1E-8) {
                        _complex = other.getComplex() * (1.0 - eta * eta / 3.0);
                    } else {
                        double delta = std::tanh(eta);
                        _complex = other.getComplex() * delta / eta;
                    }
                    return *this;
                }
                
                Distortion & Distortion::operator=(ReducedShear const & other) {
                    double g = other.getE();
                    _complex = other.getComplex() * 2.0 / (1 + g * g);
                    return *this;
                }
                
                detail::EllipticityBase::Jacobian Distortion::dAssign(ConformalShear const & other) {
                    Jacobian result = Jacobian::Zero();
                    double eta = other.getE();
                    double alpha, beta;
                    if (eta < 1E-8) {
                        alpha = (1.0 - eta * eta / 3.0);
                        beta = -2.0 / 3.0;
                    } else {
                        double delta = std::tanh(eta);
                        alpha = delta / eta;
                        beta = (1.0 - delta * delta - alpha) / (eta * eta);
                    }
                    _complex = other.getComplex() * alpha;
                    result(0, 0) = alpha + other.getE1() * other.getE1() * beta;
                    result(1, 1) = alpha + other.getE2() * other.getE2() * beta;
                    result(1, 0) = result(0, 1) = other.getE1() * other.getE2() * beta;
                    return result;
                }
                
                detail::EllipticityBase::Jacobian Distortion::dAssign(ReducedShear const & other) {
                    Jacobian result = Jacobian::Zero();
                    double g = other.getE();
                    double alpha = 2.0 / (1 + g * g);
                    double beta = -alpha * alpha;
                    _complex = other.getComplex() * alpha;
                    result(0, 0) = alpha + other.getE1() * other.getE1() * beta;
                    result(1, 1) = alpha + other.getE2() * other.getE2() * beta;
                    result(1, 0) = result(0, 1) = other.getE1() * other.getE2() * beta;
                    return result;
                }
                
                void Distortion::normalize() {
                    if (getE() > 1.0) {
                        throw LSST_EXCEPT(
87 ce01a540 - lsst::pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
87 21597d88 + lsst::pex::exceptions::InvalidParameterError,
? ^^ ^ "Distortion magnitude cannot be greater than one." ); } } }}}} // namespace lsst::afw::geom::ellipses

Return to list

Commits in /Users/nate/repos_hsc/afw/

ce01a540

commit ce01a5406f327071e1701d534e563f0e75b870c4
Author: jbosch 
Date:   Wed Feb 2 01:27:08 2011 +0000

    afw #1556 - ellipses updated (#1551), but swig wrappers for ellipses now broken

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

include/lsst/afw/image/Wcs.h

Diff:

                // -*- LSST-C++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                
                #ifndef LSST_AFW_IMAGE_WCS_H
                #define LSST_AFW_IMAGE_WCS_H
                
                
                #include "Eigen/Core"
                #include "lsst/base.h"
                #include "lsst/daf/base/Persistable.h"
                #include "lsst/daf/base/Citizen.h"
                #include "lsst/afw/image/Image.h"
                #include "lsst/afw/coord/Coord.h"
                #include "lsst/afw/geom/AffineTransform.h"
                #include "lsst/afw/geom/Point.h"
                #include "lsst/afw/geom/Extent.h"
                #include "lsst/afw/geom/XYTransform.h"
                #include "lsst/afw/table/io/Persistable.h"
                
                struct wcsprm;                          // defined in wcs.h
                
                namespace lsst {
                namespace daf {
                    namespace base {
                        class PropertySet;
                    }
                }
                namespace afw {
                    namespace formatters {
                        class WcsFormatter;
                    }
                    namespace table {
                        class BaseRecord;
                    }
                namespace image {
                
                /// 
                /// @brief Implementation of the WCS standard for a any projection
                /// 
                /// Implements a single representation of the World Coordinate
                /// System of a two dimensional image  The standard is defined in two papers
                /// - Greisen & Calabretta, 2002 A&A 395, 1061
                /// - Calabretta & Greisen, 2002, A&A 395, 1077
                ///  
                /// In its simplest sense, Wcs is used to convert from position in the sky (in
                /// right ascension and declination) to pixel position on an image (and back
                /// again). It is, however, much more general than that and can understand a
                /// myriad of different coordinate systems.
                /// 
                /// A wcs can be constructed from a reference position (crval, crpix) and a
73 2b49698a - /// translation matrix. Alternatively, if you have the header from a fits file,
? ^^^^
73 191ee518 + /// translation matrix. Alternatively, if you have the header from a FITS file,
? ^^^^ /// you can create a Wcs object with the makeWcs() function. This function /// determines whether your Wcs is one the subset of projection systems that is
76 2b49698a - /// dealt with specially by Lsst, and creates an object of the correct
? ^^^
76 191ee518 + /// dealt with specially by LSST, and creates an object of the correct
? ^^^ /// class. Otherwise, a pointer to a Wcs object is returned. Most astronomical /// images use tangent plane projection, so makeWcs() returns a TanWcs object /// pointer /// /// \code /// import lsst.afw.image as afwImg /// fitsHeader = afwImg.readMetadata(filename) /// /// if 0: /// #This doesn't work /// wcs = afwImg.Wcs(fitsHeader) /// /// wcs = afwImg.makeWcs(fitsHeader) /// /// pixelPosition = wcs.skyToPixel(ra, dec) /// skyPosition = wcs.skyToPixel(xPosition, yPosition) /// \endcode /// /// /// o[ /// This class is implemented in by calls to the wcslib library /// by Mark Calabretta http://www.atnf.csiro.au/people/mcalabre/WCS/ ///
100 2b49698a - /// Note that we violate the Wcs standard in one minor way. The standard states
? ^^
100 191ee518 + /// Note that we violate the WCS standard in one minor way. The standard states
? ^^ /// that none of the CRPIX or CRVAL keywords are required, for the header to be /// valid, and the appropriate values should be set to 0.0 if the keywords are /// absent. This is a recipe for painful bugs in analysis, so we violate the /// standard by insisting that the keywords CRPIX[1,2] and CRVAL[1,2] are /// present when reading a header (keywords CRPIX1a etc are also accepted) class Wcs : public lsst::daf::base::Persistable, public lsst::daf::base::Citizen, public afw::table::io::PersistableFacade, public afw::table::io::Persistable { public: typedef boost::shared_ptr Ptr; typedef boost::shared_ptr ConstPtr; /**
117 74533ef4 - * @brief Create a Wcs of the correct class using a fits header.
? ^^^^
117 191ee518 + * @brief Create a Wcs of the correct class using a FITS header.
? ^^^^ * * Set stripMetadata=true to remove processed keywords from the PropertySet. */ friend Wcs::Ptr makeWcs(PTR(lsst::daf::base::PropertySet) const& fitsMetadata, bool stripMetadata); Wcs(lsst::afw::geom::Point2D const & crval, lsst::afw::geom::Point2D const & crpix, Eigen::Matrix2d const & CD, std::string const & ctype1="RA---TAN", std::string const & ctype2="DEC--TAN", double equinox=2000, std::string const & raDecSys="ICRS", std::string const & cunits1="deg", std::string const & cunits2="deg" ); virtual ~Wcs(); virtual Ptr clone(void) const; bool operator==(Wcs const & other) const; bool operator!=(Wcs const & other) const { return !(*this == other); }
137 74533ef4 - /// Returns CRVAL
137 191ee518 + /// Returns CRVAL. This need not be the centre of the image.
lsst::afw::coord::Coord::Ptr getSkyOrigin() const;
139 191ee518 +
/// Returns CRPIX (corrected to LSST convention). lsst::afw::geom::Point2D getPixelOrigin() const;
141 74533ef4 - /// Returns CD matrix. You would never have guessed that from the name.
142 191ee518 +
143 191ee518 + /// Returns the CD matrix.
Eigen::Matrix2d getCDMatrix() const;
145 191ee518 +
146 191ee518 + /// Flip CD matrix around the y-axis
virtual void flipImage(int flipLR, int flipTB, lsst::afw::geom::Extent2I dimensions) const;
148 191ee518 +
149 191ee518 + /// Rotate image by nQuarter times 90 degrees.
virtual void rotateImageBy90(int nQuarter, lsst::afw::geom::Extent2I dimensions) const; /// Return a PropertyList containing FITS header keywords that can be used to save the Wcs.x virtual PTR(lsst::daf::base::PropertyList) getFitsMetadata() const; /** * Does the Wcs follow the convention of North=Up, East=Left? *
152 74533ef4 - * This actually just measures the sign of the determinant of the CD matrix
153 74533ef4 - * to determine the "handedness" of the coordinate system.
158 191ee518 + * The conventional sense for a WCS image is to have North up and East to the left, or at least to be
159 191ee518 + * able to rotate the image to that orientation. It is possible to create a "flipped" WCS, where East
160 191ee518 + * points right when the image is rotated such that North is up. Flipping a WCS is akin to producing a
161 191ee518 + * mirror image. This function tests whether the image is flipped or not.
*/ bool isFlipped() const; /// Sky area covered by a pixel at position \c pix00 in units of square degrees. double pixArea(lsst::afw::geom::Point2D pix00) const; /// Returns the pixel scale [Angle/pixel] geom::Angle pixelScale() const;
163 74533ef4 - /// Convert from celestial coordinates to pixel coordinates.
171 191ee518 + /**
172 191ee518 + * @brief Convert from pixel position to sky coordinates (e.g. RA/dec)
173 191ee518 + *
174 191ee518 + * Convert a pixel position (e.g. x,y) to a celestial coordinate (e.g. RA/dec). The output coordinate
175 191ee518 + * system depends on the values of CTYPE used to construct the object. For RA/dec, the CTYPES should
176 191ee518 + * be RA---TAN and DEC--TAN.
177 191ee518 + */
PTR(coord::Coord) pixelToSky(double pix1, double pix2) const;
166 74533ef4 - /// Convert from celestial coordiantes to pixel coordinates.
180 74533ef4 + /**
181 191ee518 + * @brief Convert from pixel position to sky coordinates (e.g. RA/dec)
182 74533ef4 + *
183 191ee518 + * Convert a pixel position (e.g. x,y) to a celestial coordinate (e.g. RA/dec). The output coordinate
184 191ee518 + * system depends on the values of CTYPE used to construct the object. For RA/dec, the CTYPES should
185 191ee518 + * be RA---TAN and DEC--TAN.
186 191ee518 + */
PTR(coord::Coord) pixelToSky(lsst::afw::geom::Point2D const & pixel) const;
169 74533ef4 -
170 74533ef4 - /**
? -
189 191ee518 + /*
171 74533ef4 - * @brief Convert from celestial coordiantes to pixel coordinates.
190 191ee518 + * @brief Convert from pixel position to sky coordinates (e.g. RA/dec)
*
173 74533ef4 - *
174 74533ef4 - * @note This routine is designed for the knowledgeable user in need of
192 191ee518 + * @note This routine is designed for the knowledgeable user in need of performance;
? +++++++++++++
175 74533ef4 - * performance; it's safer to call the version that returns a PTR(Coord).
? -------------
193 191ee518 + * it's safer to call the version that returns a PTR(Coord).
*/ void pixelToSky( double pixel1, double pixel2, geom::Angle& sky1, geom::Angle& sky2 ) const;
198 191ee518 +
180 1b55259d -
199 74533ef4 + /**
? +++
181 74533ef4 - /**
182 74533ef4 - * @brief Convert from sky coordinates (e.g ra/dec) to pixel positions.
? ^^^ -
200 191ee518 + * @brief Convert from sky coordinates (e.g. RA/dec) to pixel positions
? ^^^^ *
202 191ee518 + * Convert a sky position (e.g. RA/dec) to a pixel position. The exact meaning of sky1, sky2
203 191ee518 + * and the return value depend on the properties of the wcs (i.e. the values of CTYPE1 and
204 191ee518 + * CTYPE2), but the inputs are usually RA/dec. The outputs are x and y pixel position.
205 74533ef4 + *
184 74533ef4 - * ASSUMES the angles are in the appropriate coordinate system for this WCS.
? ^^
206 191ee518 + * ASSUMES the angles are in the appropriate coordinate system for this Wcs.
? ^^ */ geom::Point2D skyToPixel(geom::Angle sky1, geom::Angle sky2) const;
188 251be71c - /// @brief Convert from sky coordinates (e.g ra/dec) to pixel positions.
? ^^^
210 191ee518 + /// @brief Convert from sky coordinates (e.g. RA/dec) to pixel positions.
? ^^^^ geom::Point2D skyToPixel(coord::Coord const & coord) const; /**
192 251be71c - * @brief Convert from sky coordinates (e.g ra/dec) to intermediate world coordinates
? ^^^
214 191ee518 + * @brief Convert from sky coordinates (e.g. RA/dec) to intermediate world coordinates
? ^^^^ * * Intermediate world coordinates are in DEGREES. */ geom::Point2D skyToIntermediateWorldCoord(coord::Coord const & coord) const;
197 1b55259d -
219 191ee518 +
virtual bool hasDistortion() const { return false;};
221 191ee518 +
199 1b55259d -
222 191ee518 + /**
? +++
223 191ee518 + * Return the linear part of the Wcs, the CD matrix in FITS-speak, as an AffineTransform.
224 191ee518 + */
geom::LinearTransform getLinearTransform() const;
201 1b55259d -
226 191ee518 +
/** * @brief Return the local linear approximation to Wcs::pixelToSky at a point given in sky coordinates. * * The local linear approximation is defined such the following is true (ignoring floating-point errors): * @code * wcs.linearizePixelToSky(sky, skyUnit)(wcs.skyToPixel(sky)) == sky.getPosition(skyUnit); * @endcode * (recall that AffineTransform::operator() is matrix multiplication with the augmented point (x,y,1)). * * This is currently implemented as a numerical derivative, but we should specialise the Wcs class * (or rather its implementation) to handle "simple" cases such as TAN-SIP analytically * * @param[in] coord Position in sky coordinates where transform is desired. * @param[in] skyUnit Units to use for sky coordinates; units of matrix elements will be skyUnits/pixel. */ geom::AffineTransform linearizePixelToSky( coord::Coord const & coord, geom::AngleUnit skyUnit = geom::degrees ) const; /** * @brief Return the local linear approximation to Wcs::pixelToSky at a point given in pixel coordinates. * * The local linear approximation is defined such the following is true (ignoring floating-point errors): * @code * wcs.linearizePixelToSky(pix, skyUnit)(pix) == wcs.pixelToSky(pix).getPosition(skyUnit) * @endcode * (recall that AffineTransform::operator() is matrix multiplication with the augmented point (x,y,1)). * * This is currently implemented as a numerical derivative, but we should specialise the Wcs class * (or rather its implementation) to handle "simple" cases such as TAN-SIP analytically * * @param[in] pix Position in pixel coordinates where transform is desired. * @param[in] skyUnit Units to use for sky coordinates; units of matrix elements will be skyUnits/pixel. */ geom::AffineTransform linearizePixelToSky( geom::Point2D const & pix, geom::AngleUnit skyUnit = geom::degrees ) const; /** * @brief Return the local linear approximation to Wcs::skyToPixel at a point given in sky coordinates. * * The local linear approximation is defined such the following is true (ignoring floating-point errors): * @code * wcs.linearizeSkyToPixel(sky, skyUnit)(sky.getPosition(skyUnit)) == wcs.skyToPixel(sky) * @endcode * (recall that AffineTransform::operator() is matrix multiplication with the augmented point (x,y,1)). * * This is currently implemented as a numerical derivative, but we should specialise the Wcs class * (or rather its implementation) to handle "simple" cases such as TAN-SIP analytically * * @param[in] coord Position in sky coordinates where transform is desired. * @param[in] skyUnit Units to use for sky coordinates; units of matrix elements will be pixels/skyUnit. */ geom::AffineTransform linearizeSkyToPixel( coord::Coord const & coord, geom::AngleUnit skyUnit = geom::degrees ) const; /** * @brief Return the local linear approximation to Wcs::skyToPixel at a point given in pixel coordinates. * * The local linear approximation is defined such the following is true (ignoring floating-point errors): * @code * wcs.linearizeSkyToPixel(pix, skyUnit)(wcs.pixelToSky(pix).getPosition(skyUnit)) == pix * @endcode * (recall that AffineTransform::operator() is matrix multiplication with the augmented point (x,y,1)). * * This is currently implemented as a numerical derivative, but we should specialise the Wcs class * (or rather its implementation) to handle "simple" cases such as TAN-SIP analytically * * @param[in] pix Position in pixel coordinates where transform is desired. * @param[in] skyUnit Units to use for sky coordinates; units of matrix elements will be pixels/skyUnit.
276 251be71c - */
301 191ee518 + */
geom::AffineTransform linearizeSkyToPixel( geom::Point2D const & pix, geom::AngleUnit skyUnit = geom::degrees ) const;
282 1b55259d - //Mutators
307 3e709686 + // Mutators; the first one is virtual, even though it will never be overridden,
308 3e709686 + // to make sure subclasses use the correct version of both
309 191ee518 +
310 191ee518 + /**
311 191ee518 + * @brief Move the pixel reference position by (dx, dy)
312 191ee518 + *
313 191ee518 + * Used when persisting and retrieving sub-images. The LSST convention is that Wcs returns pixel position
314 191ee518 + * (which is based on position in the parent image), but the FITS convention is to return pixel index
315 191ee518 + * (which is bases on position in the sub-image). In order that the FITS files we create make sense
316 191ee518 + * to other FITS viewers, we change to the FITS convention when writing out images.
317 191ee518 + */
318 04cbfea6 + virtual void shiftReferencePixel(double dx, double dy);
319 a454b111 +
320 191ee518 + // Virtual to make sure subclasses use the correct version of both shiftReferencePixel mutators.
283 c9c89e06 - void shiftReferencePixel(geom::Extent2D const & d) {shiftReferencePixel(d.getX(), d.getY());}
321 191ee518 + virtual void shiftReferencePixel(geom::Extent2D const & d) { shiftReferencePixel(d.getX(), d.getY()); }
? ++++++++ + +
284 3263f939 - void shiftReferencePixel(double dx, double dy);
/// @brief Whether the Wcs is persistable using afw::table::io archives. virtual bool isPersistable() const; private: //Allow the formatter to access private goo LSST_PERSIST_FORMATTER(lsst::afw::formatters::WcsFormatter) void initWcsLib(geom::Point2D const & crval, geom::Point2D const & crpix, Eigen::Matrix2d const & CD, std::string const & ctype1, std::string const & ctype2, double equinox, std::string const & raDecSys, std::string const & cunits1, std::string const & cunits2 );
300 74533ef4 - virtual void pixelToSkyImpl(double pixel1, double pixel2, geom::Angle skyTmp[2]) const;
301 74533ef4 - virtual geom::Point2D skyToPixelImpl(geom::Angle sky1, geom::Angle sky2) const;
302 e8b0ec03 -
protected: friend class WcsFactory; // See afw::table::io::Persistable virtual std::string getPersistenceName() const; virtual std::string getPythonModule() const; virtual void write(OutputArchiveHandle & handle) const; // Protected virtual implementation for operator== (must be true in both directions for equality). virtual bool _isSubset(Wcs const & other) const; // Default constructor, only used by WcsFormatter Wcs();
318 1b55259d - //If you want to create a Wcs from a fits header, use makeWcs().
? ^^^^ -
352 191ee518 + //If you want to create a Wcs from a FITS header, use makeWcs().
? ^^^^ //This is protected because the derived classes need to be able to see it. Wcs(CONST_PTR(lsst::daf::base::PropertySet) const& fitsMetadata); // Construct from a record; used by WcsFactory for afw::table::io persistence. explicit Wcs(afw::table::BaseRecord const & record); Wcs(Wcs const & rhs); Wcs& operator= (const Wcs &);
361 a0b9d98c +
362 a0b9d98c + virtual void pixelToSkyImpl(double pixel1, double pixel2, geom::Angle skyTmp[2]) const;
363 a0b9d98c + virtual geom::Point2D skyToPixelImpl(geom::Angle sky1, geom::Angle sky2) const;
afw::coord::Coord::Ptr makeCorrectCoord(geom::Angle sky0, geom::Angle sky1) const; /** * Given a Coord (as a shared pointer), return the sky position in the correct * coordinate system for this Wcs. */ afw::coord::Coord::Ptr convertCoordToSky(coord::Coord const & coord) const; virtual geom::AffineTransform linearizePixelToSkyInternal( geom::Point2D const & pix, coord::Coord const & coord, geom::AngleUnit skyUnit ) const; virtual geom::AffineTransform linearizeSkyToPixelInternal( geom::Point2D const & pix, coord::Coord const & coord, geom::AngleUnit skyUnit ) const; void initWcsLibFromFits(CONST_PTR(lsst::daf::base::PropertySet) const& fitsMetadata); void _initWcs(); void _setWcslibParams(); struct wcsprm* _wcsInfo; int _nWcsInfo; int _relax; ///< Degree of permissiveness for wcspih (0 for strict); see wcshdr.h for details. int _wcsfixCtrl; ///< Do potentially unsafe translations of non-standard unit strings? 0/1 = no/yes int _wcshdrCtrl; ///< Controls messages to stderr from wcshdr (0 for none); see wcshdr.h for details int _nReject; coord::CoordSystem _coordSystem; }; namespace detail { PTR(lsst::daf::base::PropertyList) createTrivialWcsAsPropertySet(std::string const& wcsName, int const x0=0, int const y0=0); geom::Point2I getImageXY0FromMetadata(std::string const& wcsName, lsst::daf::base::PropertySet *metadata); } Wcs::Ptr makeWcs(PTR(lsst::daf::base::PropertySet) const& fitsMetadata, bool stripMetadata=false); /* Note, CD matrix elements must be in degrees/pixel. */ Wcs::Ptr makeWcs(coord::Coord const & crval, geom::Point2D const & crpix, double CD11, double CD12, double CD21, double CD22); namespace detail { int stripWcsKeywords(PTR(lsst::daf::base::PropertySet) const& metadata, ///< Metadata to be stripped CONST_PTR(Wcs) const& wcs ///< A Wcs with (implied) keywords ); } /**
385 d95640da - * @brief XYTransformFromWcsPair: Represents an XYTransform obtained by putting two Wcs's "back to back".
? ^^^^^^^ ----- ^
422 191ee518 + * @brief XYTransformFromWcsPair: An XYTransform obtained by putting two Wcs objects "back to back".
? ^ ^^^^^^^ * * Eventually there will be an XYTransform subclass which represents a camera distortion. * For now we can get a SIP camera distortion in a clunky way, by using an XYTransformFromWcsPair * with a SIP-distorted TanWcs and an undistorted Wcs. *
391 d95640da - * Note: this is very similar to class afw::math::detail::WcsSrcPosFunctor
? ---
428 624db730 + * Note: this is very similar to class afw::math::detail::WcsPositionFunctor
? +++++ * but watch out since the XY0 offset convention is different!! */ class XYTransformFromWcsPair : public afw::geom::XYTransform { public: XYTransformFromWcsPair(CONST_PTR(Wcs) dst, CONST_PTR(Wcs) src); virtual ~XYTransformFromWcsPair() { } virtual PTR(afw::geom::XYTransform) invert() const; /// The following methods are needed to devirtualize the XYTransform parent class virtual PTR(afw::geom::XYTransform) clone() const; virtual Point2D forwardTransform(Point2D const &pixel) const; virtual Point2D reverseTransform(Point2D const &pixel) const; protected: CONST_PTR(Wcs) _dst; CONST_PTR(Wcs) _src; }; }}} // lsst::afw::image #endif // LSST_AFW_IMAGE_WCS_H // LocalWords: LSST

Return to list

Commits in /Users/nate/repos_hsc/afw/

d95640da

commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
Author: Kendrick Smith 
Date:   Tue Feb 19 23:44:14 2013 -0500

    move afw::image::XYTransform -> afw::geom::XYTransform
         afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
         afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
    
    wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom

251be71c

commit 251be71c68bf8814a927efe8af85ea36e65414ad
Author: Jim Bosch 
Date:   Tue Feb 21 12:10:10 2012 -0500

    added const reference overloads for Wcs member functions that take a Coord object, deprecated those that take a Coord::ConstPtr, and made the latter delegate to the former

1b55259d

commit 1b55259dfbd4c11afe550786186b041d712c3ff3
Author: bick 
Date:   Sat Oct 9 19:48:06 2010 +0000

    #1453 Added py-test for createWcs() (should depricate), added identical makeWcs() API.

2b49698a

commit 2b49698aac5268bff502c3c48061f1e547db9a29
Author: dstn 
Date:   Tue May 10 17:32:05 2011 +0000

    CRVAL is a Coord; pixel scale is an Angle; make SourceMatch use Angle also (mostly)

c9c89e06

commit c9c89e060322883ace8599bf9b3584a73ac25d7b
Author: jbosch 
Date:   Tue Mar 8 23:14:46 2011 +0000

    afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms

e8b0ec03

commit e8b0ec03aa0d945974517d5075eece12512c664b
Author: jbosch 
Date:   Mon Aug 30 23:46:35 2010 +0000

    afw/1130 - new API for Wcs linearization; implementation done, need to add tests

3263f939

commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
Author: dubcovsky 
Date:   Thu Feb 24 00:56:41 2011 +0000

    #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet

74533ef4

commit 74533ef4645b80ab0095f60b25f56737204bf577
Author: Jim Bosch 
Date:   Thu Dec 6 20:28:41 2012 -0500

    Fix more documentation, Ptr usage in TanWcs and Wcs.

Commits in /Users/nate/repos_lsst/afw/

3e709686

commit 3e709686d5e305921dd503396f195147d79be650
Author: Russell Owen 
Date:   Wed Feb 11 15:55:16 2015 -0800

    Fix a C++ issue in shadowing a method of Wcs

74533ef4

commit 74533ef4645b80ab0095f60b25f56737204bf577
Author: Jim Bosch 
Date:   Thu Dec 6 20:28:41 2012 -0500

    Fix more documentation, Ptr usage in TanWcs and Wcs.

624db730

commit 624db730b18aee1cfa2bed9d4b6c64a67da00a26
Author: Steven Bickerton 
Date:   Tue Feb 18 18:24:47 2014 +0900

    renamed SrcPosFunctor -> PositionFunctor

191ee518

commit 191ee518a0e63d5c563aa62bfdf673ff70c5a44d
Author: John Swinbank 
Date:   Fri Mar 20 11:27:35 2015 -0400

    Clean up documentation of Wcs.
    
    Remove duplication between Wcs.cc and Wcs.h (which results in duplicate text
    in Doxygen output).
    
    Correct contradictory/incorrect documentation (notably, repeated claims that
    pixelToSky converts *from* sky *to* pixel coordinates).

a0b9d98c

commit a0b9d98c33134ce69b177a9b6b6260de9f2bccfd
Author: Russell Owen 
Date:   Thu Jan 22 17:41:16 2015 -0800

    Added DistortedTanWcs and a unit test.
    
    fixup! Added DistortedTanWcs and a preliminary unit test.
    
    Fixed some incorrect names in DistortedTanWcs and improved argument names accordingly.
    
    Ignore _build files

04cbfea6

commit 04cbfea652c046ea1ad62e45816c1dc6c9f6209b
Author: Russell Owen 
Date:   Wed Feb 11 08:58:28 2015 -0800

    Implemented reviewer comments

a454b111

commit a454b1115b1084ea425dc9c6d2a7dc02ec6f735d
Author: fergal 
Date:   Thu Jun 11 19:43:34 2009 +0000

    Added printSip for debugging purposes

Return to list

include/lsst/afw/gpu/detail/GpuBuffer2D.h

Diff:

                // -*- LSST-C++ -*-
                
                /*
                 * LSST Data Management System
                 * Copyright 2008 - 2012 LSST Corporation.
                 *
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 *
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 *
                 * You should have received a copy of the LSST License Statement and
                 * the GNU General Public License along with this program.  If not,
                 * see .
                 */
                
                /**
                 * @file
                 *
                 * @brief contains GpuBuffer2D class (for simple handling of images or 2D arrays)
                 *
                 * @author Kresimir Cosic
                 *
                 * @ingroup afw
                 */
                
                namespace lsst {
                namespace afw {
                namespace gpu {
                namespace detail {
                
                /**
                 * @brief Class for representing an image or 2D array in general)
                 *
                 * Allocates width*height pixels memory for image. Automatically allocates and
                 * releases memory for buffer (this class is the owner of the buffer).
                 *
                 * Can be uninitialized. Only uninitialized image buffer can be copied.
                 * For copying initialized image buffers, use CopyFromBuffer member function.
                 * Provides access to pixels and lines in image
                 * Can be copied to and from the Image.
                 *
                 * @ingroup afw
                 */
                template 
                class GpuBuffer2D
                {
                public:
                    typedef lsst::afw::image::Image  ImageT;
                
                    PixelT*     img;
                    int         width;
                    int         height;
                
                    GpuBuffer2D() : img(NULL) {}
                
                    //copying is not allowed except for uninitialized image buffers
                    GpuBuffer2D(const GpuBuffer2D& x) {
                        assert(x.img == NULL);
                        img = NULL;
                    };
                
                    void Init(const ImageT& image)
                    {
                        assert(img == NULL);
                        this->width = image.getWidth();
                        this->height = image.getHeight();
                        try {
                            img = new PixelT [width*height];
                        } catch(...) {
79 d0c9ef27 - throw LSST_EXCEPT(pexExcept::MemoryException, "GpuBuffer2D:Init - not enough memory");
? ^^^^^^ ^
79 21597d88 + throw LSST_EXCEPT(pexExcept::MemoryError, "GpuBuffer2D:Init - not enough memory");
? ^^ ^ } //copy input image data to buffer for (int i = 0; i < height; ++i) { typename ImageT::x_iterator inPtr = image.x_at(0, i); PixelT* imageDataPtr = img + i * width; for (typename ImageT::x_iterator cnvEnd = inPtr + width; inPtr != cnvEnd; ++inPtr, ++imageDataPtr) { *imageDataPtr = *inPtr; } } } void Init(int width, int height) { assert(img == NULL); this->width = width; this->height = height; try { img = new PixelT [width*height]; } catch(...) {
101 d0c9ef27 - throw LSST_EXCEPT(pexExcept::MemoryException, "GpuBuffer2D:Init - not enough memory");
? ^^^^^^ ^
101 21597d88 + throw LSST_EXCEPT(pexExcept::MemoryError, "GpuBuffer2D:Init - not enough memory");
? ^^ ^ } } GpuBuffer2D(const ImageT& image) { img = NULL; Init(image); } GpuBuffer2D(int width, int height) { img = NULL; Init(width, height); } ~GpuBuffer2D() { delete[] img; } int Size() const { return width * height; } PixelT* GetImgLinePtr(int y) { assert(img != NULL); assert(y >= 0 && y < height); return &img[width*y]; } const PixelT* GetImgLinePtr(int y) const { assert(img != NULL); assert(y >= 0 && y < height); return &img[width*y]; } PixelT& Pixel(int x, int y) { assert(img != NULL); assert(x >= 0 && x < width); assert(y >= 0 && y < height); return img[x+ y*width]; } const PixelT& Pixel(int x, int y) const { assert(img != NULL); assert(x >= 0 && x < width); assert(y >= 0 && y < height); return img[x+ y*width]; } void CopyFromBuffer(const GpuBuffer2D& buffer, int startX, int startY) { assert(img != NULL); for (int i = 0; i < height; ++i) { PixelT* inPtr = startX + buffer.GetImgLinePtr(i + startY); PixelT* outPtr = buffer.GetImgLinePtr(i); for (int j = 0; j < width; j++) { *outPtr = *inPtr; inPtr++; outPtr++; } } } void CopyToImage(ImageT outImage, int startX, int startY) { assert(img != NULL); for (int i = 0; i < height; ++i) { PixelT* outPtrImg = &img[width*i]; for (typename ImageT::x_iterator cnvPtr = outImage.x_at(startX, i + startY), cnvEnd = cnvPtr + width; cnvPtr != cnvEnd; ++cnvPtr ) { *cnvPtr = *outPtrImg; ++outPtrImg; } } } }; } } } } //namespace lsst::afw::math::detail ends

Return to list

Commits in /Users/nate/repos_hsc/afw/

d0c9ef27

commit d0c9ef27075669b15f7a5b6ae454e54463a214e6
Author: Kresimir Cosic 
Date:   Wed Apr 4 11:52:45 2012 +0200

    Renamed ImageBuffer to GpuBuffer2D

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

python/lsst/afw/table/Match.i

Diff:

                // -*- lsst-c++ -*-
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                
24 3252a40a - %include "lsst/pex/config.h" // LSST_CONTROL_FIELD
25 3252a40a -
/* * Wrappers for the Match object and matching functions, including instantiation of SimpleMatch, SourceMatch, * and ReferenceMatch. */ %include "lsst/afw/table/Source.i" %{ #include "lsst/afw/table/Match.h" %} %include "lsst/afw/table/Match.h" %extend lsst::afw::table::Match {
40 7c5f68d9 - %pythoncode {
38 81c3bd10 + %pythoncode %{
? + def __repr__(self): return "Match(%s,\n %s,\n %g)" % \ (repr(self.first), repr(self.second), self.distance) def __str__(self):
46 7c5f68d9 - s1, s2 = self.first, self.second
47 f7e652f5 - return "((id %d, RA,Dec (%g,%g) deg; X,Y (%g,%g))\n (id %d, RA,Dec (%g,%g) deg; X,Y (%g,%g))\n dist %g [pix or radians])" % (
48 8d70f429 - s1.getId(), s1.getRa().asDegrees(), s1.getDec().asDegrees(), s1.getX(), s1.getY(),
49 8d70f429 - s2.getId(), s2.getRa().asDegrees(), s2.getDec().asDegrees(), s2.getX(), s2.getY(),
50 f7e652f5 - self.distance)
44 b4c7305a + sourceRaDec = lambda s: ((" RA,Dec=(%g,%g) deg" % (s.getRa().asDegrees(), s.getDec().asDegrees())) if
45 b4c7305a + hasattr(s, "getRa") and hasattr(s, "getDec") else "")
46 b4c7305a + sourceXy = lambda s: ((" x,y=(%g,%g)" % (s.getX(), s.getY())) if
47 b4c7305a + hasattr(s, "getX") and hasattr(s, "getY") else "")
48 b4c7305a + sourceStr = lambda s: (s.__class__.__name__ + ("(id %d" % s.getId()) + sourceRaDec(s) +
49 b4c7305a + sourceXy(s) + ")")
50 b4c7305a +
51 b4c7305a + return "Match(%s, %s, dist %g)" % (sourceStr(self.first), sourceStr(self.second), self.distance,)
def __getitem__(self, i): """Treat a Match as a tuple of length 3: (first, second, distance)""" if i > 2 or i < -3: raise IndexError(i) if i < 0: i += 3 if i == 0: return self.first elif i == 1: return self.second else: return self.distance def __setitem__(self, i, val): """Treat a Match as a tuple of length 3: (first, second, distance)""" if i > 2 or i < -3: raise IndexError(i) if i < 0: i += 3 if i == 0: self.first = val elif i == 1: self.second = val else: self.distance = val def __len__(self): return 3 def clone(self): return self.__class__(self.first, self.second, self.distance) def __getstate__(self): return self.first, self.second, self.distance def __setstate__(self, state): self.__init__(*state)
91 e9b96e09 - }
92 81c3bd10 + %}
? + } %define %declareMatch(NAME, R1, R2) %template(NAME##Match) lsst::afw::table::Match; %template(NAME##MatchVector) std::vector< lsst::afw::table::Match >; %extend std::vector< lsst::afw::table::Match > {
102 c5c122fa - %pythoncode {
103 81c3bd10 + %pythoncode %{
? + def __getstate__(self): """Pickler""" if not self: return () firstSchema = self[0].first.schema secondSchema = self[0].second.schema firstTable = self[0].first.table secondTable = self[0].second.table first = R1##Catalog(firstSchema) second = R2##Catalog(secondSchema) distance = [] for match in self: first.append(match.first) second.append(match.second) distance.append(match.distance)
118 c5c122fa -
119 c5c122fa - from lsst.pex.exceptions import LsstCppException, NotFoundException
120 c5c122fa - def getSlot(table, name):
121 c5c122fa - """Return key for a slot, specified by name, or None"""
122 c5c122fa - getter = getattr(table, "get" + name + "Key", None)
123 c5c122fa - if getter is None:
124 c5c122fa - return None
125 c5c122fa - try:
126 c5c122fa - return getter()
127 c5c122fa - except LsstCppException as e:
128 c5c122fa - if isinstance(e.message, NotFoundException):
129 c5c122fa - return None
130 c5c122fa - raise
131 c5c122fa -
132 c5c122fa - def copySlots(tableFrom, tableTo):
133 c5c122fa - """Copy slots from one table to another
134 c5c122fa -
135 c5c122fa - Slots are identified from the method names ("define")
136 c5c122fa - and assumed to carry measurement, error and flag parts.
137 c5c122fa - """
138 c5c122fa - import re
139 c5c122fa - getKey = lambda x: getattr(tableFrom, x)() if hasattr(tableFrom, x) else None
140 c5c122fa - for method in dir(tableTo):
141 c5c122fa - m = re.search(r"define(?P.+)", method)
142 c5c122fa - if not m:
143 c5c122fa - continue
144 c5c122fa - name = m.group("name")
145 c5c122fa - meas = getSlot(tableFrom, name)
146 c5c122fa - err = getSlot(tableFrom, name + "Err")
147 c5c122fa - flag = getSlot(tableFrom, name + "Flag")
148 c5c122fa - setter = getattr(tableTo, "define" + name, None)
149 c5c122fa - if setter is not None:
150 c5c122fa - setter(meas, err, flag)
151 c5c122fa -
152 c5c122fa - copySlots(firstTable, first.table)
153 c5c122fa - copySlots(secondTable, second.table)
return (first, second, distance) def __setstate__(self, state): """Unpickler""" first, second, distance = state self.__init__([NAME##Match(f,s,d) for f,s,d in zip(first, second, distance)])
160 c5c122fa - }
125 81c3bd10 + %}
? + } // swig can't parse the template declarations for these because of the nested names in the // return values, so we repeat them here and pretend they aren't templates, using typedefs // that swig can understand. namespace lsst { namespace afw { namespace table { NAME##MatchVector matchRaDec( R1##Catalog const & cat1, R2##Catalog const & cat2, Angle radius, bool closest=true
173 4c363d4e - );
174 3252a40a - NAME##MatchVector matchRaDec(
175 3252a40a - R1##Catalog const & cat1,
176 3252a40a - R2##Catalog const & cat2,
177 3252a40a - Angle radius, MatchControl const& mc=MatchControl()
); NAME##MatchVector unpackMatches( BaseCatalog const & matches, R1##Catalog const & cat1, R2##Catalog const & cat2 ); }}} // namespace lsst::afw::table %enddef %declareMatch(Simple, Simple, Simple) %declareMatch(Reference, Simple, Source) %declareMatch(Source, Source, Source) namespace lsst { namespace afw { namespace table { SimpleMatchVector matchRaDec( SimpleCatalog const & cat,
198 3252a40a - Angle radius, MatchControl const& mc=MatchControl()
158 4c363d4e + Angle radius, bool symmetric=true
); SourceMatchVector matchRaDec( SourceCatalog const & cat,
203 3252a40a - Angle radius, MatchControl const& mc=MatchControl()
204 4c363d4e - );
205 3252a40a -
206 3252a40a - SimpleMatchVector matchRaDec(
207 3252a40a - SimpleCatalog const & cat,
208 3252a40a - Angle radius, bool symmetric
163 4c363d4e + Angle radius, bool symmetric=true
? +++++ );
211 3252a40a - SourceMatchVector matchRaDec(
? ^^^^^
166 4c363d4e + SourceMatchVector matchXy(
? ^^
167 4c363d4e + SourceCatalog const & cat1,
168 4c363d4e + SourceCatalog const & cat2,
169 4c363d4e + double radius, bool closest=true
170 4c363d4e + );
171 4c363d4e +
172 4c363d4e + SourceMatchVector matchXy(
SourceCatalog const & cat,
213 3252a40a - Angle radius, bool symmetric
? ^^^
174 4c363d4e + double radius, bool symmetric=true
? ^^^^ +++++ ); }}} // namespace lsst::afw::table // swig can't disambiguate between the different packMatches overloads (which is actually // understandable, because they'd all match a Python list), so instead we provide // a pure-Python implementation that works on any sequence. %pythoncode %{ def packMatches(matches): schema = Schema() outKey1 = schema.addField("first", type="L", doc="ID for first source record in match.") outKey2 = schema.addField("second", type="L", doc="ID for second source record in match.") keyD = schema.addField("distance", type=float, doc="Distance between matches sources.") result = BaseCatalog(schema) result.table.preallocate(len(matches)) for match in matches: record = result.addNew() record.set(outKey1, match.first.getId()) record.set(outKey2, match.second.getId()) record.set(keyD, match.distance) return result %}

Return to list

Commits in /Users/nate/repos_hsc/afw/

7c5f68d9

commit 7c5f68d9be1ee96496becdc00032e74fb8aa7d9b
Author: smm 
Date:   Wed Oct 28 03:04:18 2009 +0000

    #994: turn SourceMatch from a boost::tuple into a simple struct

8d70f429

commit 8d70f429f96be073739bc1cf495bf46305c008fe
Author: Jim Bosch 
Date:   Thu Feb 9 14:43:13 2012 -0500

    source matching (but not persistence) converted to afw/table

e9b96e09

commit e9b96e090685b517aaeb0d98ec6a767814637a25
Author: smm 
Date:   Tue Apr 21 03:03:02 2009 +0000

    Added SWIG bindings for source matching functionality

3252a40a

commit 3252a40ad55222b882acf14d2f7cf0f3fe80f585
Author: Robert Lupton the Good 
Date:   Tue Jun 10 15:00:58 2014 -0400

    Added MatchControl and implemented it for matchXY and MatchRaDec
    
    N.b. added some missing tests on matchXY, although it is unchanged by this
    changeset

c5c122fa

commit c5c122fa2c22300360bb084c44030973e9ee4de6
Author: Paul Price 
Date:   Mon Jul 22 20:37:08 2013 -0400

    Match: add pickle for the MatchVectors (#2966)
    
    Takes care to propagate the slots on each catalog, otherwise we can't
    call, e.g., match.second.getPsfFlux(), after pickling.
    
    Also adds test for pickling SourceMatchVector, including slots.

f7e652f5

commit f7e652f5927fdeefdf88716f17b2a688696a5c23
Author: dstn 
Date:   Tue May 10 19:23:43 2011 +0000

    oops, forgot to add Angle.cc

4c363d4e

commit 4c363d4e26003e91da9c9731de483546f68950f9
Author: Jim Bosch 
Date:   Fri Feb 24 16:50:39 2012 -0500

    more refactoring of matching; should finally be usable with meas_astrom (using SimpleRecord/Table for reference catalogs)

Commits in /Users/nate/repos_lsst/afw/

4c363d4e

commit 4c363d4e26003e91da9c9731de483546f68950f9
Author: Jim Bosch 
Date:   Fri Feb 24 16:50:39 2012 -0500

    more refactoring of matching; should finally be usable with meas_astrom (using SimpleRecord/Table for reference catalogs)

81c3bd10

commit 81c3bd106e6aa66e68d569426b87862d5d10f844
Author: Russell Owen 
Date:   Fri Mar 13 10:47:12 2015 -0700

    Change %python { to %python %{ in swig .i files
    
    Also outdent some cases where the resulting python
    appeared at the wrong indentation level in the interface file
    or a comment was chopped off at the beginning (including
    the leading #, resulting in comment text being treated as commands).
    
    Fix indentation errors
    
    SWIG 3.0.2 indents python code differently when using
    %pythoncode %{...%} instead of the deprecated %pythoncode {...}
    This fixes most known issues, but image slicing doesn't yet work.
    
    Make indentation of %pythoncode more robust in imageLib.i

b4c7305a

commit b4c7305a3d3ddc3973f6a26920525a3a564c511a
Author: Paul Price 
Date:   Mon Jun 23 14:48:57 2014 -0400

    Match: fix *Match.__str__ for missing x,y
    
    ReferenceMatch.first does not have getX and getY methods.

Return to list

src/table/KeyBase.cc

Diff:

                // -*- lsst-c++ -*-
                
                #include "boost/preprocessor/seq/for_each.hpp"
                #include "boost/preprocessor/tuple/to_seq.hpp"
                
                #include "lsst/afw/table/KeyBase.h"
                #include "lsst/afw/table/detail/Access.h"
                #include "lsst/afw/table/Flag.h"
                #include "lsst/afw/table/BaseRecord.h"
                
                namespace lsst { namespace afw { namespace table {
                
                Key::Element> KeyBase::getStorage() const {
                    return detail::Access::extractElement(*this, 0);
                }
                
                char const * KeyBase< Coord >::subfields[] = { "ra", "dec" };
                
                template 
                char const * KeyBase< Point >::subfields[] = { "x", "y" };
                
                template 
                char const * KeyBase< Moments >::subfields[] = { "xx", "yy", "xy" };
                
                Key KeyBase< Coord >::getRa() const { return detail::Access::extractElement(*this, 0); }
                
                Key KeyBase< Coord >::getDec() const { return detail::Access::extractElement(*this, 1); }
                
                template 
                Key KeyBase< Point >::getX() const { return detail::Access::extractElement(*this, 0); }
                
                template 
                Key KeyBase< Point >::getY() const { return detail::Access::extractElement(*this, 1); }
                
                template 
                Key KeyBase< Moments >::getIxx() const { return detail::Access::extractElement(*this, 0); }
                
                template 
                Key KeyBase< Moments >::getIyy() const { return detail::Access::extractElement(*this, 1); }
                
                template 
                Key KeyBase< Moments >::getIxy() const { return detail::Access::extractElement(*this, 2); }
                
                template 
                std::vector KeyBase< Array >::extractVector(BaseRecord const & record) const {
                    Key< Array > const * self = static_cast > const *>(this);
                    std::vector result(self->getSize());
                    typename Key< Array >::ConstReference array = record[*self];
                    std::copy(array.begin(), array.end(), result.begin());
                    return result;
                }
                
                template 
                void KeyBase< Array >::assignVector(BaseRecord & record, std::vector const & values) const {
                    Key< Array > const * self = static_cast > const *>(this);
                    std::copy(values.begin(), values.end(), record[*self].begin());
                }
                
                template 
                Key KeyBase< Array >::operator[](int i) const {
                    Key< Array > const * self = static_cast > const *>(this);
                    if (self->isVariableLength()) {
                        throw LSST_EXCEPT(
64 0b745ec6 - lsst::pex::exceptions::LogicErrorException,
? ---------
64 2d6be90c + lsst::pex::exceptions::LogicError,
"Cannot get Keys to elements of variable-length arrays." ); } if (i >= self->getSize() || i < 0) { throw LSST_EXCEPT(
70 5dee136a - lsst::pex::exceptions::LengthErrorException,
? ---------
70 21597d88 + lsst::pex::exceptions::LengthError,
"Array key index out of range." ); } return detail::Access::extractElement(*this, i); } template Key< Array > KeyBase< Array >::slice(int begin, int end) const { Key< Array > const * self = static_cast > const *>(this); if (self->isVariableLength()) { throw LSST_EXCEPT(
82 0b745ec6 - lsst::pex::exceptions::LogicErrorException,
? ---------
82 2d6be90c + lsst::pex::exceptions::LogicError,
"Cannot get Keys to slices of variable-length arrays." ); } if (begin > self->getSize() || begin < 0) { throw LSST_EXCEPT(
88 7ebf031f - lsst::pex::exceptions::LengthErrorException,
? ---------
88 21597d88 + lsst::pex::exceptions::LengthError,
"Array key begin index out of range." ); } if (end > self->getSize() || end < 0) { throw LSST_EXCEPT(
94 7ebf031f - lsst::pex::exceptions::LengthErrorException,
? ---------
94 21597d88 + lsst::pex::exceptions::LengthError,
"Array key end index out of range." ); } return detail::Access::extractRange(*this, begin, end); } template Key KeyBase< Covariance >::operator()(int i, int j) const { Key< Covariance > const * self = static_cast > const *>(this); if (i >= self->getSize() || j >= self->getSize() || i < 0 || j < 0) { throw LSST_EXCEPT(
106 5dee136a - lsst::pex::exceptions::LengthErrorException,
? ---------
106 21597d88 + lsst::pex::exceptions::LengthError,
"Covariance key index out of range." ); } return detail::Access::extractElement(*this, detail::indexCovariance(i, j)); } template Key KeyBase< Covariance< Point > >::operator()(int i, int j) const { Key< Covariance< Point > > const * self = static_cast > > const *>(this); if (i >= self->getSize() || j >= self->getSize() || i < 0 || j < 0) { throw LSST_EXCEPT(
118 5dee136a - lsst::pex::exceptions::LengthErrorException,
? ---------
118 21597d88 + lsst::pex::exceptions::LengthError,
"Covariance key index out of range." ); } return detail::Access::extractElement(*this, detail::indexCovariance(i, j)); } template Key KeyBase< Covariance< Moments > >::operator()(int i, int j) const { Key< Covariance< Moments > > const * self = static_cast > > const *>(this); if (i >= self->getSize() || j >= self->getSize() || i < 0 || j < 0) { throw LSST_EXCEPT(
130 5dee136a - lsst::pex::exceptions::LengthErrorException,
? ---------
130 21597d88 + lsst::pex::exceptions::LengthError,
"Covariance key index out of range." ); } return detail::Access::extractElement(*this, detail::indexCovariance(i, j)); } //----- Explicit instantiation ------------------------------------------------------------------------------ #define INSTANTIATE_KEY(r, data, elem) \ template class KeyBase< elem >; BOOST_PP_SEQ_FOR_EACH( INSTANTIATE_KEY, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_FIELD_TYPE_N, AFW_TABLE_FIELD_TYPE_TUPLE) ) }}} // namespace lsst::afw::table

Return to list

Commits in /Users/nate/repos_hsc/afw/

0b745ec6

commit 0b745ec681de903b911691c49f07f3ebc52c692f
Author: Jim Bosch 
Date:   Mon Dec 1 13:46:03 2014 -0500

    Add variable-length array fields to afw::table
    
    We use Array with a size of zero to indicate variable-length fields.
    It'd probably be better to use a completely different tag type, but
    Boost.Variant puts an upper limit on how many tags we have, so until
    we rewrite afw::table to avoid it, we need to limit how many we use.

5dee136a

commit 5dee136a9f602af873bc62bd6c6efb36e7aeb0d6
Author: Jim Bosch 
Date:   Sun Nov 20 01:21:52 2011 -0500

    removed per-field null bits

7ebf031f

commit 7ebf031f548246fc086a89cc8038a8350d5f85d8
Author: Jim Bosch 
Date:   Mon Jan 13 12:40:09 2014 -0500

    Add support for slicing table Array Keys (#3103)

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

2d6be90c

commit 2d6be90c6e14ab8fa2803a84a45106345037f1f5
Author: Lauren MacArthur 
Date:   Thu Apr 2 13:50:52 2015 -0400

    Remove trailing Exception in exception names

Return to list

python/lsst/afw/image/Calib.i

Diff:

                // -*- lsst-c++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                %{
                #include "lsst/afw/image/Calib.h"
                %}
                
                %import "lsst/afw/table/io/ioLib.i"
                
                %declareTablePersistable(Calib, lsst::afw::image::Calib);
                
                %typemap(out) std::pair,ndarray::Array > {
                    $result = PyTuple_New(2);
                    {
                        // need to invoke SwigValueWrapper's conversion operator
                        std::pair,ndarray::Array > & pair = $1;
                        PyObject * a0 = ndarray::PyConverter< ndarray::Array >::toPython(pair.first);
                        PyObject * a1 = ndarray::PyConverter< ndarray::Array >::toPython(pair.second);
                        PyTuple_SET_ITEM($result, 0, a0);
                        PyTuple_SET_ITEM($result, 1, a1);
                    }
                }
                
                %include "lsst/afw/image/Calib.h"
                %template(vectorCalib) std::vector >;
46 f3d3029c -
47 f3d3029c - %extend lsst::afw::image::Calib {
48 f3d3029c - %pythoncode %{
49 f3d3029c - #
50 f3d3029c - # Provide return value for C++ "void operator op=()" or it will magically end up as None
51 f3d3029c - #
52 f3d3029c - def __imul__(*args):
53 f3d3029c - """__imul__(self, double scale) -> self"""
54 f3d3029c - _imageLib.Calib___imul__(*args)
55 f3d3029c - return args[0]
56 f3d3029c -
57 f3d3029c - def __idiv__(*args):
58 f3d3029c - """__idiv__(self, double scale) -> self"""
59 f3d3029c - _imageLib.Calib___idiv__(*args)
60 f3d3029c - return args[0]
61 f3d3029c - %}
62 f3d3029c - }

Return to list

Commits in /Users/nate/repos_hsc/afw/

f3d3029c

commit f3d3029c561b957069cbf280b62ea8e37447c068
Author: Paul Price 
Date:   Mon Apr 27 18:09:36 2015 -0400

    Calib: add operator*= for scaling zeropoint

Commits in /Users/nate/repos_lsst/afw/

Return to list

src/detection/GaussianPsf.cc

Diff:

                // -*- LSST-C++ -*-
                /*
                 * LSST Data Management System
                 * Copyright 2008-2014 LSST Corporation.
                 *
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 *
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 *
                 * You should have received a copy of the LSST License Statement and
                 * the GNU General Public License along with this program.  If not,
                 * see .
                 */
                
                #include "boost/make_shared.hpp"
                
                #include "ndarray/eigen.h"
                
                #include "lsst/afw/detection/GaussianPsf.h"
                #include "lsst/afw/table/io/InputArchive.h"
                #include "lsst/afw/table/io/OutputArchive.h"
                #include "lsst/afw/table/io/CatalogVector.h"
                
                namespace lsst { namespace afw { namespace detection {
                
                namespace {
                
                // Read-only singleton struct containing the schema and keys that a GaussianPsf is mapped
                // to in record persistence.
                struct GaussianPsfPersistenceHelper : private boost::noncopyable {
                    afw::table::Schema schema;
                    afw::table::Key< afw::table::Point > dimensions;
                    afw::table::Key sigma;
                
                    static GaussianPsfPersistenceHelper const & get() {
                        static GaussianPsfPersistenceHelper instance;
                        return instance;
                    }
                
                private:
                    GaussianPsfPersistenceHelper() :
                        schema(),
                        dimensions(
                            schema.addField< afw::table::Point >(
                                "dimensions", "width/height of realization of Psf", "pixels"
                            )
                        ),
                        sigma(schema.addField("sigma", "radius of Gaussian", "pixels"))
                    {
                        schema.getCitizen().markPersistent();
                    }
                };
                
                class GaussianPsfFactory : public afw::table::io::PersistableFactory {
                public:
                
                    virtual PTR(afw::table::io::Persistable)
                    read(InputArchive const & archive, CatalogVector const & catalogs) const {
                        static GaussianPsfPersistenceHelper const & keys = GaussianPsfPersistenceHelper::get();
                        LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
                        LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u);
                        afw::table::BaseRecord const & record = catalogs.front().front();
                        LSST_ARCHIVE_ASSERT(record.getSchema() == keys.schema);
                        return boost::make_shared(
                            record.get(keys.dimensions.getX()),
                            record.get(keys.dimensions.getY()),
                            record.get(keys.sigma)
                        );
                    }
                
                    GaussianPsfFactory(std::string const & name) : afw::table::io::PersistableFactory(name) {}
                
                };
                
                GaussianPsfFactory registration("GaussianPsf");
                
                void checkDimensions(geom::Extent2I const & dimensions) {
                    if (dimensions.getX() % 2 == 0 || dimensions.getY() % 2 == 2) {
                        throw LSST_EXCEPT(
89 e1c6ff32 - pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
89 21597d88 + pex::exceptions::InvalidParameterError,
? ^^ ^ "GaussianPsf dimensions must be odd" ); } } } // anonymous GaussianPsf::GaussianPsf(int width, int height, double sigma) : Psf(true), _dimensions(width, height), _sigma(sigma) { checkDimensions(_dimensions); } GaussianPsf::GaussianPsf(geom::Extent2I const & dimensions, double sigma) : Psf(true), _dimensions(dimensions), _sigma(sigma) { checkDimensions(_dimensions); } PTR(afw::detection::Psf) GaussianPsf::clone() const { return boost::make_shared(_dimensions, _sigma); } std::string GaussianPsf::getPersistenceName() const { return "GaussianPsf"; } std::string GaussianPsf::getPythonModule() const { return "lsst.afw.detection"; } void GaussianPsf::write(OutputArchiveHandle & handle) const { static GaussianPsfPersistenceHelper const & keys = GaussianPsfPersistenceHelper::get(); afw::table::BaseCatalog catalog = handle.makeCatalog(keys.schema); PTR(afw::table::BaseRecord) record = catalog.addNew(); (*record)[keys.dimensions.getX()] = _dimensions.getX(); (*record)[keys.dimensions.getY()] = _dimensions.getY(); (*record)[keys.sigma] = getSigma(); handle.saveCatalog(catalog); } PTR(GaussianPsf::Image) GaussianPsf::doComputeKernelImage( geom::Point2D const &, image::Color const & ) const { PTR(Image) r(new Image(_dimensions)); Image::Array array = r->getArray(); r->setXY0(geom::Point2I(-_dimensions / 2)); // integer truncation intentional double sum = 0.0; for (int yIndex = 0, y = r->getY0(); yIndex < _dimensions.getY(); ++yIndex, ++y) { Image::Array::Reference row = array[yIndex]; for (int xIndex = 0, x = r->getX0(); xIndex < _dimensions.getX(); ++xIndex, ++x) { sum += row[xIndex] = std::exp(-0.5*(x*x + y*y)/(_sigma*_sigma)); } } array.asEigen() /= sum; return r; } double GaussianPsf::doComputeApertureFlux( double radius, geom::Point2D const & position, image::Color const & color ) const { return 1.0 - std::exp(-0.5*radius*radius/(_sigma*_sigma)); } geom::ellipses::Quadrupole GaussianPsf::doComputeShape( geom::Point2D const & position, image::Color const & color ) const { return geom::ellipses::Quadrupole(_sigma*_sigma, _sigma*_sigma, 0.0); } }}} // namespace lsst::afw::detection

Return to list

Commits in /Users/nate/repos_hsc/afw/

e1c6ff32

commit e1c6ff3212a409dafdc9631f04c2c92cbd255c9b
Author: Jim Bosch 
Date:   Mon Jan 20 17:22:16 2014 -0500

    C++ implementation of simple GaussianPsf class (#3115)

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

python/lsst/afw/detection/footprints.i

Diff:

                // -*- lsst-c++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                %{
                #include "boost/shared_ptr.hpp"
                #include "lsst/afw/detection/Threshold.h"
                #include "lsst/afw/detection/Footprint.h"
                #include "lsst/afw/detection/FootprintMerge.h"
                #include "lsst/afw/detection/FootprintCtrl.h"
                #include "lsst/afw/detection/HeavyFootprint.h"
                #include "lsst/afw/detection/FootprintFunctor.h"
                #include "lsst/afw/detection/FootprintArray.h"
                #include "lsst/afw/detection/FootprintArray.cc"
                #include "ndarray.h"
                %}
                
                namespace lsst { namespace afw { namespace detection {
                typedef lsst::afw::geom::Span Span;
                }}}
                
                %import "lsst/afw/table/io/ioLib.i"
                
                %include "lsst/afw/image/LsstImageTypes.h"
                %include "std_pair.i"
                %template(pairBB) std::pair;
                
                %shared_vec(boost::shared_ptr);
                
                %ignore lsst::afw::detection::FootprintFunctor::operator();
                
                // already in image.i.
                // %template(VectorBox2I) std::vector;
                
                %declareTablePersistable(Footprint, lsst::afw::detection::Footprint);
                %shared_ptr(std::vector >);
                
                %declareNumPyConverters(ndarray::Array);
                %declareNumPyConverters(ndarray::Array);
                
                %define %HeavyFootprintPtr(NAME, PIXEL_TYPE, MASK_TYPE, VAR_TYPE)
                %declareTablePersistable(HeavyFootprint ## NAME, lsst::afw::detection::HeavyFootprint);
                %declareNumPyConverters(ndarray::Array);
                %enddef
                
                %HeavyFootprintPtr(I, int,   lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel)
                %HeavyFootprintPtr(F, float, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel)
                
                %rename(assign) lsst::afw::detection::Footprint::operator=;
                
                %template(SpanContainerT)      std::vector >;
                %template(FootprintList)       std::vector >;
                
                %include "lsst/afw/detection/Threshold.h"
                %include "lsst/afw/detection/Footprint.h"
                %include "lsst/afw/detection/FootprintMerge.h"
                %include "lsst/afw/detection/FootprintCtrl.h"
                %include "lsst/afw/detection/HeavyFootprint.h"
                %include "lsst/afw/detection/FootprintFunctor.h"
                
                %define %thresholdOperations(TYPE)
                    %extend lsst::afw::detection::Threshold {
                        %template(getValue) getValue >;
                        %template(getValue) getValue >;
                        %template(getValue) getValue >;
                        %template(getValue) getValue >;
                    }
                %enddef
                
                %define %footprintOperations(PIXEL)
                %template(insertIntoImage) lsst::afw::detection::Footprint::insertIntoImage;
                %enddef
                
                %extend lsst::afw::detection::Footprint {
                    %template(intersectMask) intersectMask;
                    %footprintOperations(unsigned short)
                    %footprintOperations(int)
                    %footprintOperations(boost::uint64_t)
                }
                
                %define %heavyFootprints(NAME, PIXEL_TYPE, MASK_TYPE, VAR_TYPE)
                    %template(HeavyFootprint ##NAME) lsst::afw::detection::HeavyFootprint;
                
                /*
                %extend lsst::afw::detection::HeavyFootprint {
                    ndarray::Array getImageArray() { self->getImageArray(); }
                    ndarray::Array getMaskArray() { self->getMaskArray(); }
                    ndarray::Array getVarianceArray() { self->getVarianceArray(); }
                }
                 */
                
                    %template(HeavyFootprintPtrList ## NAME) std::vector > >;
                
                
                    %template(makeHeavyFootprint ##NAME) lsst::afw::detection::makeHeavyFootprint;
                
                    %template(mergeHeavyFootprints ##NAME) lsst::afw::detection::mergeHeavyFootprints;
                
                    %inline %{
                        //------------------------------------------------------------------------
                        // THIS CAST INTERFACE IS DEPRECATED IN FAVOR OF %castShared AND WILL BE REMOVED IN THE FUTURE
                        PTR(lsst::afw::detection::HeavyFootprint)
                            /**
                             * Cast a Footprint to a HeavyFootprint of a specified type
                             */
                            cast_HeavyFootprint##NAME(PTR(lsst::afw::detection::Footprint) foot) {
                            return boost::dynamic_pointer_cast >(foot);
                        }
                        //------------------------------------------------------------------------
                        PTR(lsst::afw::detection::HeavyFootprint)
                            /**
                             * Cast a Footprint to a HeavyFootprint; the MaskedImage disambiguates the type
                             */
                            cast_HeavyFootprint(PTR(lsst::afw::detection::Footprint) foot,
                                                lsst::afw::image::MaskedImage const&) {
                            return boost::dynamic_pointer_cast >(foot);
                        }
                    %}
                #define DERIVED_ARGS PIXEL_TYPE, MASK_TYPE, VAR_TYPE
                    %castShared(lsst::afw::detection::HeavyFootprint< DERIVED_ARGS >,
                                lsst::afw::detection::Footprint)
                #undef DERIVED_ARGS
                
                %enddef
                
                
                
148 9337578a - %define %footprintImageOperations(NAME, PIXEL_TYPE)
? ------
148 94770baf + %define %footprintImageOperations(PIXEL_TYPE)
%template(setImageFromFootprint) lsst::afw::detection::setImageFromFootprint >; %template(setImageFromFootprintList) lsst::afw::detection::setImageFromFootprintList >; %template(copyWithinFootprintImage) lsst::afw::detection::copyWithinFootprint >; %template(copyWithinFootprintMaskedImage) lsst::afw::detection::copyWithinFootprint >;
156 097386fc - %template(clipToNonzero ##NAME) lsst::afw::detection::Footprint::clipToNonzero;
? -------
156 94770baf + %template(clipToNonzero) lsst::afw::detection::Footprint::clipToNonzero;
%enddef %define %imageOperations(NAME, PIXEL_TYPE) %template(FootprintFunctor ##NAME) lsst::afw::detection::FootprintFunctor >; %template(FootprintFunctorMI ##NAME) lsst::afw::detection::FootprintFunctor >;
163 9337578a - %footprintImageOperations(NAME, PIXEL_TYPE);
? ------
163 94770baf + %footprintImageOperations(PIXEL_TYPE);
%enddef %define %maskOperations(PIXEL_TYPE) %template(footprintAndMask) lsst::afw::detection::footprintAndMask; %template(setMaskFromFootprint) lsst::afw::detection::setMaskFromFootprint; %template(clearMaskFromFootprint) lsst::afw::detection::clearMaskFromFootprint; %template(setMaskFromFootprintList) lsst::afw::detection::setMaskFromFootprintList; %enddef %heavyFootprints(I, int, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel) %heavyFootprints(F, float, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel) %thresholdOperations(lsst::afw::image::Image); %thresholdOperations(lsst::afw::image::MaskedImage); %imageOperations(F, float); %imageOperations(D, double);
181 9337578a - %footprintImageOperations(U, boost::uint16_t);
? ---
181 94770baf + %footprintImageOperations(boost::uint16_t);
182 9337578a - %footprintImageOperations(I, int);
? ---
182 94770baf + %footprintImageOperations(int);
183 9337578a - %footprintImageOperations(L, boost::uint64_t);
? ---
183 94770baf + %footprintImageOperations(boost::uint64_t);
%maskOperations(lsst::afw::image::MaskPixel); %template(FootprintFunctorMaskU) lsst::afw::detection::FootprintFunctor >; // because stupid SWIG's %template doesn't work on these functions %define %footprintArrayTemplates(T) %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %inline %{ void flattenArray( lsst::afw::detection::Footprint const & fp, ndarray::Array const & src, ndarray::Array const & dest, lsst::afw::geom::Point2I const & origin = lsst::afw::geom::Point2I() ) { lsst::afw::detection::flattenArray(fp, src, dest, origin); } void flattenArray( lsst::afw::detection::Footprint const & fp, ndarray::Array const & src, ndarray::Array const & dest, lsst::afw::geom::Point2I const & origin = lsst::afw::geom::Point2I() ) { lsst::afw::detection::flattenArray(fp, src, dest, origin); } void expandArray( lsst::afw::detection::Footprint const & fp, ndarray::Array const & src, ndarray::Array const & dest, lsst::afw::geom::Point2I const & origin = lsst::afw::geom::Point2I() ) { lsst::afw::detection::expandArray(fp, src, dest, origin); } void expandArray( lsst::afw::detection::Footprint const & fp, ndarray::Array const & src, ndarray::Array const & dest, lsst::afw::geom::Point2I const & origin = lsst::afw::geom::Point2I() ) { lsst::afw::detection::expandArray(fp, src, dest, origin); } %} %{ template void lsst::afw::detection::flattenArray( lsst::afw::detection::Footprint const &, ndarray::Array const &, ndarray::Array const &, lsst::afw::geom::Point2I const & ); template void lsst::afw::detection::flattenArray( lsst::afw::detection::Footprint const &, ndarray::Array const &, ndarray::Array const &, lsst::afw::geom::Point2I const & ); template void lsst::afw::detection::expandArray( lsst::afw::detection::Footprint const &, ndarray::Array const &, ndarray::Array const &, lsst::afw::geom::Point2I const & ); template void lsst::afw::detection::expandArray( lsst::afw::detection::Footprint const &, ndarray::Array const &, ndarray::Array const &, lsst::afw::geom::Point2I const & ); %} %enddef %footprintArrayTemplates(boost::uint16_t); %footprintArrayTemplates(int); %footprintArrayTemplates(float); %footprintArrayTemplates(double);
263 219d017d - %pythoncode {
263 81c3bd10 + %pythoncode %{
? + makeHeavyFootprint = makeHeavyFootprintF
265 219d017d - }
265 81c3bd10 + %}
? + %extend lsst::afw::detection::FootprintMergeList { %pythoncode %{ def getMergedSourceCatalog(self, catalogs, filters, peakDist, schema, idFactory, samePeakDist): """Add multiple catalogs and get the SourceCatalog with merged Footprints""" import lsst.afw.table as afwTable table = afwTable.SourceTable.make(schema, idFactory) mergedList = afwTable.SourceCatalog(table) # if peak is not an array, create an array the size of catalogs try: len(samePeakDist) except: samePeakDist = [samePeakDist] * len(catalogs) try: len(peakDist) except: peakDist = [peakDist] * len(catalogs) if len(peakDist) != len(catalogs): raise ValueError("Number of catalogs (%d) does not match length of peakDist (%d)" % (len(catalogs), len(peakDist))) if len(samePeakDist) != len(catalogs): raise ValueError("Number of catalogs (%d) does not match length of samePeakDist (%d)" % (len(catalogs), len(samePeakDist))) if len(filters) != len(catalogs): raise ValueError("Number of catalogs (%d) does not match number of filters (%d)" % (len(catalogs), len(filters))) self.clearCatalog() for cat, filter, dist, sameDist in zip(catalogs, filters, peakDist, samePeakDist): self.addCatalog(table, cat, filter, dist, True, sameDist) self.getFinalSources(mergedList) return mergedList %} }

Return to list

Commits in /Users/nate/repos_hsc/afw/

219d017d

commit 219d017d858cb916e9244afad75f6331b116b83d
Author: Dustin Lang 
Date:   Fri Jun 22 16:23:38 2012 -0400

    ARGH, wrestling with swig

9337578a

commit 9337578a740b1b809c3e65eb8e52fa91254cfffd
Author: Dustin Lang 
Date:   Fri Apr 11 13:54:58 2014 -0400

    add nearesteFootprint() function; instantiate a broader range of Footprint functions for int images

097386fc

commit 097386fc2cd385521370ffa031a621074dd4a6b9
Author: Dustin Lang 
Date:   Mon Mar 10 15:36:24 2014 -0400

    add Footprint.addSpanInSeries(), and Footprint.clipToNonzero()

Commits in /Users/nate/repos_lsst/afw/

81c3bd10

commit 81c3bd106e6aa66e68d569426b87862d5d10f844
Author: Russell Owen 
Date:   Fri Mar 13 10:47:12 2015 -0700

    Change %python { to %python %{ in swig .i files
    
    Also outdent some cases where the resulting python
    appeared at the wrong indentation level in the interface file
    or a comment was chopped off at the beginning (including
    the leading #, resulting in comment text being treated as commands).
    
    Fix indentation errors
    
    SWIG 3.0.2 indents python code differently when using
    %pythoncode %{...%} instead of the deprecated %pythoncode {...}
    This fixes most known issues, but image slicing doesn't yet work.
    
    Make indentation of %pythoncode more robust in imageLib.i

94770baf

commit 94770bafec04976204f56cf3aed80fa02bece412
Author: Dustin Lang 
Date:   Mon Jun 23 17:17:08 2014 -0500

    Address various issues from Paul Price's in-depth review.
    
    Footprint.h:
        No documentation for new methods and functions.
    
    Footprint.cc:
        Move documentation to header file.
        Indentation is inconsistent. Should always be 4.
        Don't use this-> when there is no need for it, e.g., this->addSpan should be addSpan.
        Paren following LSST_EXCEPT *must* cuddle --- it certainly may not be on the next line.
        Breaks 110 column limit.
        PixelT zero = 0; should be PixelT const zero = 0; Add const also for ix0 and iy0 --- *anywhere* the value will never change, as it helps the compiler write faster code.
        You're iterating with the postfix operator (s++) instead of prefix (++s); this can adversely affect performance in C++.
        What does the comment Ugly! refer to?
        Names foota and footb don't follow naming rules, and are a bit hard to read. Suggest aFoot and bFoot. Similarly with pka, etc.
        const Footprint::PeakList& --> Footprint::PeakList const& (throughout).
        while (1) --> while (true)
        nearestFootprint isn't documented.
        Why do you call INSTANTIATE_FLOAT on integer types???  [I renamed it -- it instantiated functions that were appropriate for *numeric*, not necessarily floating-point, types!]
        remove gratuitous 'typename'
        prefer PTR(Foo) to Foo::Ptr and CONST_PTR(Foo) to Foo:ConstPtr.
    
    HeavyFootprint?.cc:
        Some lines exceed 110 columns.
        Commented out code should be removed
    
    footprint1.py:
        Instead of self.assertTrue(a > b) use self.assertGreater(a, b). This provides a more useful message when it fails.
        Why is the trailing F required on clipToNonzeroF? It should be able to tell from the type of the image.  [fixed]
    
    Also removed stray Footprint.mergeWith() function that got messed up during rebase

Return to list

src/table/IdFactory.cc

Diff:

                #include "boost/make_shared.hpp"
                #include "boost/format.hpp"
                
                #include "lsst/pex/exceptions.h"
                #include "lsst/afw/table/IdFactory.h"
                
                namespace lsst { namespace afw { namespace table {
                
                namespace {
                
                class SimpleIdFactory : public IdFactory {
                public:
                
                    virtual RecordId operator()() { return ++_current; }
                
                    virtual void notify(RecordId id) { _current = id; }
                
                    virtual PTR(IdFactory) clone() const { return boost::make_shared(*this); }
                
                    SimpleIdFactory() : _current(0) {}
                
                private:
                    RecordId _current;
                };
                
                class SourceIdFactory : public IdFactory {
                public:
                
                    virtual RecordId operator()() {
                        if (++_lower & _upperMask) {
                            --_lower;
                            throw LSST_EXCEPT(
33 91a3a093 - pex::exceptions::LengthErrorException,
? ---------
33 21597d88 + pex::exceptions::LengthError,
(boost::format("Next ID '%s' is too large for the number of reserved bits") % (_lower + 1)).str() ); } return _upper | _lower; } virtual void notify(RecordId id) { RecordId newLower = id & (~_upper); // chop off the exact exposure ID if (newLower & _upperMask) { throw LSST_EXCEPT(
45 91a3a093 - pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
45 21597d88 + pex::exceptions::InvalidParameterError,
? ^^ ^ (boost::format("Explicit ID '%s' does not have the correct form.") % newLower).str() ); } _lower = newLower; } virtual PTR(IdFactory) clone() const { return boost::make_shared(*this); } SourceIdFactory(RecordId expId, int reserved) : _upper(expId << reserved), _upperMask(std::numeric_limits::max() << reserved), _lower(0) { if (_upper >> reserved != expId) { throw LSST_EXCEPT(
61 91a3a093 - pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
61 21597d88 + pex::exceptions::InvalidParameterError,
? ^^ ^ (boost::format("Exposure ID '%s' is too large.") % expId).str() ); } } private: RecordId const _upper; RecordId const _upperMask; RecordId _lower; }; } // anonymous PTR(IdFactory) IdFactory::makeSimple() { return boost::make_shared(); } PTR(IdFactory) IdFactory::makeSource(RecordId expId, int reserved) { return boost::make_shared(expId, reserved); } }}} // namespace lsst::afw::table

Return to list

Commits in /Users/nate/repos_hsc/afw/

91a3a093

commit 91a3a0935b9dff83459b73f19ab684f3265d2650
Author: Jim Bosch 
Date:   Sat Apr 28 18:05:27 2012 -0400

    added IdFactory for sources that includes the exposure ID in the upper bits

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

python/lsst/afw/math/background.i

Diff:

                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                %{
                #include "boost/shared_ptr.hpp"
                #include "lsst/afw/math/Background.h"
                %}
                
28 264e671e - %shared_ptr(lsst::afw::math::BackgroundControl);
%shared_ptr(lsst::afw::math::Background); %shared_ptr(lsst::afw::math::BackgroundMI); %include "lsst/afw/math/Background.h" %inline %{ PTR(lsst::afw::math::BackgroundMI) cast_BackgroundMI(PTR(lsst::afw::math::Background) bback) { return boost::dynamic_pointer_cast(bback); } %} %extend lsst::afw::math::Background {
41 36a259f5 - %pythoncode {
40 81c3bd10 + %pythoncode %{
? +
42 36a259f5 - #
41 81c3bd10 + #
43 36a259f5 - # Deal with incorrect swig wrappers for C++ "void operator op=()"
? ----
42 81c3bd10 + # Deal with incorrect swig wrappers for C++ "void operator op=()"
44 36a259f5 - #
43 81c3bd10 + #
45 36a259f5 - def __iadd__(*args):
? ----
44 81c3bd10 + def __iadd__(*args):
46 36a259f5 - """
? ----
45 81c3bd10 + """
47 36a259f5 - __iadd__(self, float scalar) -> self
? ----
46 81c3bd10 + __iadd__(self, float scalar) -> self
48 36a259f5 - """
? ----
47 81c3bd10 + """
49 2915cbac - _mathLib.Background___iadd__(*args) # clears thisown as it things args[0] is returned
? ----
48 81c3bd10 + _mathLib.Background___iadd__(*args) # clears thisown as it things args[0] is returned
50 36a259f5 - args[0].thisown = True
? ----
49 81c3bd10 + args[0].thisown = True
51 36a259f5 - return args[0]
? ----
50 81c3bd10 + return args[0]
53 36a259f5 - def __isub__(*args):
? ----
52 81c3bd10 + def __isub__(*args):
54 36a259f5 - """
? ----
53 81c3bd10 + """
55 36a259f5 - __isub__(self, float scalar) -> self
? ----
54 81c3bd10 + __isub__(self, float scalar) -> self
56 36a259f5 - """
? ----
55 81c3bd10 + """
57 2915cbac - _mathLib.Background___isub__(*args) # clears thisown as it things args[0] is returned
? ----
56 81c3bd10 + _mathLib.Background___isub__(*args) # clears thisown as it things args[0] is returned
58 36a259f5 - args[0].thisown = True
? ----
57 81c3bd10 + args[0].thisown = True
59 36a259f5 - return args[0]
? ----
58 81c3bd10 + return args[0]
60 36a259f5 - }
59 81c3bd10 + %}
? + } %extend lsst::afw::math::BackgroundMI {
64 eddd029e - %pythoncode {
63 81c3bd10 + %pythoncode %{
? +
65 eddd029e - #
64 81c3bd10 + #
66 eddd029e - # Deal with incorrect swig wrappers for C++ "void operator op=()"
? ----
65 81c3bd10 + # Deal with incorrect swig wrappers for C++ "void operator op=()"
67 eddd029e - #
66 81c3bd10 + #
68 eddd029e - def __iadd__(*args):
? ----
67 81c3bd10 + def __iadd__(*args):
69 eddd029e - """
? ----
68 81c3bd10 + """
70 eddd029e - __iadd__(self, float scalar) -> self
? ----
69 81c3bd10 + __iadd__(self, float scalar) -> self
71 eddd029e - """
? ----
70 81c3bd10 + """
72 2915cbac - _mathLib.BackgroundMI___iadd__(*args) # clears thisown as it things args[0] is returned
? ----
71 81c3bd10 + _mathLib.BackgroundMI___iadd__(*args) # clears thisown as it things args[0] is returned
73 e0cbd85f - args[0].thisown = True
? ----
72 81c3bd10 + args[0].thisown = True
74 eddd029e - return args[0]
? ----
73 81c3bd10 + return args[0]
76 eddd029e - def __isub__(*args):
? ----
75 81c3bd10 + def __isub__(*args):
77 eddd029e - """
? ----
76 81c3bd10 + """
78 eddd029e - __isub__(self, float scalar) -> self
? ----
77 81c3bd10 + __isub__(self, float scalar) -> self
79 eddd029e - """
? ----
78 81c3bd10 + """
80 2915cbac - _mathLib.BackgroundMI___isub__(*args) # clears thisown as it things args[0] is returned
? ----
79 81c3bd10 + _mathLib.BackgroundMI___isub__(*args) # clears thisown as it things args[0] is returned
81 e0cbd85f - args[0].thisown = True
? ----
80 81c3bd10 + args[0].thisown = True
82 eddd029e - return args[0]
? ----
81 81c3bd10 + return args[0]
84 65b8e9b5 - def __reduce__(self):
? ----
83 81c3bd10 + def __reduce__(self):
85 65b8e9b5 - """Pickling"""
? ----
84 81c3bd10 + """Pickling"""
86 65b8e9b5 - return self.__class__, (self.getImageBBox(), self.getStatsImage())
? ----
85 81c3bd10 + return self.__class__, (self.getImageBBox(), self.getStatsImage())
87 eddd029e - }
86 81c3bd10 + %}
? + } %define %declareBack(PIXTYPE, SUFFIX) %template(makeBackground) lsst::afw::math::makeBackground >; %template(makeBackground) lsst::afw::math::makeBackground >; %template(BackgroundMI ## SUFFIX) lsst::afw::math::BackgroundMI::BackgroundMI >; %template(getImage ## SUFFIX) lsst::afw::math::Background::getImage; %template(getImage ## SUFFIX) lsst::afw::math::BackgroundMI::getImage; %enddef
97 8d690134 + %declareBack(double, D)
%declareBack(float, F)
99 8d690134 + %declareBack(int, I)

Return to list

Commits in /Users/nate/repos_hsc/afw/

65b8e9b5

commit 65b8e9b522cb4d92402c3272872d57d1e832ce29
Author: Paul Price 
Date:   Fri Feb 7 16:11:23 2014 -0500

    Background: make BackgroundMI and BackgroundList picklable
    
    Note that an item returned by lsst.afw.math.makeBackground() cannot be
    pickled directly (it's difficult to properly pickle SWIGed polymorphic
    objects).  The current workaround is to cast it to a BackgroundMI; best
    would be to not use polymorphism from python.

eddd029e

commit eddd029e9cab2bac4793ca98e1a1e12f7364cc31
Author: Robert Lupton the Good 
Date:   Mon Mar 5 13:12:34 2012 -0500

    Support Background += val and -= val (#1972)

36a259f5

commit 36a259f57bfa56efb86ee93aac20de9ac1856aca
Author: Robert Lupton the Good 
Date:   Sun Oct 14 19:42:19 2012 -0400

    Split Background into Background and BackgroundBase
    
    The MaskedImage statsImage is really an implementation detail of this background model,
    and not a property of the Background.  I accordingly added a base class and kept the
    MaskedImage bits in the Background object.  Maybe I should have called them Background
    and BackgroundMI or something.  Note that we now need to return a pointer from makeBackground,
    hence the changes to the tests/examples

e0cbd85f

commit e0cbd85f1a31ff09ed4b892c0a522874fafafbda
Author: Robert Lupton the Good 
Date:   Wed Oct 10 20:38:35 2012 -0400

    Stop Background__iadd__ getting the reference count wrong
    
    "fixing" __iadd__ to handle a void return type seems to
    have got the ref count wrong. This shows up now as we've
    added a data member that the dtor needs to delete.
    
    N.b. We probably need to make parallel changes for image classes

264e671e

commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
Author: Steven Bickerton 
Date:   Fri Oct 24 14:37:15 2014 +0900

    Use shared_ptr.  Add test.  Disable double,int backgrounds.

2915cbac

commit 2915cbac8ebf464fe28a3c0f2752a8211d9be37b
Author: Robert Lupton the Good 
Date:   Tue Oct 16 13:19:16 2012 -0400

    Changed names of Background classes
    
    BackgroundBase -> Background
    Background     -> BackgroundMI

Commits in /Users/nate/repos_lsst/afw/

81c3bd10

commit 81c3bd106e6aa66e68d569426b87862d5d10f844
Author: Russell Owen 
Date:   Fri Mar 13 10:47:12 2015 -0700

    Change %python { to %python %{ in swig .i files
    
    Also outdent some cases where the resulting python
    appeared at the wrong indentation level in the interface file
    or a comment was chopped off at the beginning (including
    the leading #, resulting in comment text being treated as commands).
    
    Fix indentation errors
    
    SWIG 3.0.2 indents python code differently when using
    %pythoncode %{...%} instead of the deprecated %pythoncode {...}
    This fixes most known issues, but image slicing doesn't yet work.
    
    Make indentation of %pythoncode more robust in imageLib.i

8d690134

commit 8d6901346ec80fda39559d458891570da4225c5f
Author: bick 
Date:   Wed Jan 28 22:55:09 2009 +0000

    Merging make_Background() function on to afw/trunk.  This change is associated with ticket #395

Return to list

python/lsst/afw/image/mask.i

Diff:

                // -*- lsst-c++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                %{
                #   include "lsst/afw/image/Mask.h"
                %}
                
                /************************************************************************************************************/
                
                //
                // Must go After the %include
                //
                %define %mask(NAME, TYPE, PIXEL_TYPE...)
                %template(NAME##TYPE) lsst::afw::image::Mask;
                
                %extend lsst::afw::image::Mask {
                    /**
                     * Set an image to the value val
                     */
                    void set(PIXEL_TYPE val) {
                        *self = val;
                    }
                
                    /**
                     * Set pixel (x,y) to val
                     */
                    void set(int x, int y, double val) {
                        self->operator()(x, y, lsst::afw::image::CheckIndices(true)) = val;
                    }
                
                    PIXEL_TYPE get(int x, int y) const {
                        return self->operator()(x, y, lsst::afw::image::CheckIndices(true));
                    }
                
                    bool get(int x, int y, int plane) const {
                        return self->operator()(x, y, plane, lsst::afw::image::CheckIndices(true));
                    }
                
                    %newobject convert##TYPE;
                    lsst::afw::image::Image convert##TYPE() {
                        lsst::afw::image::Image out(self->getDimensions());
                        for (int y = 0; y != self->getHeight(); ++y) {
                            lsst::afw::image::Image::x_iterator optr = out.row_begin(y);
                            for (lsst::afw::image::Mask::x_iterator ptr = self->row_begin(y), end = self->row_end(y);
                                 ptr != end; ++ptr, ++optr) {
                                *optr = *ptr;
                            }
                        }
                
                        return out;
                    }
                    
74 f8edfe90 - %pythoncode {
74 81c3bd10 + %pythoncode %{
? +
75 f8edfe90 - #
75 81c3bd10 + #
76 f8edfe90 - # Deal with incorrect swig wrappers for C++ "void operator op=()"
? ----
76 81c3bd10 + # Deal with incorrect swig wrappers for C++ "void operator op=()"
77 f8edfe90 - #
77 81c3bd10 + #
78 f8edfe90 - def __ilshift__(*args):
? ----
78 81c3bd10 + def __ilshift__(*args):
79 f8edfe90 - """__ilshift__(self, NAME## Type src) -> self"""
? ----
79 81c3bd10 + """__ilshift__(self, NAME## Type src) -> self"""
80 f8edfe90 - _imageLib.Image##TYPE##Base___ilshift__(*args)
? ----
80 81c3bd10 + _imageLib.Image##TYPE##Base___ilshift__(*args)
81 f8edfe90 - return args[0]
? ----
81 81c3bd10 + return args[0]
83 f8edfe90 - def __ior__(*args):
? ----
83 81c3bd10 + def __ior__(*args):
84 f8edfe90 - """__ior__(self, NAME##Type src) -> self"""
? ----
84 81c3bd10 + """__ior__(self, NAME##Type src) -> self"""
85 f8edfe90 - _imageLib.NAME##TYPE##___ior__(*args)
? ----
85 81c3bd10 + _imageLib.NAME##TYPE##___ior__(*args)
86 f8edfe90 - return args[0]
? ----
86 81c3bd10 + return args[0]
88 f8edfe90 - def __iand__(*args):
? ----
88 81c3bd10 + def __iand__(*args):
89 f8edfe90 - """__iand__(self, NAME##TYPE src) -> self"""
? ----
89 81c3bd10 + """__iand__(self, NAME##TYPE src) -> self"""
90 f8edfe90 - _imageLib.NAME##TYPE##___iand__(*args)
? ----
90 81c3bd10 + _imageLib.NAME##TYPE##___iand__(*args)
91 f8edfe90 - return args[0]
? ----
91 81c3bd10 + return args[0]
93 8da148de - def __ixor__(*args):
? ----
93 81c3bd10 + def __ixor__(*args):
94 8da148de - """__ixor__(self, NAME##TYPE src) -> self"""
? ----
94 81c3bd10 + """__ixor__(self, NAME##TYPE src) -> self"""
95 8da148de - _imageLib.NAME##TYPE##___ixor__(*args)
? ----
95 81c3bd10 + _imageLib.NAME##TYPE##___ixor__(*args)
96 8da148de - return args[0]
? ----
96 81c3bd10 + return args[0]
97 f8edfe90 - }
97 81c3bd10 + %}
? + } %defineClone(NAME##TYPE, lsst::afw::image::Mask, PIXEL_TYPE); %supportSlicing(lsst::afw::image::Mask, PIXEL_TYPE); %fits_reduce(lsst::afw::image::Mask); %enddef /************************************************************************************************************/ %apply int { unsigned short }; // // Must go Before the %include // %ignore lsst::afw::image::Mask::operator(); %shared_ptr(lsst::afw::image::Mask); %include "lsst/afw/image/Mask.h" %mask(Mask, U, boost::uint16_t);

Return to list

Commits in /Users/nate/repos_hsc/afw/

f8edfe90

commit f8edfe90d99d004aca1819ef00099ce827e44343
Author: rhl 
Date:   Sat Nov 15 15:18:25 2008 +0000

    Merged from new-image-api branch at [6341]

8da148de

commit 8da148de7df5154674aca8f78365b676afdff8d5
Author: rhl 
Date:   Sun Mar 22 14:44:49 2009 +0000

    Added operator ^= to help manipulate CFHT mask images

Commits in /Users/nate/repos_lsst/afw/

81c3bd10

commit 81c3bd106e6aa66e68d569426b87862d5d10f844
Author: Russell Owen 
Date:   Fri Mar 13 10:47:12 2015 -0700

    Change %python { to %python %{ in swig .i files
    
    Also outdent some cases where the resulting python
    appeared at the wrong indentation level in the interface file
    or a comment was chopped off at the beginning (including
    the leading #, resulting in comment text being treated as commands).
    
    Fix indentation errors
    
    SWIG 3.0.2 indents python code differently when using
    %pythoncode %{...%} instead of the deprecated %pythoncode {...}
    This fixes most known issues, but image slicing doesn't yet work.
    
    Make indentation of %pythoncode more robust in imageLib.i

Return to list

python/lsst/afw/image/testUtils.py

Diff:

                #!/usr/bin/env python
                
                # 
                # LSST Data Management System
                # Copyright 2008, 2009, 2010 LSST Corporation.
                # 
                # This product includes software developed by the
                # LSST Project (http://www.lsst.org/).
                #
                # This program is free software: you can redistribute it and/or modify
                # it under the terms of the GNU General Public License as published by
                # the Free Software Foundation, either version 3 of the License, or
                # (at your option) any later version.
                # 
                # This program is distributed in the hope that it will be useful,
                # but WITHOUT ANY WARRANTY; without even the implied warranty of
                # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                # GNU General Public License for more details.
                # 
                # You should have received a copy of the LSST License Statement and 
                # the GNU General Public License along with this program.  If not, 
                # see .
                #
                
                ##\file
                ## \brief Utilities to help write tests, mostly using numpy 
                ##
                ## Subroutines to move data between numpy arrays and lsst::afw::image classes
                ## Mask, Image and MaskedImage.
                ## 
                ## Please only use these for testing; they are too slow for production work!
                ## Eventually Image, Mask and MaskedImage will offer much better ways to do this.
                
                import numpy
                import lsst.afw.image as afwImage
                import lsst.afw.geom as afwGeom
                
                def makeGaussianNoiseMaskedImage(dimensions, sigma, variance=1.0):
                    """Make a gaussian noise MaskedImageF
                    
                    Inputs:
                    - dimensions: dimensions of output array (cols, rows)
                    - sigma; sigma of image plane's noise distribution
                    - variance: constant value for variance plane
                    """
                    npSize = (dimensions[1], dimensions[0])
                    image = numpy.random.normal(loc=0.0, scale=sigma, size=npSize).astype(numpy.float32)
                    mask = numpy.zeros(npSize, dtype=numpy.uint16)
                    variance = numpy.zeros(npSize, dtype=numpy.float32) + variance
                    
                    return afwImage.makeMaskedImageFromArrays(image, mask, variance)
                
                def imagesDiffer(imageArr1, imageArr2, skipMaskArr=None, rtol=1.0e-05, atol=1e-08):
                    """Compare the pixels of two image arrays; return True if close, False otherwise
                    
                    Inputs:
                    - image1: first image to compare
                    - image2: second image to compare
                    - skipMaskArr: pixels to ignore; nonzero values are skipped
                    - rtol: relative tolerance (see below)
                    - atol: absolute tolerance (see below)
                    
                    rtol and atol are positive, typically very small numbers.
                    The relative difference (rtol * abs(b)) and the absolute difference "atol" are added together
                    to compare against the absolute difference between "a" and "b".
                    
                    Return a string describing the error if the images differ significantly, an empty string otherwise
                    """
                    retStrs = []
70 4d9957d5 - if skipMaskArr != None:
? ^^
70 0d6d96ba + if skipMaskArr is not None:
? ^^^^^^ maskedArr1 = numpy.ma.array(imageArr1, copy=False, mask = skipMaskArr) maskedArr2 = numpy.ma.array(imageArr2, copy=False, mask = skipMaskArr) filledArr1 = maskedArr1.filled(0.0) filledArr2 = maskedArr2.filled(0.0) else: filledArr1 = imageArr1 filledArr2 = imageArr2 nan1 = numpy.isnan(filledArr1) nan2 = numpy.isnan(filledArr2) if numpy.any(nan1 != nan2): retStrs.append("NaNs differ") posinf1 = numpy.isposinf(filledArr1) posinf2 = numpy.isposinf(filledArr2) if numpy.any(posinf1 != posinf2): retStrs.append("+infs differ") neginf1 = numpy.isneginf(filledArr1) neginf2 = numpy.isneginf(filledArr2) if numpy.any(neginf1 != neginf2): retStrs.append("-infs differ") # compare values that should be comparable (are neither infinite, nan nor masked) valSkipMaskArr = nan1 | nan2 | posinf1 | posinf2 | neginf1 | neginf2
96 4d9957d5 - if skipMaskArr != None:
? ^^
96 0d6d96ba + if skipMaskArr is not None:
? ^^^^^^ valSkipMaskArr |= skipMaskArr valMaskedArr1 = numpy.ma.array(imageArr1, copy=False, mask = valSkipMaskArr) valMaskedArr2 = numpy.ma.array(imageArr2, copy=False, mask = valSkipMaskArr) valFilledArr1 = valMaskedArr1.filled(0.0) valFilledArr2 = valMaskedArr2.filled(0.0) if not numpy.allclose(valFilledArr1, valFilledArr2, rtol=rtol, atol=atol): errArr = numpy.abs(valFilledArr1 - valFilledArr2) maxErr = errArr.max() maxPosInd = numpy.where(errArr==maxErr) maxPosTuple = (maxPosInd[1][0], maxPosInd[0][0]) errStr = "maxDiff=%s at position %s; value=%s vs. %s" % \ (maxErr, maxPosTuple, valFilledArr1[maxPosInd][0], valFilledArr2[maxPosInd][0]) retStrs.insert(0, errStr) return "; ".join(retStrs) def masksDiffer(maskArr1, maskArr2, skipMaskArr=None): """Compare the pixels of two mask arrays; return True if they match, False otherwise Inputs: - mask1: first image to compare - mask2: second image to compare - skipMaskArr: pixels to ignore; nonzero values are skipped Return a string describing the error if the images differ significantly, an empty string otherwise """ retStr = ""
124 4d9957d5 - if skipMaskArr != None:
? ^^
124 0d6d96ba + if skipMaskArr is not None:
? ^^^^^^ maskedArr1 = numpy.ma.array(maskArr1, copy=False, mask = skipMaskArr) maskedArr2 = numpy.ma.array(maskArr2, copy=False, mask = skipMaskArr) filledArr1 = maskedArr1.filled(0.0) filledArr2 = maskedArr2.filled(0.0) else: filledArr1 = maskArr1 filledArr2 = maskArr2 if numpy.any(filledArr1 != filledArr2): errArr = numpy.abs(filledArr1 - filledArr2) maxErr = errArr.max() maxPosInd = numpy.where(errArr==maxErr) maxPosTuple = (maxPosInd[1][0], maxPosInd[0][0]) retStr = "maxDiff=%s at position %s; value=%s vs. %s" % \ (maxErr, maxPosTuple, filledArr1[maxPosInd][0], filledArr2[maxPosInd][0]) retStr = "masks differ" return retStr def maskedImagesDiffer(maskedImageArrSet1, maskedImageArrSet2, doImage=True, doMask=True, doVariance=True, skipMaskArr=None, rtol=1.0e-05, atol=1e-08): """Compare pixels from two masked images Inputs: - maskedImageArrSet1: first masked image to compare as (image, mask, variance) arrays - maskedImageArrSet2: second masked image to compare as (image, mask, variance) arrays - doImage: compare image planes if True - doMask: compare mask planes if True - doVariance: compare variance planes if True - skipMaskArr: pixels to ingore on the image, mask and variance arrays; nonzero values are skipped - rtol: relative tolerance (see below) - atol: absolute tolerance (see below) rtol and atol are positive, typically very small numbers. The relative difference (rtol * abs(b)) and the absolute difference "atol" are added together to compare against the absolute difference between "a" and "b". Return a string describing the error if the images differ significantly, an empty string otherwise """ retStrs = [] for ind, (doPlane, planeName) in enumerate(((doImage, "image"), (doMask, "mask"), (doVariance, "variance"))): if not doPlane: continue if planeName == "mask": errStr = masksDiffer(maskedImageArrSet1[ind], maskedImageArrSet2[ind], skipMaskArr=skipMaskArr) if errStr: retStrs.append(errStr) else: errStr = imagesDiffer(maskedImageArrSet1[ind], maskedImageArrSet2[ind], skipMaskArr=skipMaskArr, rtol=rtol, atol=atol) if errStr: retStrs.append("%s planes differ: %s" % (planeName, errStr)) return " | ".join(retStrs)

Return to list

Commits in /Users/nate/repos_hsc/afw/

4d9957d5

commit 4d9957d519bf0293a85fdd5585bf071afb38dd4b
Author: rowen 
Date:   Thu Jun 4 00:18:53 2009 +0000

    Implemented ticket #806: improve setting of edge pixels in convolve function.
    Note that this is an API change:
    - the convolve and convolveLinear functions have lost their edgeBit arguments
    - convolved edge pixels are now (NaN, EDGE, info) for MaskedImage and NaN for Image
    All unit tests and examples have been updated accordingly.
    
    Also added the following subroutines to lsst.afw.image.testUtils:
      imagesDiffer, masksDiffer and maskedImagesDiffer
    and modified the following tests to use them:
      ConvolveImage_1.py, ConvolveMaskedImage_1.py and warpExposure_1.py

Commits in /Users/nate/repos_lsst/afw/

0d6d96ba

commit 0d6d96ba5d78d9a5ac63f8b178fee1f32d3d77a3
Author: Tim Jenness 
Date:   Tue May 5 14:04:11 2015 -0700

    Fix warning with != being used rather than "is not"
    
    numpy now complains if a numpy array is compared with None using the !=
    operator, stating that this operator will soon be modified to do an
    elementwise comparison. The correct test is whether the value is not
    None.
    
        FutureWarning: comparison to `None` will result in an elementwise
            object comparison in the future.

Return to list

include/lsst/afw/table/BaseRecord.h

Diff:

                // -*- lsst-c++ -*-
                #ifndef AFW_TABLE_BaseRecord_h_INCLUDED
                #define AFW_TABLE_BaseRecord_h_INCLUDED
                
                #include "lsst/base.h"
                #include "lsst/afw/table/fwd.h"
                #include "lsst/afw/table/Schema.h"
                #include "lsst/afw/table/BaseTable.h"
9 cfb9c7f4 + #include "lsst/afw/table/FunctorKey.h"
namespace lsst { namespace afw { namespace table { /** * @brief Base class for all records. * * BaseRecord is a polymorphic base class that provides the core record interface: access to fields * and links back to the table it is associated with. Field access is provided by the templated * get, set, and operator[] member functions. As templates they are nonvirtual and cannot be overridden * by subclasses. The implementations for these accessors is in the FieldBase template specializations. * * Each subclass of BaseRecord should be paired with a subclass of BaseTable. All record creation * goes through a table, as the table allocates the memory used to store a record's fields and * holds the Schema instance that defines those fields. * * Records are noncopyable, and are hence usually passed by shared_ptr or [const-]reference. */ class BaseRecord #ifndef SWIG // swig complains about these not being %shared_ptr, and it doesn't need to know about them : public daf::base::Citizen, private boost::noncopyable #endif { public: /// The associated table class. typedef BaseTable Table; /// The associated ColumnView class. typedef BaseColumnView ColumnView; /// Template of CatalogT used to hold records of this type. typedef CatalogT Catalog; /// Template of CatalogT used to hold const records of this type. typedef CatalogT ConstCatalog; /// @brief Return the Schema that holds this record's fields and keys. Schema getSchema() const { return _table->getSchema(); } /// @brief Return the table this record is associated with. CONST_PTR(BaseTable) getTable() const { return _table; } /** * @brief Return a pointer to the underlying elements of a field (non-const). * * This low-level access is intended mostly for use with serialization; * users should generally prefer the safer get(), set() and operator[] * member functions. */ template typename Field::Element * getElement(Key const & key) { if (!key.isValid()) { throw LSST_EXCEPT(
63 341e49d9 - pex::exceptions::LogicErrorException,
? ---------
64 21597d88 + pex::exceptions::LogicError,
"Key is not valid (if this is a SourceRecord, make sure slot aliases have been setup)." ); } return reinterpret_cast::Element*>( reinterpret_cast(_data) + key.getOffset() ); } /** * @brief Return a pointer to the underlying elements of a field (const). * * This low-level access is intended mostly for use with serialization; * users should generally prefer the safer get(), set() and operator[] * member functions. */ template typename Field::Element const * getElement(Key const & key) const { if (!key.isValid()) { throw LSST_EXCEPT(
83 341e49d9 - pex::exceptions::LogicErrorException,
? ---------
84 21597d88 + pex::exceptions::LogicError,
"Key is not valid (if this is a SourceRecord, make sure slot aliases have been setup)." ); } return reinterpret_cast::Element const *>( reinterpret_cast(_data) + key.getOffset() ); } /** * @brief Return a reference (or reference-like type) to the field's value. * * Some field types (Point, Moments, Flag, Covariance, and Coord) do not support reference access. * * No checking is done to ensure the Key belongs to the correct schema. */ template typename Field::Reference operator[](Key const & key) { return key.getReference(getElement(key), _manager); } /** * @brief Return a const reference (or const-reference-like type) to the field's value. * * Some field types (Point, Moments, Flag, Covariance, and Coord) do not support reference access. * * No checking is done to ensure the Key belongs to the correct schema. */ template typename Field::ConstReference operator[](Key const & key) const { return key.getConstReference(getElement(key), _manager); } /** * @brief Return the value of a field for the given key. * * No checking is done to ensure the Key belongs to the correct schema. */ template typename Field::Value get(Key const & key) const { return key.getValue(getElement(key), _manager); } /** * @brief Set value of a field for the given key. * * This method has an additional template parameter because some fields * accept and convert different types to the stored field type. * * No checking is done to ensure the Key belongs to the correct schema. */ template void set(Key const & key, U const & value) { key.setValue(getElement(key), _manager, value); }
140 cfb9c7f4 + #ifndef SWIG
141 cfb9c7f4 +
142 cfb9c7f4 + /**
143 cfb9c7f4 + * @brief Compute a calculated or aggregate field.
144 cfb9c7f4 + */
145 cfb9c7f4 + template
146 cfb9c7f4 + T get(OutputFunctorKey const & key) const {
147 cfb9c7f4 + return key.get(*this);
148 cfb9c7f4 + }
149 cfb9c7f4 +
150 cfb9c7f4 + /**
151 cfb9c7f4 + * @brief Set a calculated or aggregate field.
152 cfb9c7f4 + */
153 4e32ed4b + template
154 4e32ed4b + void set(InputFunctorKey const & key, U const & value) {
155 cfb9c7f4 + return key.set(*this, value);
156 cfb9c7f4 + }
157 cfb9c7f4 +
158 e83c9f0f + template
159 e83c9f0f + Ref operator[](ReferenceFunctorKey const & key) {
160 e83c9f0f + return key.getReference(*this);
161 e83c9f0f + }
162 e83c9f0f +
163 e83c9f0f + template
164 742a0d0e + ConstRef operator[](ConstReferenceFunctorKey const & key) const {
165 e83c9f0f + return key.getConstReference(*this);
166 e83c9f0f + }
167 e83c9f0f +
168 cfb9c7f4 + #endif // !SWIG
169 cfb9c7f4 +
/// @brief Copy all field values from other to this, requiring that they have equal schemas. void assign(BaseRecord const & other); /// @brief Copy field values from other to this, using a mapper. void assign(BaseRecord const & other, SchemaMapper const & mapper);
175 d0b9726b +
176 d2cae5ca + ndarray::Manager::Ptr getManager() const { return _manager; }
virtual ~BaseRecord() { _table->_destroy(*this); } protected: /// @brief Called by assign() after transferring fields to allow subclass data members to be copied. virtual void _assign(BaseRecord const & other) {} /// @brief Construct a record with uninitialized data. BaseRecord(PTR(BaseTable) const & table) : daf::base::Citizen(typeid(this)), _table(table) { table->_initialize(*this); } private: friend class BaseTable; friend class BaseColumnView; // All these are definitely private, not protected - we don't want derived classes mucking with them. void * _data; // pointer to field data PTR(BaseTable) _table; // the associated table ndarray::Manager::Ptr _manager; // shared manager for lifetime of _data (like shared_ptr with no pointer) }; }}} // namespace lsst::afw::table #endif // !AFW_TABLE_BaseRecord_h_INCLUDED

Return to list

Commits in /Users/nate/repos_hsc/afw/

341e49d9

commit 341e49d974b202e73897db621bb367ebc065c265
Author: Jim Bosch 
Date:   Mon May 7 15:39:45 2012 -0400

    Throw exceptions for invalid table keys rather than assert.

Commits in /Users/nate/repos_lsst/afw/

d2cae5ca

commit d2cae5ca01a1d7d77929a598252cf33030014cca
Author: Jim Bosch 
Date:   Fri Sep 19 15:55:18 2014 -0400

    Add memory-manager getter to BaseRecord
    
    This will be necessary to support FunctorKeys that return arrays.

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

742a0d0e

commit 742a0d0eed5391921c552a88f1a787c4ec13530c
Author: Jim Bosch 
Date:   Mon Sep 22 21:48:12 2014 -0400

    FunctorKey-based const reference access should be a const method.

d0b9726b

commit d0b9726bd73d8d763492f24fdea9d8272f185844
Author: Jim Bosch 
Date:   Mon Nov 28 14:20:55 2011 -0500

    added ModificationFlags as a run-time constness substitute, renamed 'erase' -> 'unlink' to reflect the fact that records aren't actually deleted

cfb9c7f4

commit cfb9c7f46b1c0486102a1eb7e2caa7032eee2efc
Author: Jim Bosch 
Date:   Wed Apr 9 11:41:43 2014 -0400

    Started work on FunctorKey

e83c9f0f

commit e83c9f0fc32ce0bd64230bb765cbdb28e06916b2
Author: Jim Bosch 
Date:   Sat Sep 20 08:24:50 2014 -0400

    Add base classes for FunctorKeys that return reference objects

4e32ed4b

commit 4e32ed4bc5a95b7ae0c02bb1faa78be0fd33bb1e
Author: Jim Bosch 
Date:   Mon Sep 22 21:24:43 2014 -0400

    Use two template arguments in FunctorKey invocation
    
    This lets us support implicit conversion in FunctorKey-based set.

Return to list

tests/random1.py

Diff:

1 282b39c2 - #!/usr/bin/env python
1 b80fe1d3 + #!/usr/bin/env python2
? +
2 b80fe1d3 + from __future__ import absolute_import, division
# # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for the lsst.afw.math.Random Python wrapper Run with: python Random_1.py or python >>> import unittest; T=load("Random_1"); unittest.TextTestRunner(verbosity=1).run(T.suite()) """ import time import unittest import lsst.pex.policy as pexPolicy import lsst.utils.tests as utilsTests import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def checkRngEquivalence(rng1, rng2): for i in xrange(1000): assert rng1.uniform() == rng2.uniform() def getSeed(): return int(time.time() * 1000000.0) % 1000000 class RandomTestCase(unittest.TestCase): """A test case for lsst.afw.math.Random""" def setUp(self): pass def tearDown(self): pass def testCreate(self): rngs = [] for name in afwMath.Random.getAlgorithmNames(): rngs.append(afwMath.Random(name)) for r in rngs: assert afwMath.Random(r.getAlgorithmName()).uniform() == r.uniform() r2 = afwMath.Random(r.getAlgorithm()) r2.uniform() assert r2.uniform() == r.uniform() def testCopy(self): """ Test that the generator returned by deepCopy() produces an identical random number sequence to its prototype """ rng1 = afwMath.Random(afwMath.Random.MT19937, getSeed()) rng2 = rng1.deepCopy() checkRngEquivalence(rng1, rng2) def testPolicy(self): """ Tests that policy files and environment variables can override user specified algorithms and seed values. """ pol = pexPolicy.Policy() seed = getSeed() pol.set("rngSeed", str(seed)) pol.set("rngAlgorithm", afwMath.Random.getAlgorithmNames()[afwMath.Random.RANLXD2]) r1 = afwMath.Random(afwMath.Random.RANLXD2, seed) r2 = afwMath.Random(pol) checkRngEquivalence(r1, r2) class RandomImageTestCase(unittest.TestCase): """A test case for lsst.afw.math.Random applied to Images""" def setUp(self): self.rand = afwMath.Random() self.image = afwImage.ImageF(afwGeom.Extent2I(1000, 1000)) def tearDown(self): del self.image def testState(self): for i in range(100): self.rand.uniformInt(10000) state = self.rand.getState() v1 = [self.rand.uniformInt(10000) for i in range(100)] self.rand.setState(state) v2 = [self.rand.uniformInt(10000) for i in range(100)] self.assertEqual(v1, v2) def testRandomUniformImage(self): afwMath.randomUniformImage(self.image, self.rand) #stats = afwMath.makeStatistics(self.image, afwMath.MEAN | afwMath.STDEV) def testRandomGaussianImage(self): afwMath.randomGaussianImage(self.image, self.rand) #stats = afwMath.makeStatistics(self.image, afwMath.MEAN | afwMath.STDEV) def testRandomChisqImage(self): nu = 10 afwMath.randomChisqImage(self.image, self.rand, nu) stats = afwMath.makeStatistics(self.image, afwMath.MEAN | afwMath.VARIANCE) if False: print "nu = %g. mean = %g, variance = %g" % \ (nu, stats.getValue(afwMath.MEAN), stats.getValue(afwMath.VARIANCE)) self.assertAlmostEqual(stats.getValue(afwMath.MEAN), nu, 1) self.assertAlmostEqual(stats.getValue(afwMath.VARIANCE), 2*nu, 1) def testRandomPoissonImage(self): mu = 10 afwMath.randomPoissonImage(self.image, self.rand, mu) stats = afwMath.makeStatistics(self.image, afwMath.MEAN | afwMath.VARIANCE) if False: print "mu = %g. mean = %g, variance = %g" % \ (mu, stats.getValue(afwMath.MEAN), stats.getValue(afwMath.VARIANCE)) self.assertAlmostEqual(stats.getValue(afwMath.MEAN), mu, 1) self.assertAlmostEqual(stats.getValue(afwMath.VARIANCE), mu, 1) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(RandomTestCase) suites += unittest.makeSuite(RandomImageTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

Return to list

Commits in /Users/nate/repos_hsc/afw/

282b39c2

commit 282b39c2fe1558a4990a95d7ad77a6c634a2ccb5
Author: smm 
Date:   Thu Mar 5 08:57:19 2009 +0000

    #678: shorter names, provide factory functions for RNG creation which allow policy/env variables to override algorithm/seed parameters

Commits in /Users/nate/repos_lsst/afw/

b80fe1d3

commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
Author: Russell Owen 
Date:   Mon Oct 27 18:01:15 2014 -0700

    Support from __future__ import division
    for classes such as Extension that support operator/ and/or operator/=
    and change unit tests to use it

Return to list

include/lsst/afw/math/detail/Convolve.h

Diff:

                // -*- LSST-C++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                #ifndef LSST_AFW_MATH_DETAIL_CONVOLVE_H
                #define LSST_AFW_MATH_DETAIL_CONVOLVE_H
                /**
                 * @file
                 *
                 * @brief Convolution support
                 *
                 * @author Russell Owen
                 *
                 * @ingroup afw
                 */
                #include 
                
                #include "boost/shared_ptr.hpp"
                
                #include "lsst/pex/exceptions.h"
                #include "lsst/afw/geom.h"
                #include "lsst/afw/image/Image.h"
                #include "lsst/afw/image/MaskedImage.h"
                #include "lsst/afw/math/Kernel.h"
                #include "lsst/afw/math/ConvolveImage.h"
                #include "lsst/afw/gpu/GpuExceptions.h"
                
                #define IS_INSTANCE(A, B) (dynamic_cast(&(A)) != NULL)
                
                namespace lsst {
                namespace afw {
                namespace math {
                
                namespace detail {
                    template 
                    void basicConvolve(
                            OutImageT& convolvedImage,
                            InImageT const& inImage,
                            lsst::afw::math::Kernel const& kernel,
                            lsst::afw::math::ConvolutionControl const& convolutionControl);
                    
                    template 
                    void basicConvolve(
                            OutImageT& convolvedImage,
                            InImageT const& inImage,
                            lsst::afw::math::DeltaFunctionKernel const& kernel,
                            lsst::afw::math::ConvolutionControl const&);
                    
                    template 
                    void basicConvolve(
                            OutImageT& convolvedImage,
                            InImageT const& inImage,
                            lsst::afw::math::LinearCombinationKernel const& kernel,
                            lsst::afw::math::ConvolutionControl const& convolutionControl);
                    
                    template 
                    void basicConvolve(
                            OutImageT& convolvedImage,
                            InImageT const& inImage,
                            lsst::afw::math::SeparableKernel const& kernel,
                            lsst::afw::math::ConvolutionControl const& convolutionControl);
                
                    template 
                    void convolveWithBruteForce(
                            OutImageT &convolvedImage,
                            InImageT const& inImage,
                            lsst::afw::math::Kernel const& kernel,
                            lsst::afw::math::ConvolutionControl const& convolutionControl);
                
                    // I would prefer this to be nested in KernelImagesForRegion but SWIG doesn't support that
                    class RowOfKernelImagesForRegion;
                
                    /**
                     * A collection of Kernel images for special locations on a rectangular region of an image
                     *
                     * See the Location enum for a list of those special locations.
                     *
                     * @warning The kernel images along the top and right edges are computed one row or column past
                     * the bounding box. This allows abutting KernelImagesForRegion to share corner and edge kernel images,
                     * which is useful when dividing a KernelImagesForRegion into subregions.
                     *
                     * @warning The bounding box for the region applies to the parent image.
                     *
                     * This is a low-level helper class for recursive convolving with interpolation. Many of these objects
                     * may be created during a convolution, and many will share kernel images. It uses shared pointers
                     * to kernels and kernel images for increased speed and decreased memory usage (at the expense of safety).
                     * Note that null pointers are NOT acceptable for the constructors!
                     *
                     * Also note that it uses lazy evaluation: images are computed when they are wanted.
                     */
                    class KernelImagesForRegion :
                        public lsst::daf::base::Citizen,
                        public lsst::daf::base::Persistable
                    {
                    public:
                        typedef CONST_PTR(lsst::afw::math::Kernel) KernelConstPtr;
                        typedef lsst::afw::image::Image Image;
                        typedef PTR(Image) ImagePtr;
                        typedef CONST_PTR(Image) ImageConstPtr;
                        typedef CONST_PTR(KernelImagesForRegion) ConstPtr;
                        typedef PTR(KernelImagesForRegion) Ptr;
                
                        /**
                         * locations of various points in the region
                         *
                         * RIGHT and TOP are one column/row beyond the region's bounding box.
                         * Thus adjacent regions share corner images.
                         *
                         * The posiitions are: BOTTOM_LEFT, BOTTOM_RIGHT, TOP_LEFT, TOP_RIGHT
                         *
                         * These locations always refer to the center of a pixel. Thus if the region has an odd size
                         * along an axis (so that the span to the top and right, which are one beyond, is even),
                         * the middle pixel will be 1/2 pixel off from the true center along that axis
                         * (in an unspecified direction).
                         */
                        enum Location {
                            BOTTOM_LEFT, BOTTOM_RIGHT, TOP_LEFT, TOP_RIGHT
                        };
                    
                        KernelImagesForRegion(
                                KernelConstPtr kernelPtr,
                                lsst::afw::geom::Box2I const &bbox,
                                lsst::afw::geom::Point2I const &xy0,
                                bool doNormalize);
                        KernelImagesForRegion(
                                KernelConstPtr kernelPtr,
                                lsst::afw::geom::Box2I const &bbox,
                                lsst::afw::geom::Point2I const &xy0,
                                bool doNormalize,
                                ImagePtr bottomLeftImagePtr,
                                ImagePtr bottomRightImagePtr,
                                ImagePtr topLeftImagePtr,
                                ImagePtr topRightImagePtr);
                
                        /** 
                         * Get the bounding box for the region
                         */
                        lsst::afw::geom::Box2I getBBox() const { return _bbox; };
                        /**
                         * Get xy0 of the image
                         */
                        lsst::afw::geom::Point2I getXY0() const { return _xy0; };
                        /**
                         * Get the doNormalize parameter
                         */
                        bool getDoNormalize() const { return _doNormalize; };
                        ImagePtr getImage(Location location) const;
                        /**
                         * Get the kernel (as a shared pointer to const)
                         */
                        KernelConstPtr getKernel() const { return _kernelPtr; };
                        lsst::afw::geom::Point2I getPixelIndex(Location location) const;
                        bool computeNextRow(RowOfKernelImagesForRegion ®ionRow) const;
                
                        /**
                         * Get the minInterpolationSize class constant
                         */
                        static int getMinInterpolationSize() { return _MinInterpolationSize; };
                    private:
                        typedef std::vector LocationList;
                
                        void _computeImage(Location location) const;
                        inline void _insertImage(Location location, ImagePtr imagePtr) const;
                        void _moveUp(bool isFirst, int newHeight);
                        
                        // static helper functions
                        static inline int _computeNextSubregionLength(int length, int nDivisions);
                        static std::vector _computeSubregionLengths(int length, int nDivisions);
                
                        // member variables
                        KernelConstPtr _kernelPtr;
                        lsst::afw::geom::Box2I _bbox;
                        lsst::afw::geom::Point2I _xy0;
                        bool _doNormalize;
                        mutable std::vector _imagePtrList;
                
                        static int const _MinInterpolationSize;
                    };
                    
                    /**
                     * @brief A row of KernelImagesForRegion
                     *
                     * Intended for iterating over subregions of a KernelImagesForRegion using computeNextRow.
                     */
                    class RowOfKernelImagesForRegion {
                    public:
                        typedef std::vector RegionList;
                        typedef RegionList::iterator Iterator;
                        typedef RegionList::const_iterator ConstIterator;
                        
                        RowOfKernelImagesForRegion(int nx, int ny);
                        /**
                         * @brief Return the begin iterator for the list
                         */
                        RegionList::const_iterator begin() const { return _regionList.begin(); };
                        /**
                         * @brief Return the end iterator for the list
                         */
                        RegionList::const_iterator end() const { return _regionList.end(); };
                        /**
                         * @brief Return the begin iterator for the list
                         */
                        RegionList::iterator begin() { return _regionList.begin(); };
                        /**
                         * @brief Return the end iterator for the list
                         */
                        RegionList::iterator end() { return _regionList.end(); };
                        /**
                         * @brief Return the first region in the list
                         */
                        PTR(KernelImagesForRegion) front() { return _regionList.front(); };
                        /**
                         * @brief Return the last region in the list
                         */
                        PTR(KernelImagesForRegion) back() { return _regionList.back(); };
                        int getNX() const { return _nx; };
                        int getNY() const { return _ny; };
                        int getYInd() const { return _yInd; };
                        /**
                         * @brief get the specified region (range-checked)
                         *
                         * @throw std::range_error if ind out of range
                         */
                        CONST_PTR(KernelImagesForRegion) getRegion(int ind) const { return _regionList.at(ind); };
                        bool hasData() const { return static_cast(_regionList[0]); };
                        bool isLastRow() const { return _yInd + 1 >= _ny; };
                        int incrYInd() { return ++_yInd; };
                        
                    private:
                        int _nx;
                        int _ny;
                        int _yInd;
                        RegionList _regionList;
                    };
                    
                    template 
                    void convolveWithInterpolation(
                            OutImageT &outImage,
                            InImageT const &inImage,
                            lsst::afw::math::Kernel const &kernel,
                            ConvolutionControl const &convolutionControl);
                
                    /**
                     * @brief kernel images used by convolveRegionWithInterpolation
                     */
                    struct ConvolveWithInterpolationWorkingImages {
                    public:
                        typedef lsst::afw::image::Image Image;
                        ConvolveWithInterpolationWorkingImages(geom::Extent2I const & dimensions) :
                            leftImage(dimensions),
                            rightImage(dimensions),
                            leftDeltaImage(dimensions),
                            rightDeltaImage(dimensions),
                            deltaImage(dimensions),
                            kernelImage(dimensions)
                        { }
                        Image leftImage;
                        Image rightImage;
                        Image leftDeltaImage;
                        Image rightDeltaImage;
                        Image deltaImage;
                        Image kernelImage;
                    };
                
                    template 
                    void convolveRegionWithInterpolation(
                            OutImageT &outImage,
                            InImageT const &inImage,
                            KernelImagesForRegion const ®ion,
                            ConvolveWithInterpolationWorkingImages &workingImages);
                }}}}   // lsst::afw::math::detail
                
                /*
                 * Define inline functions
                 */
                
                /**
                 * Compute length of next subregion if the region is to be divided into pieces of approximately equal length.
                 *
                 * @return length of next subregion
                 *
                 * @warning: no range checking
                 */
                inline int lsst::afw::math::detail::KernelImagesForRegion::_computeNextSubregionLength(
                    int length,     ///< length of region
                    int nDivisions) ///< number of divisions of region
                {
                    return static_cast(std::floor(0.5 +
                        (static_cast(length) / static_cast(nDivisions))));
                }
                
                /**
                 * Insert an image in the cache.
                 *
315 8ecfc75f - * @throw lsst::pex::exceptions::InvalidParameterException if image pointer is null
? ^^^^^^ ^
315 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if image pointer is null
? ^^ ^
316 8ecfc75f - * @throw lsst::pex::exceptions::InvalidParameterException if image has the wrong dimensions
? ^^^^^^ ^
316 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if image has the wrong dimensions
? ^^ ^ */ inline void lsst::afw::math::detail::KernelImagesForRegion::_insertImage( Location location, ///< location at which to insert image ImagePtr imagePtr) ///< image to insert const { if (imagePtr) { if (_kernelPtr->getDimensions() != imagePtr->getDimensions()) { std::ostringstream os; os << "image dimensions = ( " << imagePtr->getWidth() << ", " << imagePtr->getHeight() << ") != (" << _kernelPtr->getWidth() << ", " << _kernelPtr->getHeight() << ") = kernel dimensions";
329 8ecfc75f - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException, os.str());
? ^^^^^^ ^
329 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, os.str());
? ^^ ^ } _imagePtrList[location] = imagePtr; } } #endif // !defined(LSST_AFW_MATH_DETAIL_CONVOLVE_H)

Return to list

Commits in /Users/nate/repos_hsc/afw/

8ecfc75f

commit 8ecfc75fa7cc5428df87b7e90918afd0118ee912
Author: rowen 
Date:   Fri Apr 30 22:11:51 2010 +0000

    Refactored to put math::detail code into its own directory and python namespace.

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

Return to list

include/lsst/afw/math/Statistics.h

Diff:

                // -*- LSST-C++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                #if !defined(LSST_AFW_MATH_STATISTICS_H)
                #define LSST_AFW_MATH_STATISTICS_H
                /**
                 * @file Statistics.h
                 * @brief Compute Image Statistics
                 * @ingroup afw
                 * @author Steve Bickerton
                 *
                 * @note The Statistics class itself can only handle lsst::afw::image::MaskedImage() types.
                 *       The philosophy has been to handle other types by making them look like
                 *       lsst::afw::image::MaskedImage() and reusing that code.
                 *       Users should have no need to instantiate a Statistics object directly,
                 *       but should use the overloaded makeStatistics() factory functions.
                 */
                
                #include 
                #include 
                #include 
                #include "boost/iterator/iterator_adaptor.hpp"
                #include "boost/tuple/tuple.hpp"
                #include "boost/shared_ptr.hpp"
                #include "lsst/afw/image/MaskedImage.h"
                #include "lsst/afw/math/MaskedVector.h"
                
                namespace lsst {
                namespace afw {
                    namespace image {
                        template class Image;
                        template class MaskedImage;
                    }
                namespace math {
                    template class MaskedVector; // forward declaration
                
                    typedef lsst::afw::image::VariancePixel WeightPixel; // Type used for weights
                            
                /**
                 * @brief control what is calculated
                 */
                enum Property {
                    NOTHING = 0x0,         ///< We don't want anything
                    ERRORS = 0x1,          ///< Include errors of requested quantities
                    NPOINT = 0x2,          ///< number of sample points
                    MEAN = 0x4,            ///< estimate sample mean
                    STDEV = 0x8,           ///< estimate sample standard deviation
                    VARIANCE = 0x10,       ///< estimate sample variance
                    MEDIAN = 0x20,         ///< estimate sample median
                    IQRANGE = 0x40,        ///< estimate sample inter-quartile range
                    MEANCLIP = 0x80,       ///< estimate sample N-sigma clipped mean (N set in StatisticsControl, default=3)
                    STDEVCLIP = 0x100,     ///< estimate sample N-sigma clipped stdev (N set in StatisticsControl, default=3)
                    VARIANCECLIP = 0x200,  ///< estimate sample N-sigma clipped variance
                                           ///<  (N set in StatisticsControl, default=3)
                    MIN = 0x400,           ///< estimate sample minimum
                    MAX = 0x800,           ///< estimate sample maximum
                    SUM = 0x1000,          ///< find sum of pixels in the image
                    MEANSQUARE = 0x2000,   ///< find mean value of square of pixel values
                    ORMASK = 0x4000        ///< get the or-mask of all pixels used.
                };
                Property stringToStatisticsProperty(std::string const property);
                
                    
                /**
                 * @brief Pass parameters to a Statistics object
                 * @ingroup afw
                 *
                 * A class to pass parameters which control how the stats are calculated.
                 * 
                 */
                class StatisticsControl {
                    typedef enum { WEIGHTS_FALSE=0, WEIGHTS_TRUE=1, WEIGHTS_NONE } WeightsBoolean; // initial state is NONE
                public:
                
                    typedef boost::shared_ptr Ptr;
                    typedef boost::shared_ptr const ConstPtr;
                    
                    StatisticsControl(
                        double numSigmaClip = 3.0, ///< number of standard deviations to clip at
                        int numIter = 3,           ///< Number of iterations
                        lsst::afw::image::MaskPixel andMask = 0x0, ///< and-Mask: defines which mask bits cause a value to be ignored
103 06220a25 - bool isNanSafe = true, ///< flag NaNs
103 6e8b043b + bool isNanSafe = true, ///< flag NaNs & Infs
? +++++++ int useWeights = WEIGHTS_NONE ///< use weighted statistics (via a vector or an inverse variance) ) : _numSigmaClip(numSigmaClip), _numIter(numIter), _andMask(andMask), _noGoodPixelsMask(0x0), _isNanSafe(isNanSafe), _useWeights(useWeights == 0 ? WEIGHTS_FALSE : (useWeights == 1) ? WEIGHTS_TRUE : WEIGHTS_NONE),
112 6eed36a1 - _calcErrorFromInputVariance(false),
? -
112 b789cea1 + _calcErrorFromInputVariance(false)
113 6eed36a1 - _maskPropagationThresholds()
{ try {
116 73fb00fd - _noGoodPixelsMask = lsst::afw::image::Mask<>::getPlaneBitMask("NO_DATA");
? ^^^ ^^^
115 ed634991 + _noGoodPixelsMask = lsst::afw::image::Mask<>::getPlaneBitMask("EDGE");
? ^ ^^
117 ed634991 - } catch(lsst::pex::exceptions::InvalidParameterException) {
? ^^^^^^ ^
116 21597d88 + } catch(lsst::pex::exceptions::InvalidParameterError) {
? ^^ ^
118 73fb00fd - ; // Mask has no NO_DATA plane defined
? ^^^ ^^^
117 ed634991 + ; // Mask has no EDGE plane defined
? ^ ^^ } assert(_numSigmaClip > 0); assert(_numIter > 0); }
124 4a374367 -
125 6eed36a1 - //@{
126 6eed36a1 - /** When pixels with the given bit are rejected, we count what fraction the rejected
127 6eed36a1 - * pixels would have contributed (including the weights, if any) if those pixels had
128 6eed36a1 - * not been rejected, and set that bit in the return value of Statistics::getOrMask()
129 6eed36a1 - * if it exceeds the given threshold.
130 6eed36a1 - */
131 6eed36a1 - double getMaskPropagationThreshold(int bit) const;
132 6eed36a1 - void setMaskPropagationThreshold(int bit, double threshold);
133 6eed36a1 - //@}
double getNumSigmaClip() const { return _numSigmaClip; } int getNumIter() const { return _numIter; } int getAndMask() const { return _andMask; } int getNoGoodPixelsMask() const { return _noGoodPixelsMask; } bool getNanSafe() const { return _isNanSafe; } bool getWeighted() const { return _useWeights == WEIGHTS_TRUE ? true : false; } bool getWeightedIsSet() const { return _useWeights != WEIGHTS_NONE ? true : false; } bool getCalcErrorFromInputVariance() const { return _calcErrorFromInputVariance; } void setNumSigmaClip(double numSigmaClip) { assert(numSigmaClip > 0); _numSigmaClip = numSigmaClip; } void setNumIter(int numIter) { assert(numIter > 0); _numIter = numIter; } void setAndMask(int andMask) { _andMask = andMask; } void setNoGoodPixelsMask(int noGoodPixelsMask) { _noGoodPixelsMask = noGoodPixelsMask; } void setNanSafe(bool isNanSafe) { _isNanSafe = isNanSafe; } void setWeighted(bool useWeights) { _useWeights = useWeights ? WEIGHTS_TRUE : WEIGHTS_FALSE; } void setCalcErrorFromInputVariance(bool calcErrorFromInputVariance) { _calcErrorFromInputVariance = calcErrorFromInputVariance; } private:
155 6eed36a1 -
156 6eed36a1 - friend class Statistics;
157 6eed36a1 -
double _numSigmaClip; // Number of standard deviations to clip at int _numIter; // Number of iterations int _andMask; // and-Mask to specify which mask planes to ignore int _noGoodPixelsMask; // mask to set if no values are acceptable
162 a3819593 - bool _isNanSafe; // Check for NaNs before running (slower)
148 6e8b043b + bool _isNanSafe; // Check for NaNs & Infs before running (slower)
? +++++++ WeightsBoolean _useWeights; // Calculate weighted statistics (enum because of 3-valued logic) bool _calcErrorFromInputVariance; // Calculate errors from the input variances, if available
165 6eed36a1 - std::vector _maskPropagationThresholds; // Thresholds for when to propagate mask bits,
166 6eed36a1 - // treated like a dict (unset bits are set to 1.0)
}; /** * @ingroup afw * * A class to evaluate %image statistics * * The basic strategy is to construct a Statistics object from an Image and * a statement of what we want to know. The desired results can then be * returned using Statistics methods. A StatisticsControl object is used to * pass parameters. The statistics currently implemented are listed in the * enum Properties in Statistics.h. * * @code // sets NumSigclip (3.0), and NumIter (3) for clipping lsst::afw::math::StatisticsControl sctrl(3.0, 3); sctrl.setNumSigmaClip(4.0); // reset number of standard deviations for N-sigma clipping sctrl.setNumIter(5); // reset number of iterations for N-sigma clipping sctrl.setAndMask(0x1); // ignore pixels with these mask bits set
187 093be85f - sctrl.setNanSafe(true); // check for NaNs, a bit slower (default=true)
171 6e8b043b + sctrl.setNanSafe(true); // check for NaNs & Infs, a bit slower (default=true)
? +++++++ lsst::afw::math::Statistics statobj = lsst::afw::math::makeStatistics(*img, afwMath::NPOINT | afwMath::MEAN | afwMath::MEANCLIP, sctrl); double const n = statobj.getValue(lsst::afw::math::NPOINT); std::pair const mean = statobj.getResult(lsst::afw::math::MEAN); // Returns (value, error) double const meanError = statobj.getError(lsst::afw::math::MEAN); // just the error * @endcode * * @note Factory function: We used a helper function, \c makeStatistics, rather that the constructor * directly so that the compiler could deduce the types -- cf. \c std::make_pair) *
201 a3819593 - * @note Inputs: The class Statistics is templatized, and makeStatistics() can take either:
? --
185 89372b8c + * @note Inputs: The class Statistics is templated, and makeStatistics() can take either:
* (1) an image, (2) a maskedImage, or (3) a std::vector<> * Overloaded makeStatistics() functions then wrap what they were passed in Image/Mask-like classes * and call the Statistics constructor. * @note Clipping: The clipping is done iteratively with numSigmaClip and numIter specified in * the StatisticsControl object. The first clip (ie. the first iteration) is performed at: * median +/- numSigmaClip*IQ_TO_STDEV*IQR, where IQ_TO_STDEV=~0.74 is the conversion factor * between the IQR and sigma for a Gaussian distribution. All subsequent iterations perform * clips at mean +/- numSigmaClip*stdev. * */ class Statistics { public: /// The type used to report (value, error) for desired statistics typedef std::pair Value; template explicit Statistics(ImageT const &img, MaskT const &msk, VarianceT const &var, int const flags, StatisticsControl const& sctrl = StatisticsControl()); template explicit Statistics(ImageT const &img, MaskT const &msk, VarianceT const &var, WeightT const &weights, int const flags, StatisticsControl const& sctrl = StatisticsControl()); Value getResult(Property const prop = NOTHING) const; double getError(Property const prop = NOTHING) const; double getValue(Property const prop = NOTHING) const; lsst::afw::image::MaskPixel getOrMask() const { return _allPixelOrMask; } private: long _flags; // The desired calculation int _n; // number of pixels in the image Value _mean; // the image's mean Value _variance; // the image's variance double _min; // the image's minimum double _max; // the image's maximum double _sum; // the sum of all the image's pixels Value _meanclip; // the image's N-sigma clipped mean Value _varianceclip; // the image's N-sigma clipped variance Value _median; // the image's median double _iqrange; // the image's interquartile range lsst::afw::image::MaskPixel _allPixelOrMask; // the 'or' of all masked pixels StatisticsControl _sctrl; // the control structure bool _weightsAreMultiplicative; // Multiply by weights rather than dividing by them template void doStatistics(ImageT const &img, MaskT const &msk, VarianceT const &var, WeightT const &weights, int const flags, StatisticsControl const& sctrl); }; /************************************* The factory functions **********************************/ /** * @brief This iterator will never increment. It is returned by row_begin() in the MaskImposter class * (below) to allow phony mask pixels to be iterated over for non-mask images within Statistics. */ template class infinite_iterator : public boost::iterator_adaptor, const ValueT*, const ValueT, boost::forward_traversal_tag> { public: infinite_iterator() : infinite_iterator::iterator_adaptor_(0) {} explicit infinite_iterator(const ValueT* p) : infinite_iterator::iterator_adaptor_(p) {} private: friend class boost::iterator_core_access; void increment() { ; } // never actually advance the iterator }; /** * @brief A Mask wrapper to provide an infinite_iterator for Mask::row_begin(). This allows a fake * Mask to be passed in to Statistics with a regular (non-masked) Image. */ template class MaskImposter { public: typedef infinite_iterator x_iterator; explicit MaskImposter(ValueT val = 0) { _val[0] = val; } x_iterator row_begin(int) const { return x_iterator(_val); } private: ValueT _val[1]; }; /** * @brief Handle a watered-down front-end to the constructor (no variance) * @relates Statistics */ template Statistics makeStatistics(lsst::afw::image::Image const &img, lsst::afw::image::Mask const &msk, int const flags, StatisticsControl const& sctrl = StatisticsControl() ) { MaskImposter var; return Statistics(img, msk, var, flags, sctrl); } /** * @brief Handle a straight front-end to the constructor * @relates Statistics */ template Statistics makeStatistics(ImageT const &img, MaskT const &msk, VarianceT const &var, int const flags, StatisticsControl const& sctrl = StatisticsControl() ) { return Statistics(img, msk, var, flags, sctrl); } /** * @brief Handle MaskedImages, just pass the getImage() and getMask() values right on through. * @relates Statistics */ template Statistics makeStatistics( lsst::afw::image::MaskedImage const &mimg, int const flags, StatisticsControl const& sctrl = StatisticsControl() ) { if (sctrl.getWeighted() || sctrl.getCalcErrorFromInputVariance()) { return Statistics(*mimg.getImage(), *mimg.getMask(), *mimg.getVariance(), flags, sctrl); } else { MaskImposter var; return Statistics(*mimg.getImage(), *mimg.getMask(), var, flags, sctrl); } } /** * @brief Handle MaskedImages, just pass the getImage() and getMask() values right on through. * @relates Statistics */ template Statistics makeStatistics( lsst::afw::image::MaskedImage const &mimg, lsst::afw::image::Image const &weights, int const flags, StatisticsControl const& sctrl = StatisticsControl() ) { if (sctrl.getWeighted() || sctrl.getCalcErrorFromInputVariance() || (!sctrl.getWeightedIsSet() && (weights.getWidth() != 0 && weights.getHeight() != 0))) { return Statistics(*mimg.getImage(), *mimg.getMask(), *mimg.getVariance(), weights, flags, sctrl); } else { MaskImposter var; return Statistics(*mimg.getImage(), *mimg.getMask(), var, weights, flags, sctrl); } } /** * @brief Front end for specialization to handle Masks * @note The definition (in Statistics.cc) simply calls the specialized constructor * @relates Statistics */ Statistics makeStatistics(lsst::afw::image::Mask const &msk, int const flags, StatisticsControl const& sctrl = StatisticsControl()); /** * @brief The makeStatistics() overload to handle regular (non-masked) Images * @relates Statistics */ template Statistics makeStatistics( lsst::afw::image::Image const &img, ///< Image (or Image) whose properties we want int const flags, ///< Describe what we want to calculate StatisticsControl const& sctrl = StatisticsControl() ///< Control calculation ) { // make a phony mask that will be compiled out MaskImposter const msk; MaskImposter const var; return Statistics(img, msk, var, flags, sctrl); } /** * @brief A vector wrapper to provide a vector with the necessary methods and typedefs to * be processed by Statistics as though it were an Image. */ template class ImageImposter { public: // types we'll use in Statistics typedef typename std::vector::const_iterator x_iterator; typedef typename std::vector::const_iterator fast_iterator; typedef ValueT Pixel; // constructors for std::vector<>, and copy constructor // These are both shallow! ... no actual copying of values explicit ImageImposter(std::vector const &v) : _v(v) { } explicit ImageImposter(ImageImposter const &img) : _v(img._getVector()) {} // The methods we'll use in Statistics x_iterator row_begin(int) const { return _v.begin(); } x_iterator row_end(int) const { return _v.end(); } int getWidth() const { return _v.size(); } int getHeight() const { return 1; } bool empty() const { return _v.empty(); } private: std::vector const &_v; // a private reference to the data std::vector const &_getVector() const { return _v; } // get the ref for the copyCon }; /** * @brief The makeStatistics() overload to handle std::vector<> * @relates Statistics */ template Statistics makeStatistics(std::vector const &v, ///< Image (or MaskedImage) whose properties we want int const flags, ///< Describe what we want to calculate StatisticsControl const& sctrl = StatisticsControl() ///< Control calculation ) { ImageImposter img(v); // wrap the vector in a fake image MaskImposter msk; // instantiate a fake mask that will be compiled out. MaskImposter var; return Statistics(img, msk, var, flags, sctrl); } /** * @brief The makeStatistics() overload to handle std::vector<> * @relates Statistics */ template Statistics makeStatistics(std::vector const &v, ///< Image (or MaskedImage) whose properties we want std::vector const &vweights, ///< Weights int const flags, ///< Describe what we want to calculate StatisticsControl const& sctrl = StatisticsControl() ///< Control calculation ) { ImageImposter img(v); // wrap the vector in a fake image MaskImposter msk; // instantiate a fake mask that will be compiled out. MaskImposter var; ImageImposter weights(vweights); return Statistics(img, msk, var, weights, flags, sctrl); } /** * @brief The makeStatistics() overload to handle lsst::afw::math::MaskedVector<> * @relates Statistics */ template Statistics makeStatistics(lsst::afw::math::MaskedVector const &mv, ///< MaskedVector int const flags, ///< Describe what we want to calculate StatisticsControl const& sctrl = StatisticsControl() ///< Control calculation ) { if (sctrl.getWeighted() || sctrl.getCalcErrorFromInputVariance()) { return Statistics(*mv.getImage(), *mv.getMask(), *mv.getVariance(), flags, sctrl); } else { MaskImposter var; return Statistics(*mv.getImage(), *mv.getMask(), var, flags, sctrl); } } /** * @brief The makeStatistics() overload to handle lsst::afw::math::MaskedVector<> * @relates Statistics */ template Statistics makeStatistics(lsst::afw::math::MaskedVector const &mv, ///< MaskedVector std::vector const &vweights, ///< weights int const flags, ///< Describe what we want to calculate StatisticsControl const& sctrl = StatisticsControl() ///< Control calculation ) { ImageImposter weights(vweights); if (sctrl.getWeighted() || sctrl.getCalcErrorFromInputVariance()) { return Statistics(*mv.getImage(), *mv.getMask(), *mv.getVariance(), weights, flags, sctrl); } else { MaskImposter var; return Statistics(*mv.getImage(), *mv.getMask(), var, weights, flags, sctrl); } } }}} #endif

Return to list

Commits in /Users/nate/repos_hsc/afw/

ed634991

commit ed6349915ce0ffddfed2ec6aff165846d5340d49
Author: Robert Lupton the Good 
Date:   Thu Dec 29 10:15:49 2011 -0500

    The EDGE bitplane  may not be defined

6eed36a1

commit 6eed36a1b6376390c028ec0a15a8d35d040b951c
Author: Jim Bosch 
Date:   Thu May 1 12:58:41 2014 -0400

    Propagate rejected pixel mask planes when the amount of rejection crosses a threshold.

093be85f

commit 093be85fa83f156430f08709447f545771bae7ba
Author: bick 
Date:   Tue Sep 29 20:24:07 2009 +0000

    #749 comment updates.

73fb00fd

commit 73fb00fd8b3533247dad52e9a46e2470b77fe48f
Author: Paul Price 
Date:   Thu May 22 11:08:42 2014 -0400

    add NO_DATA mask plane, and use in warping/convolution
    
    The EDGE mask plane was originally intended to mean "pixel near the
    edge of the detector, so we haven't been able to properly convolve to
    search for sources", but it was hijacked to mean "pixels in a warped
    image that are off the edge of the original".  It has since had both
    meanings, which should be distinct.
    
    We introduce the NO_DATA mask plane to mean "pixels off the edge of
    the original", and reserve "EDGE" to mean "pixels near the edge".
    afw::math::edgePixel (used for pixels with no good inputs when
    warping) now returns a value for pixels *off* the edge (should it
    be renamed? but that's changing a public API).  Convolution now
    masks pixels near the edge as EDGE if copying edge pixels, and
    NO_DATA otherwise.

4a374367

commit 4a374367c9ea2928eaeadc16978d411646fea859
Author: bick 
Date:   Thu Sep 24 01:17:20 2009 +0000

    #749 Basic working functionality for Image, MaskedImage, and std::vector.  Needs much clean-up though.

a3819593

commit a3819593676f1da48225c1ff65e385882b40141b
Author: bick 
Date:   Mon Jan 11 20:15:41 2010 +0000

    Statistics returns nan instead of throwing exception (#1123).  Removed pdb from tests.

06220a25

commit 06220a25438ca7dc624c01f2b657210c8202b6b9
Author: bick 
Date:   Mon Aug 23 15:53:33 2010 +0000

    Improved doxygen comment for andMask meaning in StatisticsControl class.

Commits in /Users/nate/repos_lsst/afw/

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

ed634991

commit ed6349915ce0ffddfed2ec6aff165846d5340d49
Author: Robert Lupton the Good 
Date:   Thu Dec 29 10:15:49 2011 -0500

    The EDGE bitplane  may not be defined

6e8b043b

commit 6e8b043b597d4cf3616ba44da677a86e82961f5e
Author: John Swinbank 
Date:   Mon Apr 6 11:37:03 2015 -0400

    CheckFinite should check for Inf (as well as NaN).
    
    Addresses DM-2488.

89372b8c

commit 89372b8c30dc02f74200c6bff3c80d1a1d9020b4
Author: Robert Lupton the Good 
Date:   Thu Jul 17 22:48:09 2014 -0400

    Fixed doxygen comments
    
    Need /** to introduce comments that doxy will parse

b789cea1

commit b789cea1c72cef6b95e34b03e0118265c01c3380
Author: rhl 
Date:   Fri Sep 30 05:27:43 2011 +0000

    Moved more calculatins into sumImage

Return to list

examples/mask.cc

Diff:

                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                #include 
                #include 
                #include 
                
27 a9aec7fc + #include "lsst/utils/Utils.h"
28 a9aec7fc + #include "lsst/pex/exceptions.h"
27 f8edfe90 - #include "lsst/afw/image/Mask.h"
? -----
29 a9aec7fc + #include "lsst/afw/image.h"
28 f8edfe90 - #include "lsst/afw/image/LsstImageTypes.h"
namespace afwGeom = lsst::afw::geom; namespace afwImage = lsst::afw::image; /************************************************************************************************************/ int main() { afwImage::Mask img(afwGeom::Extent2I(10, 6)); // This is equivalent to mask = 100: for (afwImage::Mask::iterator ptr = img.begin(); ptr != img.end(); ++ptr) { (*ptr)[0] = 100; } // so is this, but fills backwards for (afwImage::Mask::reverse_iterator ptr = img.rbegin(); ptr != img.rend(); ++ptr) { (*ptr)[0] = 100; } // so is this, but tests a different way of choosing begin() for (afwImage::Mask::iterator ptr = img.at(0, 0); ptr != img.end(); ++ptr) { (*ptr)[0] = 100; } afwImage::Mask jmg = img; printf("%dx%d\n", img.getWidth(), img.getHeight()); *img.y_at(7, 2) = 999; *img.x_at(0, 0) = 0; img(img.getWidth() - 1, img.getHeight() - 1) = 100; printf("sub Masks\n"); // img will be modified afwImage::Mask simg1( img, afwGeom::Box2I(afwGeom::Point2I(1, 1), afwGeom::Extent2I(7, 3)), afwImage::LOCAL ); afwImage::Mask simg( simg1, afwGeom::Box2I(afwGeom::Point2I(0, 0), afwGeom::Extent2I(5, 2)), afwImage::LOCAL ); { afwImage::Mask nimg(simg.getDimensions()); nimg = 1; simg <<= nimg; } for (int r = 0; r != img.getHeight(); ++r) { std::fill(img.row_begin(r), img.row_end(r), 100*(1 + r)); }
82 8c6c0d93 -
83 8c6c0d93 - std::string afwdata(getenv("AFWDATA_DIR"));
84 8c6c0d93 - std::string smallMaskFile;
85 8c6c0d93 - if (afwdata.empty()) {
86 8c6c0d93 - std::cerr << "AFWDATA_DIR not set." << std::endl;
83 c3d8b5cf + std::string inImagePath;
84 a9aec7fc + try {
85 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
86 c3d8b5cf + inImagePath = dataDir + "/data/small.fits";
87 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
88 a9aec7fc + std::cerr << "Usage: mask [fitsFile]" << std::endl;
89 a9aec7fc + std::cerr << "fitsFile is the path to a masked image" << std::endl;
90 a9aec7fc + std::cerr << "\nError: setup afwdata or specify fitsFile.\n" << std::endl;
exit(EXIT_FAILURE);
88 8c6c0d93 - } else {
89 8c6c0d93 - smallMaskFile = afwdata + "/small_MI_msk.fits";
}
94 c3d8b5cf + afwImage::MaskedImage mi = afwImage::MaskedImage(inImagePath);
92 8c6c0d93 -
93 8c6c0d93 - afwImage::Mask msk(smallMaskFile);
94 f8edfe90 - printf("msk(0,0) = %d\n", msk(0,0));
95 a9aec7fc + printf("mask(0,0) = %d\n", (*(mi.getMask()))(0,0));
? + +++ +++++++ ++++
95 f8edfe90 -
96 8c6c0d93 - afwImage::DecoratedImage dimg(smallMaskFile);
97 f8edfe90 - //Image::Ptr img = dimg.getImage();
98 f8edfe90 - printf("dimg(0,0) = %d\n", (*(dimg.getImage()))(0,0));
? - ^ ^ --
96 a9aec7fc + printf("image(0,0) = %f\n", (*(mi.getImage()))(0,0));
? + + ^ ^ return 0; }

Return to list

Commits in /Users/nate/repos_hsc/afw/

f8edfe90

commit f8edfe90d99d004aca1819ef00099ce827e44343
Author: rhl 
Date:   Sat Nov 15 15:18:25 2008 +0000

    Merged from new-image-api branch at [6341]

8c6c0d93

commit 8c6c0d93eaf03478cc6379a16055c3ae6119aa35
Author: bick 
Date:   Fri Jan 8 21:49:43 2010 +0000

    #1113 Changed examples to default to afwdata fits files with no arguments.

Commits in /Users/nate/repos_lsst/afw/

7cbb2bb9

commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
Author: Russell Owen 
Date:   Tue Apr 28 17:08:34 2015 -0700

    Use lsst.utils.getPackageDir instead of eups.productDir

c3d8b5cf

commit c3d8b5cfa7d0dd7a5c1204dc69b6d400a8c4e25c
Author: Russell Owen 
Date:   Tue Jul 8 14:45:38 2014 -0700

    Minor updates
    
    Change maskedImageFitsIO to print the name of the written image file.
    Unify variable names.

a9aec7fc

commit a9aec7fccf43933d582b64486479b2a10a861329
Author: Russell Owen 
Date:   Tue Jul 8 11:41:49 2014 -0700

    Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
    
    afw was full of examples of std::string = getenv("AFWDATA_DIR")
    followed by testing for a non-empty string. This doesn't work as expected
    because getenv returns NULL if the environment variable does not exist.
    Fixed by calling eups::productDir("afwdata") and explicitly checking
    for the exception raised if the product is not setup.
    
    Also, most of that code used outdated paths to files in AFWDATA.
    In a few cases files were being read that no longer exist,
    so minor additional changes were needed.

Return to list

python/lsst/afw/gpu/gpuLib.i

Diff:

                // -*- lsst-c++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                %define gpuLib_DOCSTRING
                "
                Python interface to lsst::afw::gpu classes
                "
                %enddef
                
                %feature("autodoc", "1");
                %module(package="lsst.afw.gpu",docstring=gpuLib_DOCSTRING) gpuLib
                
34 83a7bbff + %{
35 83a7bbff + #include "lsst/afw/gpu/DevicePreference.h"
36 83a7bbff + #include "lsst/afw/gpu/GpuExceptions.h"
37 83a7bbff + #include "lsst/afw/gpu/IsGpuBuild.h"
38 6fc1c3d1 + #include "lsst/pex/exceptions.h"
39 83a7bbff + %}
40 83a7bbff +
41 6fc1c3d1 + %import "lsst/pex/exceptions/exceptionsLib.i"
%include "lsst/p_lsstSwig.i" %lsst_exceptions();
39 2d4ec240 - %import "lsst/pex/exceptions/exceptionsLib.i"
40 2d4ec240 -
41 83a7bbff - %{
42 83a7bbff - #include "lsst/afw/gpu/DevicePreference.h"
43 83a7bbff - #include "lsst/afw/gpu/GpuExceptions.h"
44 83a7bbff - #include "lsst/afw/gpu/IsGpuBuild.h"
45 83a7bbff - %}
46 83a7bbff -
%include "lsst/afw/gpu/DevicePreference.h" %include "lsst/afw/gpu/GpuExceptions.h" %include "lsst/afw/gpu/IsGpuBuild.h"
51 6fc1c3d1 + %declareException(GpuMemoryError, lsst.pex.exceptions.RuntimeError,
52 6fc1c3d1 + lsst::afw::gpu::GpuMemoryError)
53 6fc1c3d1 + %declareException(GpuRuntimeError, lsst.pex.exceptions.RuntimeError,
54 6fc1c3d1 + lsst::afw::gpu::GpuRuntimeError)
51 83a7bbff -
52 83a7bbff -
53 83a7bbff -
54 83a7bbff -
55 83a7bbff -

Return to list

Commits in /Users/nate/repos_hsc/afw/

2d4ec240

commit 2d4ec240c3e671e6de344f82faa1e57c9187b573
Author: Jim Bosch 
Date:   Fri Aug 24 16:48:48 2012 -0400

    fix problems in GPU swig module by %importing pex_exceptions

83a7bbff

commit 83a7bbff049c2d648a441e51803286bb3a4d39db
Author: Kresimir Cosic 
Date:   Thu Jul 19 03:59:00 2012 +0200

    Added afwGpu python interface (gpuLib.i)

Commits in /Users/nate/repos_lsst/afw/

6fc1c3d1

commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
Author: Jim Bosch 
Date:   Thu Jul 17 16:05:56 2014 -0400

    Adapt to changes in exception Python wrappers (DM-827)

83a7bbff

commit 83a7bbff049c2d648a441e51803286bb3a4d39db
Author: Kresimir Cosic 
Date:   Thu Jul 19 03:59:00 2012 +0200

    Added afwGpu python interface (gpuLib.i)

Return to list

examples/timeSpatiallyVaryingConvolve.py

Diff:

                #!/usr/bin/env python
                
                # 
                # LSST Data Management System
                # Copyright 2008, 2009, 2010 LSST Corporation.
                # 
                # This product includes software developed by the
                # LSST Project (http://www.lsst.org/).
                #
                # This program is free software: you can redistribute it and/or modify
                # it under the terms of the GNU General Public License as published by
                # the Free Software Foundation, either version 3 of the License, or
                # (at your option) any later version.
                # 
                # This program is distributed in the hope that it will be useful,
                # but WITHOUT ANY WARRANTY; without even the implied warranty of
                # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                # GNU General Public License for more details.
                # 
                # You should have received a copy of the LSST License Statement and 
                # the GNU General Public License along with this program.  If not, 
                # see .
                #
                
                import math
                import sys
                import os
                import time
                
30 7cbb2bb9 + import lsst.utils
30 ea1cf49a - import eups
31 ea1cf49a -
import lsst.pex.logging as pexLog import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom
36 ea1cf49a - import lsst.afw.math.detail as mathDetail
pexLog.Debug("lsst.afw", 0) MaxIter = 20 MaxTime = 1.0 # seconds
41 7cbb2bb9 + afwdataDir = lsst.utils.getPackageDir("afwdata")
43 ea1cf49a - dataDir = eups.productDir("afwdata")
44 ea1cf49a - if not dataDir:
45 ea1cf49a - raise RuntimeError("Must set up afwdata")
47 850f9fc3 - InputMaskedImagePath = os.path.join(dataDir, "data", "med.fits")
43 7cbb2bb9 + InputMaskedImagePath = os.path.join(afwdataDir, "data", "med.fits")
? +++ def getSpatialParameters(nKernelParams, func): """Get basic spatial parameters list You may wish to tweak it up for specific cases (especially the lower order terms) """ nCoeff = func.getNParameters() spParams = [[0.0]*nCoeff]*nKernelParams for kernelTermInd in range(nKernelParams): spParams[kernelTermInd][0] = 1.0 spParams[kernelTermInd][1:3] = [1.0e-3]*len(spParams[kernelTermInd][1:3]) spParams[kernelTermInd][3:6] = [1.0e-6]*len(spParams[kernelTermInd][3:6]) spParams[kernelTermInd][6:10] = [1.0e-9]*len(spParams[kernelTermInd][6:10]) return spParams def getAnalyticKernel(kSize, imSize, spOrder): """Return spatially varying analytic kernel: a Gaussian @param kSize: kernel size (scalar; height = width) @param x, y imSize: image size """ gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) polyFunc = afwMath.PolynomialFunction2D(spOrder) kernel = afwMath.AnalyticKernel(kSize, kSize, gaussFunc, polyFunc) minSigma = 0.1 maxSigma = 3.0 spParams = getSpatialParameters(3, polyFunc) spParams[0][0:3] = [minSigma, (maxSigma - minSigma) / float(imSize[0]), 0.0] spParams[1][0:3] = [minSigma, 0.0, (maxSigma - minSigma) / float(imSize[1])] kernel.setSpatialParameters(spParams); return kernel def getSeparableKernel(kSize, imSize, spOrder): """Return spatially varying separable kernel: a pair of 1-d Gaussians @param kSize: kernel size (scalar; height = width) @param x, y imSize: image size """ gaussFunc = afwMath.GaussianFunction1D(1) polyFunc = afwMath.PolynomialFunction2D(spOrder) kernel = afwMath.SeparableKernel(kSize, kSize, gaussFunc, gaussFunc, polyFunc) minSigma = 0.1 maxSigma = 3.0 spParams = getSpatialParameters(2, polyFunc) spParams[0][0:3] = [minSigma, (maxSigma - minSigma) / float(imSize[0]), 0.0] spParams[1][0:3] = [minSigma, 0.0, (maxSigma - minSigma) / float(imSize[0])] kernel.setSpatialParameters(spParams); return kernel def getDeltaLinearCombinationKernel(kSize, imSize, spOrder): """Return a LinearCombinationKernel of delta functions @param kSize: kernel size (scalar; height = width) @param x, y imSize: image size """ kernelList = afwMath.KernelList() for ctrX in range(kSize): for ctrY in range(kSize): kernelList.append(afwMath.DeltaFunctionKernel(kSize, kSize, afwGeom.Point2I(ctrX, ctrY))) polyFunc = afwMath.PolynomialFunction2D(spOrder) kernel = afwMath.LinearCombinationKernel(kernelList, polyFunc) spParams = getSpatialParameters(len(kernelList), polyFunc) kernel.setSpatialParameters(spParams); return kernel def getGaussianLinearCombinationKernel(kSize, imSize, spOrder): """Return a LinearCombinationKernel with 5 bases, each a Gaussian @param kSize: kernel size (scalar; height = width) @param x, y imSize: image size """ kernelList = afwMath.KernelList() for fwhmX, fwhmY, angle in ( (2.0, 2.0, 0.0), (0.5, 4.0, 0.0), (0.5, 4.0, math.pi / 4.0), (0.5, 4.0, math.pi / 2.0), (4.0, 4.0, 0.0), ): gaussFunc = afwMath.GaussianFunction2D(fwhmX, fwhmY, angle) kernelList.append(afwMath.AnalyticKernel(kSize, kSize, gaussFunc)) polyFunc = afwMath.PolynomialFunction2D(spOrder) kernel = afwMath.LinearCombinationKernel(kernelList, polyFunc) spParams = getSpatialParameters(len(kernelList), polyFunc) kernel.setSpatialParameters(spParams); return kernel def timeConvolution(outImage, inImage, kernel, convControl): """Time convolution @param outImage: output image or masked image (must be the same size as inImage) @param inImage: input image or masked image @param kernel: convolution kernel @param convControl: convolution control parameters (afwMath.ConvolutionControl) @return (elapsed time in seconds, number of iterations) """ startTime = time.time(); for nIter in range(1, MaxIter + 1): # mathDetail.convolveWithInterpolation(outImage, inImage, kernel, convControl) afwMath.convolve(outImage, inImage, kernel, convControl) endTime = time.time() if endTime - startTime > MaxTime: break return (endTime - startTime, nIter) def timeSet(outImage, inImage, kernelFunction, kernelDescr, convControl, spOrder, doInterp=True): """Time a set of convolutions for various parameters Inputs: ... the usual - spOrder: the order of the spatial Polynomial2 function - doInterp: if True then test interpolation, else only test brute force """ imSize = inImage.getDimensions() if doInterp: methodDescrInterpDistList = ( ("no interpolation", 0), ("linear interpolation over 10 x 10 pixels", 10), ("linear interpolation over 20 x 20 pixels", 20), ) else: methodDescrInterpDistList = ( ("no interpolation", 0), ) for methodDescr, maxInterpolationDistance in methodDescrInterpDistList: convControl.setMaxInterpolationDistance(maxInterpolationDistance) print "%s using %s" % (kernelDescr, methodDescr) print "ImWid\tImHt\tKerWid\tKerHt\tSec/Cnv" for kSize in (5, 11, 19): kernel = kernelFunction(kSize, imSize, spOrder) dur, nIter = timeConvolution(outImage, inImage, kernel, convControl) print "%d\t%d\t%d\t%d\t%0.2f" % (imSize[0], imSize[1], kSize, kSize, dur/float(nIter)) print def run(): convControl = afwMath.ConvolutionControl() convControl.setDoNormalize(True) spOrder = 3 print "All kernels use a spatial model of a Polynomial2 of order %s" % (spOrder,) for imageClass in ( afwImage.ImageF, afwImage.ImageD, afwImage.MaskedImageF, afwImage.MaskedImageD, ): print "\n*** Test convolution with %s ***\n" % (imageClass.__name__,) if len(sys.argv) < 2: inImage = imageClass(InputMaskedImagePath) # to get original behavior change True to False: if (False): bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(256, 256)) inImage = imageClass(inImage, bbox, afwImage.LOCAL, False) else: inImage = imageClass(sys.argv[1]) outImage = imageClass(inImage.getDimensions()) timeSet(outImage, inImage, getAnalyticKernel, "AnalyticKernel", convControl, spOrder=spOrder) timeSet(outImage, inImage, getSeparableKernel, "SeparableKernel", convControl, spOrder=spOrder, doInterp=False) timeSet(outImage, inImage, getGaussianLinearCombinationKernel, "LinearCombinationKernel with 5 Gaussian Basis Kernels", convControl, spOrder=spOrder) timeSet(outImage, inImage, getDeltaLinearCombinationKernel, "LinearCombinationKernel with Delta Function Basis", convControl, spOrder=spOrder) if __name__ == "__main__": run()

Return to list

Commits in /Users/nate/repos_hsc/afw/

850f9fc3

commit 850f9fc3814fbc5ef4b1675409a57b4c27661e80
Author: Russell Owen 
Date:   Fri Jun 15 11:34:06 2012 -0700

    Fix bug in example: the sample data moved

ea1cf49a

commit ea1cf49ac5574f3f5997ad3c99dac5481a395eeb
Author: rowen 
Date:   Mon May 10 21:28:15 2010 +0000

    Added python code to time spatially varying convolution (not quite finished).

Commits in /Users/nate/repos_lsst/afw/

7cbb2bb9

commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
Author: Russell Owen 
Date:   Tue Apr 28 17:08:34 2015 -0700

    Use lsst.utils.getPackageDir instead of eups.productDir

Return to list

python/lsst/afw/display/rgb.py

Diff:

                import numpy as np
                
3 f49676d7 - import lsst.afw.image as afwImage
4 f49676d7 - import lsst.afw.math as afwMath
5 f49676d7 - from lsst.afw.display.displayLib import replaceSaturatedPixels, getZScale
? -----------
3 7e2503b6 + from lsst.afw.display.displayLib import replaceSaturatedPixels
6 f49676d7 -
7 f49676d7 - def computeIntensity(imageR, imageG=None, imageB=None):
8 f49676d7 - """!Return a naive total intensity from the red, blue, and green intensities
9 f49676d7 - \param imageR intensity of image that'll be mapped to red; or intensity if imageG and imageB are None
10 f49676d7 - \param imageG intensity of image that'll be mapped to green; or None
11 f49676d7 - \param imageB intensity of image that'll be mapped to blue; or None
12 f49676d7 -
13 f49676d7 - Inputs may be MaskedImages, Images, or numpy arrays and the return is of the same type
14 f49676d7 - """
15 f49676d7 - if imageG is None or imageB is None:
16 f49676d7 - assert imageG is None and imageB is None, \
17 f49676d7 - "Please specify either a single image or red, green, and blue images"
18 f49676d7 - return imageR
19 f49676d7 -
20 f49676d7 - imageRGB = [imageR, imageG, imageB]
21 f49676d7 -
22 f49676d7 - for i, c in enumerate(imageRGB):
23 f49676d7 - if hasattr(c, "getImage"):
24 f49676d7 - c = imageRGB[i] = c.getImage()
25 f49676d7 - if hasattr(c, "getArray"):
26 f49676d7 - imageRGB[i] = c.getArray()
27 f49676d7 -
28 f49676d7 - intensity = (imageRGB[0] + imageRGB[1] + imageRGB[2])/float(3)
29 f49676d7 - #
30 f49676d7 - # Repack into whatever type was passed to us
31 f49676d7 - #
32 f49676d7 - Image = afwImage.ImageU if intensity.dtype == 'uint16' else afwImage.ImageF
33 f49676d7 -
34 f49676d7 - if hasattr(imageR, "getImage"): # a maskedImage
35 f49676d7 - intensity = afwImage.makeMaskedImage(Image(intensity))
36 f49676d7 - elif hasattr(imageR, "getArray"):
37 f49676d7 - intensity = Image(intensity)
38 f49676d7 -
39 f49676d7 - return intensity
class Mapping(object): """!Baseclass to map red, blue, green intensities into uint8 values"""
44 f49676d7 - def __init__(self, minimum=None, image=None):
8 7e2503b6 + def __init__(self, min):
"""!Create a mapping
46 f49676d7 - \param minimum Intensity that should be mapped to black (a scalar or array for R, G, B)
? ----
10 7e2503b6 + \param min Intensity that should be mapped to black (a scalar or array for R, G, B)
47 08a7740e - \param image The image to be used to calculate the mapping.
48 08a7740e -
49 08a7740e - If provided, also the default for makeRgbImage()
"""
12 7e2503b6 +
self._uint8Max = float(np.iinfo(np.uint8).max) try:
54 f49676d7 - len(minimum)
? ----
16 7e2503b6 + len(min)
except:
56 f49676d7 - minimum = 3*[minimum]
? ---- ----
18 7e2503b6 + min = 3*[min]
57 f49676d7 - assert len(minimum) == 3, "Please provide 1 or 3 values for minimum"
? ---- ----
19 7e2503b6 + assert len(min) == 3, "Please provide 1 or 3 values for min"
59 f49676d7 - self.minimum = minimum
? ---- ----
21 7e2503b6 + self._min = min
? +
60 f49676d7 - self._image = image
62 08a7740e - def makeRgbImage(self, imageR=None, imageG=None, imageB=None,
? ----- ----- ^^^^^^
23 7e2503b6 + def makeRgbImage(self, imageR, imageG, imageB):
? ^^
63 08a7740e - xSize=None, ySize=None, rescaleFactor=None):
"""!Convert 3 arrays, imageR, imageG, and imageB into a numpy RGB image
65 f49676d7 - \param imageR Image to map to red (if None, use the image passed to the ctor)
66 f49676d7 - \param imageG Image to map to green (if None, use imageR)
67 f49676d7 - \param imageB Image to map to blue (if None, use imageR)
68 08a7740e - \param xSize Desired width of RGB image (or None). If ySize is None, preserve aspect ratio
69 08a7740e - \param ySize Desired height of RGB image (or None)
70 08a7740e - \param rescaleFactor Make size of output image rescaleFactor*size of the input image (or None)
72 f49676d7 - N.b. images may be afwImage.Images or numpy arrays
? ------
26 7e2503b6 + N.b. images may be afwImages or numpy arrays
"""
74 f49676d7 - if imageR is None:
75 f49676d7 - if self._image is None:
76 f49676d7 - raise RuntimeError("You must provide an image (or pass one to the constructor)")
77 f49676d7 - imageR = self._image
78 f49676d7 -
79 f49676d7 - if imageG is None:
80 f49676d7 - imageG = imageR
81 f49676d7 - if imageB is None:
82 f49676d7 - imageB = imageR
83 f49676d7 -
imageRGB = [imageR, imageG, imageB] for i, c in enumerate(imageRGB): if hasattr(c, "getImage"): c = imageRGB[i] = c.getImage() if hasattr(c, "getArray"): imageRGB[i] = c.getArray()
91 08a7740e - if xSize is not None or ySize is not None:
92 08a7740e - assert rescaleFactor is None, "You may not specify a size and rescaleFactor"
93 08a7740e - h, w = imageRGB[0].shape
94 08a7740e - if ySize is None:
95 08a7740e - ySize = int(xSize*h/float(w) + 0.5)
96 08a7740e - elif xSize is None:
97 08a7740e - xSize = int(ySize*w/float(h) + 0.5)
98 08a7740e -
99 08a7740e - size = (ySize, xSize) # n.b. y, x order for scipy
100 08a7740e - elif rescaleFactor is not None:
101 08a7740e - size = float(rescaleFactor) # an int is intepreted as a percentage
102 08a7740e - else:
103 08a7740e - size = None
104 08a7740e -
105 08a7740e - if size is not None:
106 08a7740e - try:
107 08a7740e - import scipy.misc
108 f73544e1 - scipy.misc.imresize
109 f73544e1 - except (ImportError, AttributeError) as e:
110 f73544e1 - raise RuntimeError("Unable to rescale as scipy.misc.imresize is unavailable: %s" % e)
111 08a7740e -
112 08a7740e - for i, im in enumerate(imageRGB):
113 08a7740e - imageRGB[i] = scipy.misc.imresize(im, size, interp='bilinear', mode='F')
114 08a7740e -
115 f49676d7 - return np.dstack(self._convertImagesToUint8(*imageRGB)).astype(np.uint8)
35 7e2503b6 + return np.flipud(np.dstack(self._convertImagesToUint8(*imageRGB)).astype(np.uint8))
? ++++++++++ + def intensity(self, imageR, imageG, imageB):
118 f49676d7 - """!Return the total intensity from the red, blue, and green intensities
38 7e2503b6 + """!Return the total intensity from the red, blue, and green intensities"""
? +++
39 7e2503b6 + return (imageR + imageG + imageB)/float(3);
120 f49676d7 - This is a naive computation, and may be overridden by subclasses
121 f49676d7 - """
122 f49676d7 - return computeIntensity(imageR, imageG, imageB)
41 7e2503b6 + def mapIntensityToUint8(self, I):
42 7e2503b6 + """Map an intensity into the range of a uint8, [0, 255] (but not converted to uint8)"""
43 7e2503b6 + return np.where(I <= 0, 0, np.where(I < self._uint8Max, I, self._uint8Max))
def _convertImagesToUint8(self, imageR, imageG, imageB): """Use the mapping to convert images imageR, imageG, and imageB to a triplet of uint8 images"""
126 f49676d7 - imageR = imageR - self.minimum[0] # n.b. makes copy
? ----
47 7e2503b6 + imageR = imageR - self._min[0] # n.b. makes copy
? +
127 f49676d7 - imageG = imageG - self.minimum[1]
? ----
48 7e2503b6 + imageG = imageG - self._min[1]
? +
128 f49676d7 - imageB = imageB - self.minimum[2]
? ----
49 7e2503b6 + imageB = imageB - self._min[2]
? + fac = self.mapIntensityToUint8(self.intensity(imageR, imageG, imageB)) imageRGB = [imageR, imageG, imageB]
54 7e2503b6 +
for c in imageRGB: c *= fac
135 f49676d7 - c[c < 0] = 0 # individual bands can still be < 0, even if fac isn't
57 7e2503b6 + c[c <= 0] = 0
pixmax = self._uint8Max r0, g0, b0 = imageRGB # copies -- could work row by row to minimise memory usage
140 f49676d7 - with np.errstate(invalid='ignore', divide='ignore'): # n.b. np.where can't and doesn't short-circuit
? ----------
62 7e2503b6 + with np.errstate(invalid='ignore', divide='ignore'): # n.b. np.where doesn't (and can't) short-circuit
? ++++++++++++ for i, c in enumerate(imageRGB): c = np.where(r0 > g0, np.where(r0 > b0, np.where(r0 >= pixmax, c*pixmax/r0, c), np.where(b0 >= pixmax, c*pixmax/b0, c)), np.where(g0 > b0, np.where(g0 >= pixmax, c*pixmax/g0, c), np.where(b0 >= pixmax, c*pixmax/b0, c))).astype(np.uint8) c[c > pixmax] = pixmax imageRGB[i] = c
152 f49676d7 -
74 7e2503b6 +
return imageRGB
154 16cfe977 -
155 f49676d7 - class LinearMapping(Mapping):
156 f49676d7 - """!A linear map map of red, blue, green intensities into uint8 values"""
157 f49676d7 -
158 f49676d7 - def __init__(self, minimum=None, maximum=None, image=None):
159 f49676d7 - """!A linear stretch from [minimum, maximum]; if one or both are omitted use image minimum/maximum to set them
160 f49676d7 -
161 f49676d7 - \param minimum Intensity that should be mapped to black (a scalar or array for R, G, B)
162 f49676d7 - \param maximum Intensity that should be mapped to white (a scalar)
163 f49676d7 - """
164 f49676d7 -
165 f49676d7 - if minimum is None or maximum is None:
166 f49676d7 - assert image is not None, "You must provide an image if you don't set both minimum and maximum"
167 f49676d7 -
168 f49676d7 - stats = afwMath.makeStatistics(image, afwMath.MIN | afwMath.MAX)
169 f49676d7 - if minimum is None:
170 f49676d7 - minimum = stats.getValue(afwMath.MIN)
171 f49676d7 - if maximum is None:
172 f49676d7 - maximum = stats.getValue(afwMath.MAX)
173 f49676d7 -
174 f49676d7 - Mapping.__init__(self, minimum, image)
175 f49676d7 - self.maximum = maximum
176 f49676d7 -
177 f49676d7 - if maximum is None:
178 f49676d7 - self._range = None
179 f49676d7 - else:
180 f49676d7 - assert maximum - minimum != 0, "minimum and maximum values must not be equal"
181 f49676d7 - self._range = float(maximum - minimum)
182 f49676d7 -
183 f49676d7 - def mapIntensityToUint8(self, I):
184 f49676d7 - """Return an array which, when multiplied by an image, returns that image mapped to the range of a
185 f49676d7 - uint8, [0, 255] (but not converted to uint8)
186 f49676d7 -
187 f49676d7 - The intensity is assumed to have had minimum subtracted (as that can be done per-band)
188 f49676d7 - """
189 f49676d7 - with np.errstate(invalid='ignore', divide='ignore'): # n.b. np.where can't and doesn't short-circuit
190 f49676d7 - return np.where(I <= 0, 0,
191 f49676d7 - np.where(I >= self._range, self._uint8Max/I, self._uint8Max/self._range))
192 f49676d7 -
193 f49676d7 - class ZScaleMapping(LinearMapping):
194 f49676d7 - """!A mapping for a linear stretch chosen by the zscale algorithm
195 f49676d7 - (preserving colours independent of brightness)
196 f49676d7 -
197 f49676d7 - x = (I - minimum)/range
198 f49676d7 - """
199 f49676d7 -
200 f49676d7 - def __init__(self, image, nSamples=1000, contrast=0.25):
201 f49676d7 - """!A linear stretch from [z1, z2] chosen by the zscale algorithm
202 f49676d7 - \param nSamples The number of samples to use to estimate the zscale parameters
203 f49676d7 - \param contrast The number of samples to use to estimate the zscale parameters
204 f49676d7 - """
205 f49676d7 -
206 f49676d7 - if not hasattr(image, "getArray"):
207 f49676d7 - image = afwImage.ImageF(image)
208 f49676d7 - z1, z2 = getZScale(image, nSamples, contrast)
209 f49676d7 -
210 f49676d7 - LinearMapping.__init__(self, z1, z2, image)
class AsinhMapping(Mapping): """!A mapping for an asinh stretch (preserving colours independent of brightness)
215 f49676d7 - x = asinh(Q (I - minimum)/range)/Q
? ----
80 7e2503b6 + x = asinh(Q (I - min)/range)/Q
This reduces to a linear stretch if Q == 0 See http://adsabs.harvard.edu/abs/2004PASP..116..133L """
222 f49676d7 - def __init__(self, minimum, range, Q=8):
? ---- --
87 7e2503b6 + def __init__(self, min, range, Q):
223 f49676d7 - Mapping.__init__(self, minimum)
? ----
88 7e2503b6 + Mapping.__init__(self, min)
epsilon = 1.0/2**23 # 32bit floating point machine epsilon; sys.float_info.epsilon is 64bit if abs(Q) < epsilon: Q = 0.1 else: Qmax = 1e10 if Q > Qmax: Q = Qmax if False: self._slope = self._uint8Max/Q # gradient at origin is self._slope else: frac = 0.1 # gradient estimated using frac*range is _slope self._slope = frac*self._uint8Max/np.arcsinh(frac*Q) self._soften = Q/float(range); def mapIntensityToUint8(self, I):
107 7e2503b6 + return np.where(I <= 0, 0, np.arcsinh(I*self._soften)*self._slope/I)
242 f49676d7 - """Return an array which, when multiplied by an image, returns that image mapped to the range of a
243 f49676d7 - uint8, [0, 255] (but not converted to uint8)
245 f49676d7 - The intensity is assumed to have had minimum subtracted (as that can be done per-band)
246 f49676d7 - """
247 f49676d7 - with np.errstate(invalid='ignore', divide='ignore'): # n.b. np.where can't and doesn't short-circuit
248 f49676d7 - return np.where(I <= 0, 0, np.arcsinh(I*self._soften)*self._slope/I)
249 f49676d7 -
250 f49676d7 - class AsinhZScaleMapping(AsinhMapping):
251 f49676d7 - """!A mapping for an asinh stretch, estimating the linear stretch by zscale
252 f49676d7 -
253 f49676d7 - x = asinh(Q (I - z1)/(z2 - z1))/Q
254 f49676d7 -
255 f49676d7 - See AsinhMapping
256 f49676d7 - """
257 f49676d7 -
258 f49676d7 - def __init__(self, image, Q=12, pedestal=None):
259 f49676d7 - """!
260 f49676d7 - Create an asinh mapping from an image, setting the linear part of the stretch using zscale
261 16cfe977 -
262 f49676d7 - \param image The image to analyse, or a list of 3 images to be converted to an intensity image
263 f49676d7 - \param Q The asinh softening parameter
264 f49676d7 - \param pedestal The value, or array of 3 values, to subtract from the images; or None
265 f49676d7 -
266 f49676d7 - N.b. pedestal, if not None, is removed from the images when calculating the zscale
267 f49676d7 - stretch, and added back into Mapping.minimum[]
268 f49676d7 - """
269 f49676d7 - try:
270 f49676d7 - assert len(image) in (1, 3,), "Please provide 1 or 3 images"
271 f49676d7 - except TypeError:
272 f49676d7 - image = [image]
273 f49676d7 -
274 f49676d7 - if pedestal is not None:
275 f49676d7 - try:
276 f49676d7 - assert len(pedestal) in (1, 3,), "Please provide 1 or 3 pedestals"
277 f49676d7 - except TypeError:
278 f49676d7 - pedestal = 3*[pedestal]
279 f49676d7 -
280 f49676d7 - image = list(image) # needs to be mutable
281 f49676d7 - for i, im in enumerate(image):
282 f49676d7 - if pedestal[i] != 0.0:
283 f49676d7 - if hasattr(im, "getImage"):
284 f49676d7 - im = im.getImage()
285 f49676d7 - if hasattr(im, "getArray"):
286 f49676d7 - im = im.getArray()
287 f49676d7 -
288 f49676d7 - image[i] = im - pedestal[i] # n.b. a copy
289 f49676d7 - else:
290 f49676d7 - pedestal = len(image)*[0.0]
291 f49676d7 -
292 f49676d7 - image = computeIntensity(*image)
293 f49676d7 -
294 f49676d7 - zscale = ZScaleMapping(image)
295 f49676d7 - range = zscale.maximum - zscale.minimum[0] # zscale.minimum is always a triple
296 f49676d7 - minimum = zscale.minimum
297 f49676d7 -
298 f49676d7 - for i, level in enumerate(pedestal):
299 f49676d7 - minimum[i] += level
300 f49676d7 -
301 f49676d7 - AsinhMapping.__init__(self, minimum, range, Q)
302 f49676d7 - self._image = image # support self.makeRgbImage()
303 f49676d7 -
304 f49676d7 - def makeRGB(imageR, imageG=None, imageB=None, minimum=0, range=5, Q=20, fileName=None,
? ----- ----- ----
109 7e2503b6 + def makeRGB(imageR, imageG, imageB, min=0, range=5, Q=20, fileName=None,
305 08a7740e - saturatedBorderWidth=0, saturatedPixelValue=None,
? ^
110 7e2503b6 + saturatedBorderWidth=0, saturatedPixelValue=None):
? ^^
306 08a7740e - xSize=None, ySize=None, rescaleFactor=None):
"""Make a set of three images into an RGB image using an asinh stretch and optionally write it to disk If saturatedBorderWidth is non-zero, replace saturated pixels with saturatedPixelValue. Note that replacing saturated pixels requires that the input images be MaskedImages. """
312 f49676d7 - if imageG is None:
313 f49676d7 - imageG = imageR
314 f49676d7 - if imageB is None:
315 f49676d7 - imageB = imageR
316 f49676d7 -
if saturatedBorderWidth: if saturatedPixelValue is None: raise ValueError("saturatedPixelValue must be set if saturatedBorderWidth is set") replaceSaturatedPixels(imageR, imageG, imageB, saturatedBorderWidth, saturatedPixelValue)
322 f49676d7 - asinhMap = AsinhMapping(minimum, range, Q)
? ----
121 7e2503b6 + asinhMap = AsinhMapping(min, range, Q)
323 08a7740e - rgb = asinhMap.makeRgbImage(imageR, imageG, imageB,
? ^
122 7e2503b6 + rgb = asinhMap.makeRgbImage(imageR, imageG, imageB)
? ^
324 08a7740e - xSize=xSize, ySize=ySize, rescaleFactor=rescaleFactor)
325 08a7740e -
if fileName: writeRGB(fileName, rgb) return rgb
331 f49676d7 - def displayRGB(rgb, show=True):
? -----------
128 7e2503b6 + def displayRGB(rgb):
332 f49676d7 - """!Display an rgb image using matplotlib
? -
129 7e2503b6 + """Display an rgb image using matplotlib"""
? +++
333 f49676d7 - \param rgb The RGB image in question
334 f49676d7 - \param show If true, call plt.show()
335 f49676d7 - """
import matplotlib.pyplot as plt
337 f49676d7 - plt.imshow(rgb, interpolation='nearest', origin="lower")
? ----------------
131 7e2503b6 + plt.imshow(rgb, interpolation='nearest')
338 f49676d7 - if show:
339 f49676d7 - plt.show()
? ----
132 7e2503b6 + plt.show()
340 f49676d7 - return plt
def writeRGB(fileName, rgbImage):
135 7e2503b6 + """Write an RGB image (made by e.g. makeRGB) to fileName"""
343 f49676d7 - """!Write an RGB image to disk
344 f49676d7 - \param fileName The output file. The suffix defines the format, and must be supported by matplotlib
345 f49676d7 - \param rgbImage The image, as made by e.g. makeRGB
346 f49676d7 -
347 f49676d7 - Most versions of matplotlib support png and pdf (although the eps/pdf/svg writers may be buggy,
348 f49676d7 - possibly due an interaction with useTeX=True in the matplotlib settings).
349 f49676d7 -
350 f49676d7 - If your matplotlib bundles pil/pillow you should also be able to write jpeg and tiff files.
351 f49676d7 - """
import matplotlib.image matplotlib.image.imsave(fileName, rgbImage) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # # Support the legacy API # class asinhMappingF(object):
360 f49676d7 - """!\deprecated Object used to support legacy API"""
361 f49676d7 - def __init__(self, minimum, range, Q):
? ----
144 7e2503b6 + def __init__(self, min, range, Q):
362 f49676d7 - self.minimum = minimum
? ---- ----
145 7e2503b6 + self.min = min
self.range = range self.Q = Q class _RgbImageF(object):
367 f49676d7 - """!\deprecated Object used to support legacy API"""
def __init__(self, imageR, imageG, imageB, mapping):
369 f49676d7 - """!\deprecated Legacy API"""
370 f49676d7 - asinh = AsinhMapping(mapping.minimum, mapping.range, mapping.Q)
? ----
151 7e2503b6 + asinh = AsinhMapping(mapping.min, mapping.range, mapping.Q)
self.rgb = asinh.makeRgbImage(imageR, imageG, imageB) def write(self, fileName):
374 f49676d7 - """!\deprecated Legacy API"""
writeRGB(fileName, self.rgb) def RgbImageF(imageR, imageG, imageB, mapping):
378 f49676d7 - """!\deprecated Legacy API"""
return _RgbImageF(imageR, imageG, imageB, mapping)

Return to list

Commits in /Users/nate/repos_hsc/afw/

08a7740e

commit 08a7740ed756ee7b2c845b4ce6aed8d9a0f50d04
Author: Robert Lupton the Good 
Date:   Tue Apr 21 10:21:27 2015 -0400

    Added xSize, ySize, and rescaleFactor arguments to {make,write}RGB; HSC-1207
    
    N.b. requires scipy which is not a dependency of afw.

f73544e1

commit f73544e15abd2760bf84794798cf4b84e97e938d
Author: Robert Lupton the Good 
Date:   Sat Apr 25 08:21:39 2015 -0400

    Add a test that not only does scipy.misc exist, but it also supports imresize

16cfe977

commit 16cfe9776e35798afb73eab2a10ce798ab25dcca
Author: Robert Lupton the Good 
Date:   Mon Mar 16 18:01:42 2015 -0400

    Initial port/rewrite from afw_extensions_rgb
    
    With changes from code reviews squashed in

f49676d7

commit f49676d7f1348f9de8ca21ee633e0c25473251ae
Author: Robert Lupton the Good 
Date:   Sun Apr 19 10:50:17 2015 -0300

    Implemented Linear and ZScale transformations, HSC-1206
    
    Linear was already available with Q=0, but this way is clearer; the default is to use min/max limits.
    
    I also added AsinhZScaleMapping which uses the zscale code to set the stretch.
    
    I did not port the log mappings, as the C++ is not really something I'd like to see in the long-term stack (e.g. reinterpret_casts between ints and doubles).
    It would be easy to add a LogMapper in pure python, and if this is needed please open a new issue.
    
    The ZScale code comes from Mineo-san's fitsthumb, but doesn't give quite the same upper limit as ds9.  I'm not sure where the discrepancy is, but I don't think it matters.

Commits in /Users/nate/repos_lsst/afw/

7e2503b6

commit 7e2503b6b492a50a007c974e9a05a2cc64fd0138
Author: Robert Lupton the Good 
Date:   Mon Mar 16 18:01:42 2015 -0400

    Initial port/rewrite from afw_extensions_rgb
    
    With changes from code reviews squashed in

Return to list

tests/testSimpleTable.py

Diff:

1 7f5a3711 - #!/usr/bin/env python
1 b80fe1d3 + #!/usr/bin/env python2
? +
2 b80fe1d3 + from __future__ import absolute_import, division
# # LSST Data Management System
5 7f5a3711 - # Copyright 2008, 2009, 2010 LSST Corporation.
6 de8a1b40 + # Copyright 2008-2014 AURA/LSST
# # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for table.SimpleTable Run with: ./testSimpleTable.py or python >>> import testSimpleTable; testSimpleTable.run() """
35 7f5a3711 - import sys
36 7f5a3711 - import os
36 c605dfcd + import os.path
? +++++ import unittest import numpy
40 aa977b5e + try:
41 aa977b5e + import pyfits
42 aa977b5e + except ImportError:
43 aa977b5e + pyfits = None
44 aa977b5e + print "WARNING: pyfits not available; some tests will not be run"
45 aa977b5e +
import lsst.utils.tests import lsst.pex.exceptions
48 028f751f + import lsst.daf.base
import lsst.afw.table import lsst.afw.geom import lsst.afw.coord import lsst.afw.fits
53 7f5a3711 +
54 4bae7ca1 + numpy.random.seed(1)
try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def makeArray(size, dtype): return numpy.array(numpy.random.randn(size), dtype=dtype) def makeCov(size, dtype): m = numpy.array(numpy.random.randn(size, size), dtype=dtype) r = numpy.dot(m, m.transpose()) # not quite symmetric for single-precision on some platforms for i in range(r.shape[0]): for j in range(i): r[i,j] = r[j,i] return r class SimpleTableTestCase(lsst.utils.tests.TestCase): def checkScalarAccessors(self, record, key, name, value1, value2): fastSetter = getattr(record, "set" + key.getTypeString()) fastGetter = getattr(record, "get" + key.getTypeString()) record[key] = value1 self.assertEqual(record[key], value1) self.assertEqual(record.get(key), value1) self.assertEqual(record[name], value1) self.assertEqual(record.get(name), value1) self.assertEqual(fastGetter(key), value1) record.set(key, value2) self.assertEqual(record[key], value2) self.assertEqual(record.get(key), value2) self.assertEqual(record[name], value2) self.assertEqual(record.get(name), value2) self.assertEqual(fastGetter(key), value2) record[name] = value1 self.assertEqual(record[key], value1) self.assertEqual(record.get(key), value1) self.assertEqual(record[name], value1) self.assertEqual(record.get(name), value1) self.assertEqual(fastGetter(key), value1) record.set(name, value2) self.assertEqual(record[key], value2) self.assertEqual(record.get(key), value2) self.assertEqual(record[name], value2) self.assertEqual(record.get(name), value2) self.assertEqual(fastGetter(key), value2) fastSetter(key, value1) self.assertEqual(record[key], value1) self.assertEqual(record.get(key), value1) self.assertEqual(record[name], value1) self.assertEqual(record.get(name), value1) self.assertEqual(fastGetter(key), value1) self.assert_(key.subfields is None) def checkGeomAccessors(self, record, key, name, value): fastSetter = getattr(record, "set" + key.getTypeString()) fastGetter = getattr(record, "get" + key.getTypeString()) record.set(key, value) self.assertEqual(record.get(key), value) record.set(name, value) self.assertEqual(record.get(name), value) fastSetter(key, value) self.assertEqual(fastGetter(key), value) def checkArrayAccessors(self, record, key, name, value): fastSetter = getattr(record, "set" + key.getTypeString()) fastGetter = getattr(record, "get" + key.getTypeString()) record.set(key, value) self.assert_(numpy.all(record.get(key) == value)) record.set(name, value) self.assert_(numpy.all(record.get(name) == value)) fastSetter(key, value) self.assert_(numpy.all(fastGetter(key) == value)) def testRecordAccess(self): schema = lsst.afw.table.Schema() k0 = schema.addField("f0", type="U") k1 = schema.addField("f1", type="I") k2 = schema.addField("f2", type="L") k3 = schema.addField("f3", type="F") k4 = schema.addField("f4", type="D") k5 = schema.addField("f5", type="PointI") k7 = schema.addField("f7", type="PointD") k9 = schema.addField("f9", type="MomentsD") k10b = schema.addField("f10b", type="ArrayU", size=2) k10a = schema.addField("f10a", type="ArrayI", size=3) k10 = schema.addField("f10", type="ArrayF", size=4) k11 = schema.addField("f11", type="ArrayD", size=5) k12 = schema.addField("f12", type="CovF", size=3) k14 = schema.addField("f14", type="CovPointF") k16 = schema.addField("f16", type="CovMomentsF") k18 = schema.addField("f18", type="Angle") k19 = schema.addField("f19", type="Coord") k20 = schema.addField("f20", type="String", size=4) table = lsst.afw.table.BaseTable.make(schema) record = table.makeRecord() self.assertEqual(record[k1], 0) self.assertEqual(record[k2], 0) self.assert_(numpy.isnan(record[k3])) self.assert_(numpy.isnan(record[k4])) self.assertEqual(record.get(k5), lsst.afw.geom.Point2I()) self.assert_(numpy.isnan(record[k7.getX()])) self.assert_(numpy.isnan(record[k7.getY()])) self.checkScalarAccessors(record, k0, "f0", 5, 6) self.checkScalarAccessors(record, k1, "f1", 2, 3) self.checkScalarAccessors(record, k2, "f2", 2, 3) self.checkScalarAccessors(record, k3, "f3", 2.5, 3.5) self.checkScalarAccessors(record, k4, "f4", 2.5, 3.5) self.checkGeomAccessors(record, k5, "f5", lsst.afw.geom.Point2I(5, 3)) self.checkGeomAccessors(record, k7, "f7", lsst.afw.geom.Point2D(5.5, 3.5)) for k in (k5, k7): self.assertEqual(k.subfields, ("x", "y")) self.checkGeomAccessors(record, k9, "f9", lsst.afw.geom.ellipses.Quadrupole(5.5, 3.5, -1.0)) self.assertEqual(k9.subfields, ("xx", "yy", "xy")) self.checkArrayAccessors(record, k10b, "f10b", makeArray(k10b.getSize(), dtype=numpy.uint16)) self.checkArrayAccessors(record, k10a, "f10a", makeArray(k10a.getSize(), dtype=numpy.int32)) self.checkArrayAccessors(record, k10, "f10", makeArray(k10.getSize(), dtype=numpy.float32)) self.checkArrayAccessors(record, k11, "f11", makeArray(k11.getSize(), dtype=numpy.float64)) for k in (k10, k11): self.assertEqual(k.subfields, tuple(range(k.getSize()))) self.checkArrayAccessors(record, k12, "f12", makeCov(k12.getSize(), dtype=numpy.float32)) self.checkArrayAccessors(record, k14, "f14", makeCov(k14.getSize(), dtype=numpy.float32)) self.checkArrayAccessors(record, k16, "f16", makeCov(k16.getSize(), dtype=numpy.float32)) sub1 = k11.slice(1, 3) sub2 = k11[0:2] self.assert_((record.get(sub1) == record.get(k11)[1:3]).all()) self.assert_((record.get(sub2) == record.get(k11)[0:2]).all()) self.assertEqual(sub1[0], sub2[1]) for k in (k12, k14, k16): n = 0 for idx, subkey in zip(k.subfields, k.subkeys): self.assertEqual(k[idx], subkey) n += 1 self.assertEqual(n, k.getElementCount()) self.checkGeomAccessors(record, k18, "f18", lsst.afw.geom.Angle(1.2)) self.assert_(k18.subfields is None) self.checkGeomAccessors( record, k19, "f19", lsst.afw.coord.IcrsCoord(lsst.afw.geom.Angle(1.3), lsst.afw.geom.Angle(0.5)) ) self.assertEqual(k19.subfields, ("ra", "dec")) self.checkScalarAccessors(record, k20, "f20", "foo", "bar") k0a = lsst.afw.table.Key["D"]() k0b = lsst.afw.table.Key["Flag"]()
190 341e49d9 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LogicErrorException, record.get, k0a)
? ^^^^^^^^^^^^^^^ ------- ------ ---------
199 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LogicError, record.get, k0a)
? ++ ^
191 341e49d9 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LogicErrorException, record.get, k0b)
? ^^^^^^^^^^^^^^^ ------- ------ ---------
200 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LogicError, record.get, k0b)
? ++ ^ def _testBaseFits(self, target): schema = lsst.afw.table.Schema() k = schema.addField("f", type="D") cat1 = lsst.afw.table.BaseCatalog(schema) for i in range(50): record = cat1.addNew() record.set(k, numpy.random.randn()) cat1.writeFits(target) cat2 = lsst.afw.table.BaseCatalog.readFits(target) self.assertEqual(len(cat1), len(cat2)) for r1, r2 in zip(cat1, cat2): self.assertEqual(r1.get(k), r2.get(k)) def testBaseFits(self):
207 ee5b9d95 - self._testBaseFits("testBaseTable.fits")
208 6c49463c - os.remove("testBaseTable.fits")
216 c605dfcd + with lsst.utils.tests.getTempFilePath(".fits") as tmpFile:
217 c605dfcd + self._testBaseFits(tmpFile)
self.assertRaises(Exception, lsst.afw.table.BaseCatalog.readFits, "nonexistentfile.fits") def testMemoryFits(self): mem = lsst.afw.fits.MemFileManager() self._testBaseFits(mem) def testColumnView(self): schema = lsst.afw.table.Schema() k0 = schema.addField("f0", type="U") k1 = schema.addField("f1", type="I") kb1 = schema.addField("fb1", type="Flag") k2 = schema.addField("f2", type="F") kb2 = schema.addField("fb2", type="Flag") k3 = schema.addField("f3", type="D") kb3 = schema.addField("fb3", type="Flag") k4 = schema.addField("f4", type="ArrayF", size=2) k5 = schema.addField("f5", type="ArrayD", size=3) k6 = schema.addField("f6", type="Angle") k7 = schema.addField("f7", type="ArrayU", size=4) catalog = lsst.afw.table.BaseCatalog(schema) catalog.addNew() catalog[0].set(k0, 1) catalog[0].set(k1, 2) catalog[0].set(k2, 0.5) catalog[0].set(k3, 0.25) catalog[0].set(kb1, False) catalog[0].set(kb2, True) catalog[0].set(kb3, False) catalog[0].set(k4, numpy.array([-0.5, -0.25], dtype=numpy.float32)) catalog[0].set(k5, numpy.array([-1.5, -1.25, 3.375], dtype=numpy.float64)) catalog[0].set(k6, lsst.afw.geom.Angle(0.25)) catalog[0].set(k7, numpy.array([2,3,4,1], dtype=numpy.uint16)) col1a = catalog[k1] self.assertEqual(col1a.shape, (1,)) catalog.addNew() catalog[1].set(k0, 4) catalog[1].set(k1, 3) catalog[1].set(k2, 2.5) catalog[1].set(k3, 0.75) catalog[1].set(kb1, True) catalog[1].set(kb2, False) catalog[1].set(kb3, True) catalog[1].set(k4, numpy.array([-3.25, -0.75], dtype=numpy.float32)) catalog[1].set(k5, numpy.array([-1.25, -2.75, 0.625], dtype=numpy.float64)) catalog[1].set(k6, lsst.afw.geom.Angle(0.15)) catalog[1].set(k7, numpy.array([5,6,8,7], dtype=numpy.uint16)) col1b = catalog[k1] self.assertEqual(col1b.shape, (2,)) columns = catalog.getColumnView() for key in [k0, k1, k2, k3, kb1, kb2, kb3]: array = columns[key] for i in [0, 1]: self.assertEqual(array[i], catalog[i].get(key)) for key in [k4, k5, k7]: array = columns[key] for i in [0, 1]: self.assert_(numpy.all(array[i] == catalog[i].get(key))) for key in [k6]: array = columns[key] for i in [0, 1]: self.assertEqual(lsst.afw.geom.Angle(array[i]), catalog[i].get(key)) for key in [k1, k2, k3]: vals = columns[key].copy() vals *= 2 array = columns[key] array *= 2 for i in [0, 1]: self.assertEqual(catalog[i].get(key), vals[i]) self.assertEqual(array[i], vals[i]) def testUnsignedFitsPersistence(self): """Test FITS round-trip of unsigned short ints, since FITS handles unsigned columns differently from signed columns """ schema = lsst.afw.table.Schema() k1 = schema.addField("f1", type=numpy.uint16, doc="scalar uint16") k2 = schema.addField("f2", type="ArrayU", doc="array uint16", size=4) cat1 = lsst.afw.table.BaseCatalog(schema) record1 = cat1.addNew() record1.set(k1, 4) record1.set(k2, numpy.array([5, 6, 7, 8], dtype=numpy.uint16)) filename = "testSimpleTable-testUnsignedFitsPersistence.fits" cat1.writeFits(filename) cat2 = lsst.afw.table.BaseCatalog.readFits(filename) record2 = cat2[0] self.assertEqual(cat1.schema, cat2.schema) self.assertEqual(record1.get(k1), record2.get(k1)) self.assertTrue(numpy.all(record1.get(k2) == record2.get(k2))) os.remove(filename) def testIteration(self): schema = lsst.afw.table.Schema() k = schema.addField("a", type=int) catalog = lsst.afw.table.BaseCatalog(schema) for n in range(5): record = catalog.addNew() record[k] = n for n, r in enumerate(catalog): self.assertEqual(n, r[k]) def testTicket2262(self): """Test that we can construct an array field in Python""" f1 = lsst.afw.table.Field["ArrayF"]("name", "doc", "units", 5) f2 = lsst.afw.table.Field["ArrayD"]("name", "doc", 5) self.assertEqual(f1.getSize(), 5) self.assertEqual(f2.getSize(), 5)
315 6c49463c -
324 df7781eb +
def testExtract(self): schema = lsst.afw.table.Schema()
318 14647d65 - schema.addField("a.b.c1", type=numpy.float64)
? ^ ^
327 df7781eb + schema.addField("a_b_c1", type=numpy.float64)
? ^ ^
319 14647d65 - schema.addField("a.b.c2", type="Flag")
? ^ ^
328 df7781eb + schema.addField("a_b_c2", type="Flag")
? ^ ^
320 14647d65 - schema.addField("a.d1", type=numpy.int32)
? ^
329 df7781eb + schema.addField("a_d1", type=numpy.int32)
? ^
321 14647d65 - schema.addField("a.d2", type="ArrayF", size=2)
322 14647d65 - schema.addField("q.e1", type="PointI")
323 14647d65 - covKey = schema.addField("q.e2", type="CovF", size=3)
330 df7781eb + schema.addField("a_d2", type=numpy.float32)
331 df7781eb + pointKey = lsst.afw.table.Point2IKey.addFields(schema, "q_e1", "doc for point field", "pixels")
332 df7781eb + schema.addField("q_e2_xxSigma", type=numpy.float32)
333 df7781eb + schema.addField("q_e2_yySigma", type=numpy.float32)
334 df7781eb + schema.addField("q_e2_xySigma", type=numpy.float32)
335 df7781eb + schema.addField("q_e2_xx_yy_Cov", type=numpy.float32)
336 df7781eb + schema.addField("q_e2_xx_xy_Cov", type=numpy.float32)
337 df7781eb + schema.addField("q_e2_yy_xy_Cov", type=numpy.float32)
338 df7781eb + covKey = lsst.afw.table.CovarianceMatrix3fKey(schema["q_e2"], ["xx", "yy", "xy"])
324 14647d65 - self.assertEqual(schema.extract("a.b.*", ordered=True).keys(), ["a.b.c1", "a.b.c2"])
? ^ ^ ^ ^ ^ ^
339 df7781eb + self.assertEqual(schema.extract("a_b_*", ordered=True).keys(), ["a_b_c1", "a_b_c2"])
? ^ ^ ^ ^ ^ ^
325 14647d65 - self.assertEqual(schema.extract("*1", ordered=True).keys(), ["a.b.c1", "a.d1", "q.e1"])
? ^ ^ ^ --------
340 df7781eb + self.assertEqual(schema.extract("*1", ordered=True).keys(), ["a_b_c1", "a_d1"])
? ^ ^ ^
326 14647d65 - self.assertEqual(schema.extract("a.b.*", "*2", ordered=True).keys(),
? ^ ^
341 df7781eb + self.assertEqual(schema.extract("a_b_*", "*2", ordered=True).keys(),
? ^ ^
327 14647d65 - ["a.b.c1", "a.b.c2", "a.d2", "q.e2"])
? ^ ^ ^ ^ ^ --------
342 df7781eb + ["a_b_c1", "a_b_c2", "a_d2"])
? ^ ^ ^ ^ ^
328 14647d65 - self.assertEqual(schema.extract(regex=r"a\.(.+)1", sub=r"\1f", ordered=True).keys(), ["b.cf", "df"])
? ^^ ^
343 df7781eb + self.assertEqual(schema.extract(regex=r"a_(.+)1", sub=r"\1f", ordered=True).keys(), ["b_cf", "df"])
? ^ ^ catalog = lsst.afw.table.BaseCatalog(schema) for i in range(5): record = catalog.addNew()
332 14647d65 - record.set("a.b.c1", numpy.random.randn())
? ^ ^
347 df7781eb + record.set("a_b_c1", numpy.random.randn())
? ^ ^
333 14647d65 - record.set("a.b.c2", True)
? ^ ^
348 df7781eb + record.set("a_b_c2", True)
? ^ ^
334 14647d65 - record.set("a.d1", numpy.random.randint(100))
? ^
349 df7781eb + record.set("a_d1", numpy.random.randint(100))
? ^
335 14647d65 - record.set("a.d2", numpy.random.randn(2).astype(numpy.float32))
? ^ -----------------------
350 df7781eb + record.set("a_d2", numpy.random.randn())
? ^
336 14647d65 - record.set("q.e1", lsst.afw.geom.Point2I(numpy.random.randint(10), numpy.random.randint(10)))
? ^^^ ^^
351 df7781eb + record.set(pointKey, lsst.afw.geom.Point2I(numpy.random.randint(10), numpy.random.randint(10)))
? ^^^^^^ ^
337 14647d65 - record.set("q.e2", numpy.random.randn(3,3).astype(numpy.float32))
? ^^^ ^^
352 df7781eb + record.set(covKey, numpy.random.randn(3,3).astype(numpy.float32))
? ^^^^ ^ d = record.extract("*") self.assertEqual(set(d.keys()), set(schema.getNames()))
340 14647d65 - self.assertEqual(d["a.b.c1"], record.get("a.b.c1"))
? ^ ^ ^ ^
355 df7781eb + self.assertEqual(d["a_b_c1"], record.get("a_b_c1"))
? ^ ^ ^ ^
341 14647d65 - self.assertEqual(d["a.b.c2"], record.get("a.b.c2"))
? ^ ^ ^ ^
356 df7781eb + self.assertEqual(d["a_b_c2"], record.get("a_b_c2"))
? ^ ^ ^ ^
342 14647d65 - self.assertEqual(d["a.d1"], record.get("a.d1"))
? ^ ^
357 df7781eb + self.assertEqual(d["a_d1"], record.get("a_d1"))
? ^ ^
343 14647d65 - self.assert_(numpy.all(d["a.d2"] == record.get("a.d2")))
344 14647d65 - self.assertEqual(d["q.e1"], record.get("q.e1"))
? ^^^^ ^^^^
358 df7781eb + self.assertEqual(d["a_d2"], record.get("a_d2"))
? ^^^^ ^^^^
345 14647d65 - self.assert_(numpy.all(d["q.e2"] == record.get("q.e2")))
346 14647d65 - d = record.extract("q.e1", split=True)
347 14647d65 - self.assertEqual(d["q.e1.x"], record.get("q.e1.x"))
? ^ ^ ^^ ^^^^
359 df7781eb + self.assertEqual(d["q_e1_x"], record.get(pointKey.getX()))
? ^ ^ ^^^^^^^^ + ^^^^
348 14647d65 - self.assertEqual(d["q.e1.y"], record.get("q.e1.y"))
? ^ ^ ^^ ^^^^
360 df7781eb + self.assertEqual(d["q_e1_y"], record.get(pointKey.getY()))
? ^ ^ ^^^^^^^^ + ^^^^
349 14647d65 - self.assert_("q.e1" not in d)
allIdx = slice(None) sliceIdx = slice(0, 4, 2) boolIdx = numpy.array([True, False, False, True, True]) for kwds, idx in [ ({}, allIdx), ({"copy": True}, allIdx), ({"where": boolIdx}, boolIdx), ({"where": sliceIdx}, sliceIdx), ({"where": boolIdx, "copy": True}, boolIdx), ({"where": sliceIdx, "copy": True}, sliceIdx), ]:
361 14647d65 -
d = catalog.extract("*", **kwds)
363 14647d65 - self.assert_(numpy.all(d["a.b.c1"] == catalog.get("a.b.c1")[idx]))
? ^ ^ ^ ^
373 df7781eb + self.assert_(numpy.all(d["a_b_c1"] == catalog.get("a_b_c1")[idx]))
? ^ ^ ^ ^
364 14647d65 - self.assert_(numpy.all(d["a.b.c2"] == catalog.get("a.b.c2")[idx]))
? ^ ^ ^ ^
374 df7781eb + self.assert_(numpy.all(d["a_b_c2"] == catalog.get("a_b_c2")[idx]))
? ^ ^ ^ ^
365 14647d65 - self.assert_(numpy.all(d["a.d1"] == catalog.get("a.d1")[idx]))
? ^ ^
375 df7781eb + self.assert_(numpy.all(d["a_d1"] == catalog.get("a_d1")[idx]))
? ^ ^
366 14647d65 - self.assert_(numpy.all(d["a.d2"] == catalog.get("a.d2")[idx]))
? ^ ^
376 df7781eb + self.assert_(numpy.all(d["a_d2"] == catalog.get("a_d2")[idx]))
? ^ ^
367 14647d65 - self.assert_(numpy.all(d["q.e1.x"] == catalog.get("q.e1.x")[idx]))
? ^ ^ ^ ^
377 df7781eb + self.assert_(numpy.all(d["q_e1_x"] == catalog.get("q_e1_x")[idx]))
? ^ ^ ^ ^
368 14647d65 - self.assert_(numpy.all(d["q.e1.y"] == catalog.get("q.e1.y")[idx]))
? ^ ^ ^ ^
378 df7781eb + self.assert_(numpy.all(d["q_e1_y"] == catalog.get("q_e1_y")[idx]))
? ^ ^ ^ ^
369 14647d65 - cov = d["q.e2"]
370 14647d65 - for i in range(covKey.getSize()):
371 14647d65 - for j in range(covKey.getSize()):
372 14647d65 - self.assert_(numpy.all(cov[:,i,j] == catalog.get(covKey[i,j])[idx]))
if "copy" in kwds or idx is boolIdx: for col in d.values(): self.assert_(col.flags.c_contiguous)
382 25e84506 + # Test that aliases are included in extract()
383 25e84506 + schema.getAliasMap().set("b_f", "a_b")
384 25e84506 + d = schema.extract("b_f*")
385 25e84506 + self.assertEqual(sorted(d.keys()), ["b_f_c1", "b_f_c2"])
def testExtend(self): schema1 = lsst.afw.table.SourceTable.makeMinimalSchema() k1 = schema1.addField("f1", type=int) k2 = schema1.addField("f2", type=float) cat1 = lsst.afw.table.BaseCatalog(schema1) for i in range(1000): record = cat1.addNew() record.setI(k1, i) record.setD(k2, numpy.random.randn()) self.assertFalse(cat1.isContiguous()) cat2 = lsst.afw.table.BaseCatalog(schema1) cat2.extend(cat1, deep=True) self.assertEqual(len(cat1), len(cat2)) self.assert_(cat2.isContiguous()) cat3 = lsst.afw.table.BaseCatalog(cat1.table) cat3.extend(cat1, deep=False) self.assertFalse(cat3.isContiguous()) cat4 = lsst.afw.table.BaseCatalog(cat1.table) cat4.extend(list(cat1), deep=False) self.assertFalse(cat4.isContiguous()) cat4 = lsst.afw.table.BaseCatalog(schema1) cat4.extend(list(cat1), deep=True) self.assertFalse(cat4.isContiguous()) mapper = lsst.afw.table.SchemaMapper(schema1) mapper.addMinimalSchema(lsst.afw.table.SourceTable.makeMinimalSchema()) k2a = mapper.addMapping(k2) schema2 = mapper.getOutputSchema() self.assert_(mapper.getOutputSchema().contains(lsst.afw.table.SourceTable.makeMinimalSchema())) cat5 = lsst.afw.table.BaseCatalog(schema2) cat5.extend(cat1, mapper=mapper) self.assert_(cat5.isContiguous()) cat6 = lsst.afw.table.SourceCatalog(schema2) cat6.extend(list(cat1), mapper=mapper) self.assertFalse(cat6.isContiguous()) cat7 = lsst.afw.table.SourceCatalog(schema2)
412 c2e69e2c - cat7.reserve(len(cat1) * 2)
? ^
422 a9485a48 + cat7.reserve(len(cat1) * 3)
? ^ cat7.extend(list(cat1), mapper=mapper)
414 c2e69e2c - cat7.extend(cat1, mapper=mapper)
? -------
424 a9485a48 + cat7.extend(cat1, mapper)
425 a9485a48 + cat7.extend(list(cat1), mapper)
self.assert_(cat7.isContiguous())
427 a9485a48 + cat8 = lsst.afw.table.BaseCatalog(schema2)
428 a9485a48 + cat8.extend(list(cat7), True)
429 a9485a48 + cat8.extend(list(cat7), deep=True)
def testTicket2308(self): inputSchema = lsst.afw.table.SourceTable.makeMinimalSchema() mapper1 = lsst.afw.table.SchemaMapper(inputSchema) mapper1.addMinimalSchema(lsst.afw.table.SourceTable.makeMinimalSchema(), True) mapper2 = lsst.afw.table.SchemaMapper(inputSchema) mapper2.addMinimalSchema(lsst.afw.table.SourceTable.makeMinimalSchema(), False) inputTable = lsst.afw.table.SourceTable.make(inputSchema) inputRecord = inputTable.makeRecord() inputRecord.set("id", 42) outputTable1 = lsst.afw.table.SourceTable.make(mapper1.getOutputSchema()) outputTable2 = lsst.afw.table.SourceTable.make(mapper2.getOutputSchema()) outputRecord1 = outputTable1.makeRecord() outputRecord2 = outputTable2.makeRecord() self.assertEqual(outputRecord1.getId(), outputRecord2.getId()) self.assertNotEqual(outputRecord1.getId(), inputRecord.getId()) outputRecord1.assign(inputRecord, mapper1) self.assertEqual(outputRecord1.getId(), inputRecord.getId()) outputRecord2.assign(inputRecord, mapper2) self.assertNotEqual(outputRecord2.getId(), inputRecord.getId()) def testTicket2393(self): schema = lsst.afw.table.Schema() k = schema.addField(lsst.afw.table.Field[int]("i", "doc for i")) item = schema.find("i") self.assertEqual(k, item.key)
443 fd4c0bae - def testSchemaMapperRename(self):
444 fd4c0bae - schema = lsst.afw.table.Schema()
445 fd4c0bae - ka = schema.addField("a", type=numpy.int32, doc="doc for a", units="unita")
446 fd4c0bae - kb = schema.addField("b", type="ArrayF", doc="doc for b", units="unitb", size=4)
447 fd4c0bae - mapper1 = lsst.afw.table.SchemaMapper(schema)
448 fd4c0bae - ka1 = mapper1.addMapping(ka, "a1")
449 fd4c0bae - kb1 = mapper1.addMapping(kb, "b1")
450 fd4c0bae - schema1 = mapper1.getOutputSchema()
451 fd4c0bae - self.assertEqual(schema1.find(ka1).field.getName(), "a1")
452 fd4c0bae - self.assertEqual(schema1.find(ka1).field.getDoc(), schema.find(ka).field.getDoc())
453 fd4c0bae - self.assertEqual(schema1.find(ka1).field.getUnits(), schema.find(ka).field.getUnits())
454 fd4c0bae - self.assertEqual(schema1.find(kb1).field.getName(), "b1")
455 fd4c0bae - self.assertEqual(schema1.find(kb1).field.getDoc(), schema.find(kb).field.getDoc())
456 fd4c0bae - self.assertEqual(schema1.find(kb1).field.getUnits(), schema.find(kb).field.getUnits())
457 fd4c0bae - self.assertEqual(schema1.find(kb1).field.getSize(), schema.find(kb).field.getSize())
458 fd4c0bae - mapper2 = lsst.afw.table.SchemaMapper(schema)
459 fd4c0bae - fa2 = lsst.afw.table.Field[numpy.int32]("a2", "doc for a2", "unitsa2")
460 fd4c0bae - fb2 = lsst.afw.table.Field["ArrayF"]("b2", "doc for b2", "unitsb2", 4)
461 fd4c0bae - ka2 = mapper2.addMapping(ka, fa2)
462 fd4c0bae - kb2 = mapper2.addMapping(kb, fb2)
463 fd4c0bae - schema2 = mapper2.getOutputSchema()
464 fd4c0bae - self.assertEqual(schema2.find(ka2).field.getName(), "a2")
465 fd4c0bae - self.assertEqual(schema2.find(ka2).field.getDoc(), fa2.getDoc())
466 fd4c0bae - self.assertEqual(schema2.find(ka2).field.getUnits(), fa2.getUnits())
467 fd4c0bae - self.assertEqual(schema2.find(kb2).field.getName(), "b2")
468 fd4c0bae - self.assertEqual(schema2.find(kb2).field.getDoc(), fb2.getDoc())
469 fd4c0bae - self.assertEqual(schema2.find(kb2).field.getUnits(), fb2.getUnits())
470 fd4c0bae - self.assertEqual(schema2.find(kb2).field.getSize(), fb2.getSize())
471 fd4c0bae - ka3 = mapper2.addMapping(ka, "a3")
472 fd4c0bae - kb3 = mapper2.addMapping(kb, "b3")
473 fd4c0bae - self.assertEqual(ka2, ka3)
474 fd4c0bae - self.assertEqual(kb2, kb3)
475 fd4c0bae - schema2 = mapper2.getOutputSchema()
476 fd4c0bae - self.assertEqual(schema2.find(ka2).field.getName(), "a3")
477 fd4c0bae - self.assertEqual(schema2.find(ka2).field.getDoc(), fa2.getDoc())
478 fd4c0bae - self.assertEqual(schema2.find(ka2).field.getUnits(), fa2.getUnits())
479 fd4c0bae - self.assertEqual(schema2.find(kb2).field.getName(), "b3")
480 fd4c0bae - self.assertEqual(schema2.find(kb2).field.getDoc(), fb2.getDoc())
481 fd4c0bae - self.assertEqual(schema2.find(kb2).field.getUnits(), fb2.getUnits())
482 fd4c0bae - self.assertEqual(schema2.find(kb2).field.getSize(), fb2.getSize())
483 fd4c0bae -
def testTicket2850(self): schema = lsst.afw.table.Schema() table = lsst.afw.table.BaseTable.make(schema) self.assertEqual(table.getBufferSize(), 0) def testTicket2894(self): """Test boolean-array indexing of catalogs""" schema = lsst.afw.table.Schema() key = schema.addField(lsst.afw.table.Field[int]("i", "doc for i")) cat1 = lsst.afw.table.BaseCatalog(schema) cat1.addNew().set(key, 1) cat1.addNew().set(key, 2) cat1.addNew().set(key, 3) cat2 = cat1[numpy.array([True, False, False], dtype=bool)] self.assertTrue((cat2[key] == numpy.array([1], dtype=int)).all()) self.assertEqual(cat2[0], cat1[0]) # records compare using pointer equality cat3 = cat1[numpy.array([True, True, False], dtype=bool)] self.assertTrue((cat3[key] == numpy.array([1,2], dtype=int)).all()) cat4 = cat1[numpy.array([True, False, True], dtype=bool)] self.assertTrue((cat4.copy(deep=True)[key] == numpy.array([1,3], dtype=int)).all()) def testTicket2938(self): """Test heterogenous catalogs that have records from multiple tables""" schema = lsst.afw.table.Schema() schema.addField("i", type=int, doc="doc for i") cat = lsst.afw.table.BaseCatalog(schema) cat.addNew() t1 = lsst.afw.table.BaseTable.make(schema) cat.append(t1.makeRecord()) self.assertEqual(cat[-1].getTable(), t1)
514 2f0fa9cd - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.RuntimeErrorException,
487 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.RuntimeError,
cat.getColumnView)
516 2f0fa9cd - filename = "testTicket2938.fits"
489 c605dfcd + with lsst.utils.tests.getTempFilePath(".fits") as filename:
517 2f0fa9cd - cat.writeFits(filename) # shouldn't throw
490 c605dfcd + cat.writeFits(filename) # shouldn't throw
? ++++
518 2f0fa9cd - schema.addField("d", type=float, doc="doc for d")
491 c605dfcd + schema.addField("d", type=float, doc="doc for d")
? ++++
519 2f0fa9cd - t2 = lsst.afw.table.BaseTable.make(schema)
492 c605dfcd + t2 = lsst.afw.table.BaseTable.make(schema)
? ++++
520 2f0fa9cd - cat.append(t2.makeRecord())
493 c605dfcd + cat.append(t2.makeRecord())
? ++++
494 c605dfcd + self.assertRaises(lsst.pex.exceptions.LogicError, cat.writeFits, filename)
521 2f0fa9cd - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LogicErrorException,
522 2f0fa9cd - cat.writeFits, filename)
523 2f0fa9cd - os.remove(filename)
def testTicket3056(self): """Test sorting and sort-based searches of Catalogs""" schema = lsst.afw.table.SimpleTable.makeMinimalSchema() ki = schema.addField("i", type=int, doc="doc for i") kl = schema.addField("l", type=numpy.int64, doc="doc for l") kf = schema.addField("f", type=float, doc="doc for f") cat = lsst.afw.table.SimpleCatalog(schema) for j in range(50, 0, -1): record = cat.addNew() record.set(ki, j//10) record.set(kl, j) record.set(kf, numpy.random.randn()) self.assertFalse(cat.isSorted(ki)) self.assertFalse(cat.isSorted(kl)) # sort by unique int64 field, try unique lookups cat.sort(kl) self.assertTrue(cat.isSorted(kl)) r10 = cat.find(10, kl) self.assertEqual(r10.get(kl), 10) # sort by probably-unique float field, try unique and range lookups cat.sort(kf) self.assertTrue(cat.isSorted(kf)) r10 = cat.find(10, kf) self.assertTrue(r10 is None or r10.get(kf) == 10.0) # latter case virtually impossible i0 = cat.lower_bound(-0.5, kf) i1 = cat.upper_bound(0.5, kf) for i in range(i0, i1): self.assertGreaterEqual(cat[i].get(kf), -0.5) self.assertLess(cat[i].get(kf), 0.5) for r in cat[cat.between(-0.5, 0.5, kf)]: self.assertGreaterEqual(r.get(kf), -0.5) self.assertLess(r.get(kf), 0.5) # sort by nonunique int32 field, try range lookups cat.sort(ki) self.assertTrue(cat.isSorted(ki)) s = cat.equal_range(3, ki) self.assertTrue(cat[s].isSorted(kf)) # test for stable sort for r in cat[s]: self.assertEqual(r.get(ki), 3) self.assertEqual(s.start, cat.lower_bound(3, ki)) self.assertEqual(s.stop, cat.upper_bound(3, ki)) def testRename(self): """Test field-renaming functionality in Field, SchemaMapper""" field1i = lsst.afw.table.Field[int]("i1", "doc for i", "units for i") field2i = field1i.copyRenamed("i2") self.assertEqual(field1i.getName(), "i1") self.assertEqual(field2i.getName(), "i2") self.assertEqual(field1i.getDoc(), field2i.getDoc()) self.assertEqual(field1i.getUnits(), field2i.getUnits()) field1a = lsst.afw.table.Field["ArrayF"]("a1", "doc for a", "units for a", 3) field2a = field1a.copyRenamed("a2") self.assertEqual(field1a.getName(), "a1") self.assertEqual(field2a.getName(), "a2") self.assertEqual(field1a.getDoc(), field2a.getDoc()) self.assertEqual(field1a.getUnits(), field2a.getUnits()) self.assertEqual(field1a.getSize(), field2a.getSize()) schema1 = lsst.afw.table.Schema() k1i = schema1.addField(field1i) k1a = schema1.addField(field1a) mapper = lsst.afw.table.SchemaMapper(schema1) k2i = mapper.addMapping(k1i, "i2") k2a = mapper.addMapping(k1a, "a2") schema2 = mapper.getOutputSchema() self.assertEqual(schema1.find(k1i).field.getName(), "i1") self.assertEqual(schema2.find(k2i).field.getName(), "i2") self.assertEqual(schema1.find(k1a).field.getName(), "a1") self.assertEqual(schema2.find(k2a).field.getName(), "a2") self.assertEqual(schema1.find(k1i).field.getDoc(), schema2.find(k2i).field.getDoc()) self.assertEqual(schema1.find(k1a).field.getDoc(), schema2.find(k2a).field.getDoc()) self.assertEqual(schema1.find(k1i).field.getUnits(), schema2.find(k2i).field.getUnits()) self.assertEqual(schema1.find(k1a).field.getUnits(), schema2.find(k2a).field.getUnits()) self.assertEqual(schema1.find(k1a).field.getSize(), schema2.find(k2a).field.getSize()) k3i = mapper.addMapping(k1i, "i3") k3a = mapper.addMapping(k1a, "a3") schema3 = mapper.getOutputSchema() self.assertEqual(schema1.find(k1i).field.getName(), "i1") self.assertEqual(schema3.find(k3i).field.getName(), "i3") self.assertEqual(schema1.find(k1a).field.getName(), "a1") self.assertEqual(schema3.find(k3a).field.getName(), "a3") self.assertEqual(schema1.find(k1i).field.getDoc(), schema3.find(k3i).field.getDoc()) self.assertEqual(schema1.find(k1a).field.getDoc(), schema3.find(k3a).field.getDoc()) self.assertEqual(schema1.find(k1i).field.getUnits(), schema3.find(k3i).field.getUnits()) self.assertEqual(schema1.find(k1a).field.getUnits(), schema3.find(k3a).field.getUnits()) self.assertEqual(schema1.find(k1a).field.getSize(), schema3.find(k3a).field.getSize()) def testTicket3066(self): """Test the doReplace option on Schema.addField """ schema = lsst.afw.table.Schema() k1a = schema.addField("f1", doc="f1a", type="I") k2a = schema.addField("f2", doc="f2a", type="Flag") k3a = schema.addField("f3", doc="f3a", type="ArrayF", size=4)
618 7e5c4d23 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
? ^^^^^^^^^^^^^^^ ------- ------ ^^^^^^ ^
589 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError,
? ++ ^ ^^ ^ schema.addField, "f1", doc="f1b", type="I")
620 7e5c4d23 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
? ^^^^^^^^^^^^^^^ ------- ------ ^^^^^^ ^
591 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError,
? ++ ^ ^^ ^ schema.addField, "f2", doc="f2b", type="Flag")
622 7e5c4d23 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
? ^^^^^^^^^^^^^^^ ------- ------ ^^^^^^ ^
593 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError,
? ++ ^ ^^ ^ schema.addField, "f1", doc="f1b", type="F")
624 7e5c4d23 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
? ^^^^^^^^^^^^^^^ ------- ------ ^^^^^^ ^
595 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError,
? ++ ^ ^^ ^ schema.addField, "f2", doc="f2b", type="F")
626 7e5c4d23 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
597 55b692d5 + self.assertRaises(lsst.pex.exceptions.TypeError,
schema.addField, "f1", doc="f1b", type="F", doReplace=True)
628 7e5c4d23 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
599 55b692d5 + self.assertRaises(lsst.pex.exceptions.TypeError,
schema.addField, "f2", doc="f2b", type="F", doReplace=True)
630 1d7de6d9 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
601 55b692d5 + self.assertRaises(lsst.pex.exceptions.TypeError,
schema.addField, "f3", doc="f3b", type="ArrayF", size=3, doReplace=True) k1b = schema.addField("f1", doc="f1b", type="I", doReplace=True) self.assertEqual(k1a, k1b) self.assertEqual(schema.find(k1a).field.getDoc(), "f1b") k2b = schema.addField("f2", doc="f2b", type="Flag", doReplace=True) self.assertEqual(k2a, k2b) self.assertEqual(schema.find(k2a).field.getDoc(), "f2b") k3b = schema.addField("f3", doc="f3b", type="ArrayF", size=4, doReplace=True) self.assertEqual(k3a, k3b) self.assertEqual(schema.find(k3a).field.getDoc(), "f3b")
643 fbcc2936 - def testDM349(self):
? -
614 bc5cccae + def testDM384(self):
? +
615 bc5cccae + """Test the versioning persistence in FitsReader and FitsWriter
616 bc5cccae + """
617 bc5cccae + # Now test with a BaseTable
618 bc5cccae + schema = lsst.afw.table.Schema()
619 bd692192 + schema.setVersion(5)
620 bc5cccae + schema.addField("f1", doc="f1a", type="I")
621 bc5cccae + schema.addField("f2", doc="f2a", type="Flag")
622 bc5cccae + schema.addField("f3", doc="f3a", type="ArrayF", size=4)
623 bc5cccae + catalog = lsst.afw.table.BaseCatalog(schema)
624 bc5cccae + self.assertEqual(catalog.getTable().getVersion(), 5)
625 c605dfcd + with lsst.utils.tests.getTempFilePath("_BaseTable.fits") as filename:
626 c605dfcd + catalog.writeFits(filename)
627 c605dfcd + # now read the table just written to disk, and see if it reads back correctly
628 c605dfcd + catalog = catalog.readFits(filename)
629 c605dfcd + metadata = catalog.getTable().getMetadata()
630 c605dfcd + self.assertEqual(catalog.schema.getVersion(), 5)
631 c605dfcd + self.assertFalse(metadata == None)
632 c605dfcd + self.assertFalse(metadata.exists("AFW_TABLE_VERSION"))
633 bc5cccae +
634 bc5cccae + # Now test with a SimpleTable
635 c605dfcd + with lsst.utils.tests.getTempFilePath("_SimpleTable.fits") as filename:
636 c605dfcd + schema = lsst.afw.table.SimpleTable.makeMinimalSchema()
637 c605dfcd + schema.setVersion(5)
638 c605dfcd + schema.addField("f1", doc="f1a", type="I")
639 c605dfcd + schema.addField("f2", doc="f2a", type="Flag")
640 c605dfcd + schema.addField("f3", doc="f3a", type="ArrayF", size=4)
641 c605dfcd + catalog = lsst.afw.table.SimpleCatalog(schema)
642 c605dfcd + self.assertEqual(catalog.getTable().getVersion(), 5)
643 c605dfcd + catalog.writeFits(filename)
644 c605dfcd + # now read the table just written to disk, and see if it reads back correctly
645 c605dfcd + catalog = catalog.readFits(filename)
646 c605dfcd + metadata = catalog.getTable().getMetadata()
647 c605dfcd + self.assertEqual(catalog.getTable().getVersion(),5)
648 c605dfcd + self.assertFalse(metadata == None)
649 c605dfcd + self.assertFalse(metadata.exists("AFW_TABLE_VERSION"))
650 bc5cccae +
651 bc5cccae + # Now a SourceTable
652 c605dfcd + with lsst.utils.tests.getTempFilePath("_SourceTable.fits") as filename:
653 c605dfcd + schema = lsst.afw.table.SourceTable.makeMinimalSchema()
654 c605dfcd + schema.setVersion(5)
655 c605dfcd + schema.addField("f1", doc="f1a", type="I")
656 c605dfcd + schema.addField("f2", doc="f2a", type="Flag")
657 c605dfcd + schema.addField("f3", doc="f3a", type="ArrayF", size=4)
658 c605dfcd + catalog = lsst.afw.table.SourceCatalog(schema)
659 c605dfcd + self.assertEqual(catalog.getTable().getVersion(), 5)
660 c605dfcd + catalog.writeFits(filename)
661 c605dfcd + # now read the table just written to disk, and see if it reads back correctly
662 c605dfcd + catalog = catalog.readFits(filename)
663 c605dfcd + metadata = catalog.getTable().getMetadata()
664 c605dfcd + self.assertEqual(catalog.getTable().getVersion(),5)
665 c605dfcd + self.assertFalse(metadata == None)
666 c605dfcd + self.assertFalse(metadata.exists("AFW_TABLE_VERSION"))
667 bc5cccae +
668 aa977b5e + def testReplacePeriods(self):
669 aa977b5e + """Test version-dependent replacement of periods with underscores.
670 aa977b5e + """
671 aa977b5e + schema1 = lsst.afw.table.Schema()
672 aa977b5e + schema1.addField("a.b.c", type=float, doc="test field 1")
673 aa977b5e + schema1.addField("a.b.d", type="Flag", doc="test field 2")
674 aa977b5e + schema1.addField("a.b.e", type=str, doc="test field 3", size=16)
675 aa977b5e + schema2 = lsst.afw.table.Schema()
676 aa977b5e + schema2.addField("a_b_c", type=float, doc="test field 1")
677 aa977b5e + schema2.addField("a_b_d", type="Flag", doc="test field 2")
678 aa977b5e + schema2.addField("a_b_e", type=str, doc="test field 3", size=16)
679 aa977b5e + filename = "ReplacePeriods.fits"
680 aa977b5e +
681 aa977b5e + # For version 0, we should replace periods with underscores when we write
682 aa977b5e + # and do the reverse when we read
683 bd692192 + schema1.setVersion(0)
684 aa977b5e + cat = lsst.afw.table.BaseCatalog(schema1)
685 c605dfcd + with lsst.utils.tests.getTempFilePath("_schema1_v0.fits") as filename:
686 c605dfcd + cat.writeFits(filename)
687 c605dfcd + if pyfits is not None:
688 c605dfcd + fits = pyfits.open(filename)
689 c605dfcd + self.assertEqual(fits[1].header["TTYPE2"], "a_b_c")
690 c605dfcd + self.assertEqual(fits[1].header["TTYPE3"], "a_b_e")
691 c605dfcd + self.assertEqual(fits[1].header["TFLAG1"], "a_b_d")
692 c605dfcd + cat = lsst.afw.table.BaseCatalog.readFits(filename)
693 c605dfcd + self.assertTrue("a.b.c" in cat.schema)
694 c605dfcd + self.assertTrue("a.b.d" in cat.schema)
695 c605dfcd + self.assertTrue("a.b.e" in cat.schema)
696 aa977b5e +
697 aa977b5e + # For version 1, we shouldn't do any such replacement
698 bd692192 + schema1.setVersion(1)
699 aa977b5e + cat = lsst.afw.table.BaseCatalog(schema1)
700 c605dfcd + with lsst.utils.tests.getTempFilePath("_schema1_v1.fits") as filename:
701 c605dfcd + cat.writeFits(filename)
702 c605dfcd + if pyfits is not None:
703 c605dfcd + fits = pyfits.open(filename)
704 c605dfcd + self.assertEqual(fits[1].header["TTYPE2"], "a.b.c")
705 c605dfcd + self.assertEqual(fits[1].header["TTYPE3"], "a.b.e")
706 c605dfcd + self.assertEqual(fits[1].header["TFLAG1"], "a.b.d")
707 c605dfcd + cat = lsst.afw.table.BaseCatalog.readFits(filename)
708 c605dfcd + self.assertTrue("a.b.c" in cat.schema)
709 c605dfcd + self.assertTrue("a.b.d" in cat.schema)
710 c605dfcd + self.assertTrue("a.b.e" in cat.schema)
711 aa977b5e +
712 aa977b5e + # Also make sure that version 1 underscores are preserved
713 bd692192 + schema2.setVersion(1)
714 aa977b5e + cat = lsst.afw.table.BaseCatalog(schema2)
715 c605dfcd + with lsst.utils.tests.getTempFilePath("_schema2.fits") as filename:
716 c605dfcd + cat.writeFits(filename)
717 c605dfcd + if pyfits is not None:
718 c605dfcd + fits = pyfits.open(filename)
719 c605dfcd + self.assertEqual(fits[1].header["TTYPE2"], "a_b_c")
720 c605dfcd + self.assertEqual(fits[1].header["TTYPE3"], "a_b_e")
721 c605dfcd + self.assertEqual(fits[1].header["TFLAG1"], "a_b_d")
722 c605dfcd + cat = lsst.afw.table.BaseCatalog.readFits(filename)
723 c605dfcd + self.assertTrue("a_b_c" in cat.schema)
724 c605dfcd + self.assertTrue("a_b_d" in cat.schema)
725 c605dfcd + self.assertTrue("a_b_e" in cat.schema)
726 aa977b5e +
727 0faa194d + def testDM352(self):
filename = os.path.join(os.path.split(__file__)[0], "data", "great3.fits") cat = lsst.afw.table.BaseCatalog.readFits(filename) self.assertEqual(len(cat), 1)
731 250f8aed +
732 f5c0126e + def testDM590(self):
733 f5c0126e + # create a simple fits table using pyfits, and tests is version number
734 f5c0126e + # when it is read into a catalog
735 f5c0126e + if pyfits is not None:
736 f5c0126e + c1 = pyfits.Column(name='id', format='J', array=(1,2,3))
737 f5c0126e + c2 = pyfits.Column(name='flux', format='K', array=(1000,2000,3000))
738 f5c0126e + c3 = pyfits.Column(name='star', format='20A', array=('Vega', 'Denebola', 'Arcturus'))
739 f5c0126e + columns = pyfits.ColDefs([c1, c2, c3])
740 f5c0126e + tbhdu = pyfits.new_table(columns)
741 c605dfcd + with lsst.utils.tests.getTempFilePath(".fits") as filename:
742 c605dfcd + tbhdu.writeto(filename, clobber=True)
743 c605dfcd + cat = lsst.afw.table.BaseCatalog.readFits(filename)
744 c605dfcd + self.assertEqual(cat.getVersion(), lsst.afw.table.Schema.DEFAULT_VERSION)
745 f5c0126e +
746 de8a1b40 + def testDM1710(self):
747 de8a1b40 + # Extending without specifying a mapper or a deep argument should not
748 de8a1b40 + # raise.
749 de8a1b40 + schema = lsst.afw.table.Schema()
750 de8a1b40 + cat1 = lsst.afw.table.BaseCatalog(schema)
751 de8a1b40 + cat2 = lsst.afw.table.BaseCatalog(schema)
752 de8a1b40 + cat1.extend(cat2)
def testVariableLengthArrays(self): schema = lsst.afw.table.Schema() ka = schema.addField("a", doc="integer", type="ArrayI", size=0) kb = schema.addField("b", doc="single-precision", type="ArrayF") kc = schema.addField("c", doc="double-precision", type="ArrayD") cat1 = lsst.afw.table.BaseCatalog(schema) record1 = cat1.addNew() self.assertEqual(list(record1.get(ka)), []) self.assertEqual(list(record1.get(kb)), []) self.assertEqual(list(record1.get(kc)), []) a1 = numpy.random.randint(low=3, high=6, size=4).astype(numpy.int32) b1 = numpy.random.randn(5).astype(numpy.float32) c1 = numpy.random.randn(6).astype(numpy.float64) # Test get/set record1.set(ka, a1) record1.set(kb, b1) record1.set(kc, c1) self.assertTrue(numpy.all(record1.get(ka) == a1)) self.assertTrue(numpy.all(record1.get(kb) == b1)) self.assertTrue(numpy.all(record1.get(kc) == c1)) # Test __getitem__ and view semantics record1[kb][2] = 3.5 self.assertEqual(b1[2], 3.5) # Check that we throw when we try to index a variable-length array Key
672 0b745ec6 - self.assertRaisesLsstCpp(lsst.pex.exceptions.LogicErrorException, lambda x: ka[x], 0)
? ---------
778 2d6be90c + self.assertRaisesLsstCpp(lsst.pex.exceptions.LogicError, lambda x: ka[x], 0)
673 0b745ec6 - self.assertRaisesLsstCpp(lsst.pex.exceptions.LogicErrorException, lambda x, y: ka[x:y], 0, 1)
? ---------
779 2d6be90c + self.assertRaisesLsstCpp(lsst.pex.exceptions.LogicError, lambda x, y: ka[x:y], 0, 1)
# Test copying records, both with and without SchemaMapper record2 = cat1.addNew() record2.assign(record1) self.assertTrue(numpy.all(record1.get(ka) == a1)) self.assertTrue(numpy.all(record1.get(kb) == b1)) self.assertTrue(numpy.all(record1.get(kc) == c1)) record1[kb][2] = 4.5 self.assertEqual(record2[kb][2], 3.5) # copy in assign() should be deep mapper = lsst.afw.table.SchemaMapper(schema) kb2 = mapper.addMapping(kb) cat2 = lsst.afw.table.BaseCatalog(mapper.getOutputSchema()) record3 = cat2.addNew() record3.assign(record1, mapper) self.assertTrue(numpy.all(record3.get(kb2) == b1)) # Test that we throw if we try to get a column view of a variable-length arry
689 0b745ec6 - self.assertRaisesLsstCpp(lsst.pex.exceptions.LogicErrorException, cat1.get, ka)
? ---------
795 2d6be90c + self.assertRaisesLsstCpp(lsst.pex.exceptions.LogicError, cat1.get, ka)
# Test that we can round-trip variable-length arrays through FITS filename = "testSimpleTable_testVariableLengthArrays.fits" cat1.writeFits(filename) cat3 = lsst.afw.table.BaseCatalog.readFits(filename) self.assertEqual(schema.compare(cat3.schema, lsst.afw.table.Schema.IDENTICAL), lsst.afw.table.Schema.IDENTICAL) record4 = cat3[0] self.assertTrue(numpy.all(record4.get(ka) == a1)) self.assertTrue(numpy.all(record4.get(kb) == b1)) self.assertTrue(numpy.all(record4.get(kc) == c1)) os.remove(filename) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" lsst.utils.tests.init() suites = [] suites += unittest.makeSuite(SimpleTableTestCase) suites += unittest.makeSuite(lsst.utils.tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" lsst.utils.tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

Return to list

Commits in /Users/nate/repos_hsc/afw/

7f5a3711

commit 7f5a3711844a524b3f23283453d5a31c3c122c09
Author: Jim Bosch 
Date:   Fri Jan 6 18:54:18 2012 -0500

    added initial SWIG for record and table classes, with support for scalar and geom fields so far

fbcc2936

commit fbcc2936441c78603256c27a74c953712370918c
Author: Jim Bosch 
Date:   Mon Mar 31 16:35:15 2014 -0400

    Fix, test, for regex bug in table FITS I/O

2f0fa9cd

commit 2f0fa9cdd45a5ee41f019fd7a2a7b4ca6ec79afb
Author: Jim Bosch 
Date:   Mon Jul 1 11:58:21 2013 -0600

    Don't require all records in a catalog to share a table (#2938)
    
    Now we just check for compatible schemas when writing to FITS.
    
    Also fixed up some documentation formatting while updating the
    docs to reflect the change in behavior

7e5c4d23

commit 7e5c4d2338fe4fb88e187860a49a42c8fc2c50f4
Author: Jim Bosch 
Date:   Wed Nov 20 16:08:46 2013 -0500

    Add support for replacing fields in Schema.addField (#3066)

1d7de6d9

commit 1d7de6d9468eaa44b004815bd1c60755fa7a6a5d
Author: Jim Bosch 
Date:   Fri Jan 10 17:08:47 2014 -0500

    When replacing fields in Schemas, need to ensure the size doesn't change.

c2e69e2c

commit c2e69e2c423540ae0c939f36bacc825da13cb695
Author: Jim Bosch 
Date:   Thu Jun 14 15:44:35 2012 -0400

    add support for preallocating records through Catalog.reserve

341e49d9

commit 341e49d974b202e73897db621bb367ebc065c265
Author: Jim Bosch 
Date:   Mon May 7 15:39:45 2012 -0400

    Throw exceptions for invalid table keys rather than assert.

ee5b9d95

commit ee5b9d95e6b81546653aa8a9bb08948a23e64bcf
Author: Paul Price 
Date:   Tue Sep 25 14:21:49 2012 -0400

    Fix writing of FITS file to memory (constructor wasn't initialising components).

14647d65

commit 14647d65e2d059c1fb2f11c1bf6f8d64b5ff53d6
Author: Jim Bosch 
Date:   Fri May 25 15:39:59 2012 -0400

    Unit tests for afw::table dictionary extractors.

0b745ec6

commit 0b745ec681de903b911691c49f07f3ebc52c692f
Author: Jim Bosch 
Date:   Mon Dec 1 13:46:03 2014 -0500

    Add variable-length array fields to afw::table
    
    We use Array with a size of zero to indicate variable-length fields.
    It'd probably be better to use a completely different tag type, but
    Boost.Variant puts an upper limit on how many tags we have, so until
    we rewrite afw::table to avoid it, we need to limit how many we use.

6c49463c

commit 6c49463cf28838980e05aea39554d9dc0794dca5
Author: Jim Bosch 
Date:   Thu Mar 22 13:05:11 2012 -0400

    fix bug in FLAGCOL key handling logic that broke FITS read support for tables with no flag fields

fd4c0bae

commit fd4c0baec617155fac0816607a5acba88e8970f5
Author: Jim Bosch 
Date:   Thu Apr 4 16:20:20 2013 -0400

    Add support for renaming without replacing the full field in SchemaMapper.

Commits in /Users/nate/repos_lsst/afw/

028f751f

commit 028f751fa3d0fe5101d2467942ea2e5229ba5200
Author: Jim Bosch 
Date:   Wed Jul 9 18:13:59 2014 -0400

    Notify owning tables when schema aliases are modified.

2d6be90c

commit 2d6be90c6e14ab8fa2803a84a45106345037f1f5
Author: Lauren MacArthur 
Date:   Thu Apr 2 13:50:52 2015 -0400

    Remove trailing Exception in exception names

f5c0126e

commit f5c0126ee21ec72bce6af997b2efe30a3a70feb0
Author: Perry Gee 
Date:   Fri Aug 29 11:31:17 2014 -0700

    fix comment in FitsReader.cc

de8a1b40

commit de8a1b40ff4a65efefd579ee12c7f097f40d2478
Author: John Swinbank 
Date:   Thu Dec 18 19:20:00 2014 -0500

    Test case for DM-1710

55b692d5

commit 55b692d5d02e72b84aa9efe49e1d212f0a807db5
Author: Jim Bosch 
Date:   Mon Oct 6 12:51:46 2014 -0400

    Be more consistent about exceptions thrown/caught in Schema::find
    
    The Python-level code, which loops over all the C++ template instantiations until it
    finds one that doesn't throw, was catching all Exceptions, not just those that meant
    the field couldn't be found with the given type.

7f5a3711

commit 7f5a3711844a524b3f23283453d5a31c3c122c09
Author: Jim Bosch 
Date:   Fri Jan 6 18:54:18 2012 -0500

    added initial SWIG for record and table classes, with support for scalar and geom fields so far

b80fe1d3

commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
Author: Russell Owen 
Date:   Mon Oct 27 18:01:15 2014 -0700

    Support from __future__ import division
    for classes such as Extension that support operator/ and/or operator/=
    and change unit tests to use it

6fc1c3d1

commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
Author: Jim Bosch 
Date:   Thu Jul 17 16:05:56 2014 -0400

    Adapt to changes in exception Python wrappers (DM-827)

4bae7ca1

commit 4bae7ca131d04a3f68e47748b0423617ffd33000
Author: Paul Price 
Date:   Wed Aug 6 16:40:49 2014 -0400

    tests: seed random number generator to make tests deterministic

bd692192

commit bd692192367d33bb64a79ca008bff10eb9b41932
Author: pgee 
Date:   Mon Aug 18 15:06:04 2014 -0700

    Move API version number from BaseTable to Schema
    
    In FitsReader, move reading the AFW_TABLE_VERSION header key into the
    Schema-from-metadata constructor.
    In FitsWriter, use the version attached to the table schema to write the
    metadata.

25e84506

commit 25e84506758c975a55e7941ebcdde88d8a0923f0
Author: Jim Bosch 
Date:   Mon Jan 26 12:13:19 2015 -0500

    Include aliases in table extract() methods.

df7781eb

commit df7781eb93bf9e0527cd6dc78f4117e9e030b3f2
Author: Jim Bosch 
Date:   Mon Jan 26 16:49:40 2015 -0500

    Update table extract() method test code to version 1

c605dfcd

commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
Author: Russell Owen 
Date:   Wed Apr 8 15:30:37 2015 -0700

    Use getTempFilePath to avoid temp file name collisions
    
    Using the same file name for temp files for different tests
    was causing occasional test failures due to collisions (one test
    would read another test's temporary file). Using the new context manager
    lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
    of accidentally picking like names in the future (e.g. from careless copy/paste),
    and handles file clean up on success.
    
    Use lsst.utils.tests.getTempFilePath where appropriate
    
    Remove old uses of os.remove, os.unlink and manually creating temporary file names
    and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
    since this automatically creates a name that is unique to a particular test method
    (and can easily create names that are unique within a test) and deletes the file at the end.
    
    Remove the only use of temporaryFile that I could find

bc5cccae

commit bc5cccaefd7b295975759bfd5213afb4e79a8f9e
Author: Perry Gee 
Date:   Mon Apr 14 12:45:10 2014 -0500

    Change to the _readTable routines in these 4 types plus BaseTable so that the
    AFW_TABLE_VERSION entry in the header is used to version each type of table.
    The getVersion() routine from BaseTable is used to get the version number during
    save, and it is written to the metadata of the table before the metadata is persisted.
    
    On read, the metadata is searched at the beginning of FitsReader::_startRecords,
    and the version number is set on the table then.  The table-getMetadata() is cleansed.
    I also moved the removal code for AFW_TYPE to here.
    
    Jim, please check the code to be sure that there are not unintended consquences from
    moving the table->setMetadata to the middle of the _readTable routines

aa977b5e

commit aa977b5e9cec2808c5751ba795da4ce21c066e7b
Author: Jim Bosch 
Date:   Sun Apr 20 10:44:26 2014 -0400

    Stop replacing periods with underscores in table I/O (DM-242)

a9485a48

commit a9485a486e70ea83dece113adef1243e5ffddb0f
Author: Jim Bosch 
Date:   Wed Dec 31 11:17:25 2014 -0800

    Allow SchemaMapper as positional argument to Catalog.extend

0faa194d

commit 0faa194d1898186dcae6ab6d3db41d7523e87046
Author: Jim Bosch 
Date:   Tue Apr 22 15:28:33 2014 -0400

    Fix test name to match the correct issue number

250f8aed

commit 250f8aed29d747269ac50ea84769104eafa48972
Author: Jim Bosch 
Date:   Mon Mar 31 16:35:15 2014 -0400

    Fix, test, for regex bug in table FITS I/O

Return to list

include/lsst/afw/math/Background.h

Diff:

                // -*- LSST-C++ -*-
                
                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                #if !defined(LSST_AFW_MATH_BACKGROUND_H)
                #define LSST_AFW_MATH_BACKGROUND_H
                /**
                 * @brief Estimate image backgrounds
                 * @ingroup afw
                 * @author Steve Bickerton
                 */
                #include 
                #include "boost/shared_ptr.hpp"
                #include "lsst/daf/base/Citizen.h"
                #include "lsst/pex/exceptions.h"
                #include "lsst/afw/geom/Box.h"
                #include "lsst/afw/math/Statistics.h"
                #include "lsst/afw/math/Interpolate.h"
39 13cd7b6a - #include "lsst/afw/math/Approximate.h"
namespace lsst { namespace afw { namespace math {
43 9118b4b1 + class ApproximateControl;
44 9118b4b1 + template class Approximate;
// // Remember to update stringToUndersampleStyle if you change this. // If this happens often, we can play CPP games to put the definition in exactly one place, although swig // may not be happy (so we could think m4 thoughts instead) // enum UndersampleStyle { THROW_EXCEPTION, REDUCE_INTERP_ORDER, INCREASE_NXNYSAMPLE }; UndersampleStyle stringToUndersampleStyle(std::string const &style); /** * @class BackgroundControl * @brief Pass parameters to a Background object */ class BackgroundControl { public: BackgroundControl( int const nxSample, ///< Num. grid samples in x int const nySample, ///< Num. grid samples in y StatisticsControl const sctrl = StatisticsControl(), ///< Configuration for Stats to be computed
67 264e671e - Property const prop = MEANCLIP, ///< statistical property to use for grid points
? -
68 fd4b25a3 + Property const prop = MEANCLIP ///< statistical property to use for grid points
68 264e671e - ApproximateControl const actrl =
69 264e671e - ApproximateControl(ApproximateControl::UNKNOWN, 1) ///< configuration for approx to be computed
) : _style(Interpolate::AKIMA_SPLINE), _nxSample(nxSample), _nySample(nySample), _undersampleStyle(THROW_EXCEPTION), _sctrl(new StatisticsControl(sctrl)),
75 264e671e - _prop(prop),
? ^
74 fd4b25a3 + _prop(prop) {
? ^^
76 264e671e - _actrl(new ApproximateControl(actrl)) {
if (nxSample <= 0 || nySample <= 0) {
78 55878294 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
? ---------
76 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
str(boost::format("You must specify at least one point, not %dx%d") % nxSample % nySample) ); } } /** * Overload constructor to handle string for statistical operator */ BackgroundControl( int const nxSample, ///< num. grid samples in x int const nySample, ///< num. grid samples in y StatisticsControl const &sctrl, ///< configuration for stats to be computed
92 264e671e - std::string const &prop, ///< statistical property to use for grid points
? ^
90 bbc73b85 + std::string const &prop ///< statistical property to use for grid points
? ^
93 264e671e - ApproximateControl const actrl =
94 264e671e - ApproximateControl(ApproximateControl::UNKNOWN, 1) ///< configuration for approx to be computed
) : _style(Interpolate::AKIMA_SPLINE), _nxSample(nxSample), _nySample(nySample), _undersampleStyle(THROW_EXCEPTION), _sctrl(new StatisticsControl(sctrl)),
100 264e671e - _prop(stringToStatisticsProperty(prop)),
? ^
96 fd4b25a3 + _prop(stringToStatisticsProperty(prop)) {
? ^^
101 264e671e - _actrl(new ApproximateControl(actrl)) {
if (nxSample <= 0 || nySample <= 0) {
103 55878294 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
? ---------
98 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
str(boost::format("You must specify at least one point, not %dx%d") % nxSample % nySample) ); } } // And now the two old APIs (preserved for backward compatibility) /** * \deprecated New code should specify the interpolation style in getImage, not the BackgroundControl ctor */ BackgroundControl( Interpolate::Style const style, ///< Style of the interpolation int const nxSample = 10, ///< Num. grid samples in x int const nySample = 10, ///< Num. grid samples in y UndersampleStyle const undersampleStyle = THROW_EXCEPTION, ///< Behaviour if there are too few points StatisticsControl const sctrl = StatisticsControl(), ///< Configuration for Stats to be computed
119 264e671e - Property const prop = MEANCLIP, ///< statistical property to use for grid points
? -
114 8a7896d8 + Property const prop = MEANCLIP ///< statistical property to use for grid points
120 264e671e - ApproximateControl const actrl =
121 264e671e - ApproximateControl(ApproximateControl::UNKNOWN, 1) ///< configuration for approx to be computed
122 264e671e -
) : _style(style), _nxSample(nxSample), _nySample(nySample), _undersampleStyle(undersampleStyle), _sctrl(new StatisticsControl(sctrl)),
128 264e671e - _prop(prop),
? ^
120 8a7896d8 + _prop(prop) {
? ^^
129 264e671e - _actrl(new ApproximateControl(actrl)) {
if (nxSample <= 0 || nySample <= 0) {
131 55878294 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
? ---------
122 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
str(boost::format("You must specify at least one point, not %dx%d") % nxSample % nySample) ); } } /** * Overload constructor to handle strings for both interp and undersample styles. * * \deprecated New code should specify the interpolation style in getImage, not the BackgroundControl ctor */ BackgroundControl( std::string const &style, ///< Style of the interpolation int const nxSample = 10, ///< num. grid samples in x int const nySample = 10, ///< num. grid samples in y std::string const &undersampleStyle = "THROW_EXCEPTION", ///< behaviour if there are too few points StatisticsControl const sctrl = StatisticsControl(), ///< configuration for stats to be computed
149 264e671e - std::string const &prop = "MEANCLIP", ///< statistical property to use for grid points
? -
140 bbc73b85 + std::string const &prop = "MEANCLIP" ///< statistical property to use for grid points
150 264e671e - ApproximateControl const actrl =
151 264e671e - ApproximateControl(ApproximateControl::UNKNOWN, 1) ///< configuration for approx to be computed
) : _style(math::stringToInterpStyle(style)), _nxSample(nxSample), _nySample(nySample), _undersampleStyle(math::stringToUndersampleStyle(undersampleStyle)), _sctrl(new StatisticsControl(sctrl)),
157 264e671e - _prop(stringToStatisticsProperty(prop)),
? ^
146 8a7896d8 + _prop(stringToStatisticsProperty(prop)) {
? ^^
158 264e671e - _actrl(new ApproximateControl(actrl)) {
if (nxSample <= 0 || nySample <= 0) {
160 55878294 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
? ---------
148 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
str(boost::format("You must specify at least one point, not %dx%d") % nxSample % nySample) ); } } virtual ~BackgroundControl() {} void setNxSample (int nxSample) { if (nxSample <= 0) {
170 55878294 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
? ---------
158 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
str(boost::format("nxSample must be position, not %d") % nxSample)); } _nxSample = nxSample; } void setNySample (int nySample) { if (nySample <= 0) {
177 55878294 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
? ---------
165 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
str(boost::format("nySample must be position, not %d") % nySample)); } _nySample = nySample; } void setInterpStyle (Interpolate::Style const style) { _style = style; } // overload to take a string void setInterpStyle (std::string const &style) { _style = math::stringToInterpStyle(style); } void setUndersampleStyle (UndersampleStyle const undersampleStyle) { _undersampleStyle = undersampleStyle; } // overload to take a string void setUndersampleStyle (std::string const &undersampleStyle) { _undersampleStyle = math::stringToUndersampleStyle(undersampleStyle); } int getNxSample() const { return _nxSample; } int getNySample() const { return _nySample; } Interpolate::Style getInterpStyle() const { if (_style < 0 || _style >= Interpolate::NUM_STYLES) {
199 fd4b25a3 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
? ^^^^^^ ^
187 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
? ^^ ^ str(boost::format("Style %d is invalid") % _style)); } return _style; } UndersampleStyle getUndersampleStyle() const { return _undersampleStyle; } PTR(StatisticsControl) getStatisticsControl() { return _sctrl; } CONST_PTR(StatisticsControl) getStatisticsControl() const { return _sctrl; } Property getStatisticsProperty() const { return _prop; } void setStatisticsProperty(Property prop) { _prop = prop; } void setStatisticsProperty(std::string prop) { _prop = stringToStatisticsProperty(prop); }
212 13cd7b6a -
213 264e671e - void setApproximateControl(PTR(ApproximateControl) actrl) { _actrl = actrl; }
214 264e671e - PTR(ApproximateControl) getApproximateControl() { return _actrl; }
215 264e671e - CONST_PTR(ApproximateControl) getApproximateControl() const { return _actrl; }
private: Interpolate::Style _style; // style of interpolation to use int _nxSample; // number of grid squares to divide image into to sample in x int _nySample; // number of grid squares to divide image into to sample in y UndersampleStyle _undersampleStyle; // what to do when nx,ny are too small for the requested interp style PTR(StatisticsControl) _sctrl; // statistics control object Property _prop; // statistics Property
224 264e671e - PTR(ApproximateControl) _actrl; // approximate control object
}; /** * @class Background * @brief A virtual base class to evaluate %image background levels */ class Background : public daf::base::Citizen { protected: template explicit Background(ImageT const& img, BackgroundControl const& bgCtrl); explicit Background(geom::Box2I const imageBBox, int const nx, int const ny); /// dtor virtual ~Background() { } public: typedef float InternalPixelT; ///< type used for any internal images, and returned by getApproximate /// Add a constant level to a background virtual void operator+=(float const delta) = 0; /// Subtract a constant level from a background virtual void operator-=(float const delta) = 0; /** * \brief Method to interpolate and return the background for entire image * * \return A boost shared-pointer to an image containing the estimated background */ template PTR(lsst::afw::image::Image) getImage( Interpolate::Style const interpStyle, ///< Style of the interpolation UndersampleStyle const undersampleStyle=THROW_EXCEPTION ///< Behaviour if there are too few points ) const { return getImage(_imgBBox, interpStyle, undersampleStyle); } /** * \brief Method to interpolate and return the background for entire image * * \return A boost shared-pointer to an image containing the estimated background */ template PTR(lsst::afw::image::Image) getImage( std::string const &interpStyle, ///< Style of the interpolation std::string const &undersampleStyle="THROW_EXCEPTION" ///< Behaviour if there are too few points ) const { return getImage(math::stringToInterpStyle(interpStyle), stringToUndersampleStyle(undersampleStyle)); } template PTR(lsst::afw::image::Image) getImage( lsst::afw::geom::Box2I const& bbox, ///< Bounding box for sub-image Interpolate::Style const interpStyle, ///< Style of the interpolation UndersampleStyle const undersampleStyle=THROW_EXCEPTION ///< Behaviour if there are too few points ) const { return _getImage(bbox, interpStyle, undersampleStyle, static_cast(0)); } template PTR(lsst::afw::image::Image) getImage( lsst::afw::geom::Box2I const& bbox, ///< Bounding box for sub-image std::string const& interpStyle, ///< Style of the interpolation std::string const& undersampleStyle="THROW_EXCEPTION" ///< Behaviour if there are too few points ) const { return _getImage(bbox, math::stringToInterpStyle(interpStyle), stringToUndersampleStyle(undersampleStyle), static_cast(0)); } /** * \brief Method to interpolate and return the background for entire image * \deprecated New code should specify the interpolation style in getImage, not the ctor */ template PTR(lsst::afw::image::Image) getImage() const {
295 264e671e - return getImage(_bctrl->getInterpStyle(), _bctrl->getUndersampleStyle());
? ^^ ^^
278 36a259f5 + return getImage(_bctrl.getInterpStyle(), _bctrl.getUndersampleStyle());
? ^ ^ } /** * Return the Interpolate::Style that we actually used in the last call to getImage() * * N.b. Interpolate can fallback to a lower order if there aren't enough samples */ Interpolate::Style getAsUsedInterpStyle() const { return _asUsedInterpStyle; } /** * Return the UndersampleStyle that we actually used in the last call to getImage() */ UndersampleStyle getAsUsedUndersampleStyle() const { return _asUsedUndersampleStyle; } /** * \brief Method to return an approximation to the background */ PTR(math::Approximate) getApproximate( ApproximateControl const& actrl, ///< Approximation style UndersampleStyle const undersampleStyle=THROW_EXCEPTION ///< Behaviour if there are too few points ) const { InternalPixelT disambiguate = 0; return _getApproximate(actrl, undersampleStyle, disambiguate); } /** * Return the input image's (PARENT) bounding box */ geom::Box2I getImageBBox() const { return _imgBBox; }
326 264e671e - PTR(BackgroundControl) getBackgroundControl() { return _bctrl; }
327 264e671e - CONST_PTR(BackgroundControl) getBackgroundControl() const { return _bctrl; }
328 13cd7b6a -
protected: geom::Box2I _imgBBox; ///< size and origin of input image
331 264e671e - PTR(BackgroundControl) _bctrl; ///< control info set by user.
? ---- -
311 2b4b80a5 + BackgroundControl _bctrl; ///< control info set by user.
? +++++ mutable Interpolate::Style _asUsedInterpStyle; ///< the style we actually used mutable UndersampleStyle _asUsedUndersampleStyle; ///< the undersampleStyle we actually used std::vector _xcen; ///< x center pix coords of sub images std::vector _ycen; ///< y center ... std::vector _xorig; ///< x origin pix coords of sub images std::vector _yorig; ///< y origin ... std::vector _xsize; ///< x size of sub images std::vector _ysize; ///< y size ... /* * We want getImage to be present in the base class, but a templated virtual function * is impossible. So we'll solve the dilemma with a hack: explicitly defined * virtual functions for the image types we need */ #if !defined(SWIG) // We'll evaluate LSST_makeBackground_get{Approximation,Image} for each type in // LSST_makeBackground_get{Approximation,Image}_types, // setting v to the second arg (i.e. "= 0" for the first invocation). The first agument, m, is ignores // Desired types
352 264e671e - #define LSST_makeBackground_getImage_types (Background::InternalPixelT)
? ^^^^^^ ^^^^^ -----------
332 9118b4b1 + #define LSST_makeBackground_getImage_types (double)(float)(int)
? ^ ^^^^^^^^^^^^^ #define LSST_makeBackground_getApproximate_types (Background::InternalPixelT) #define LSST_makeBackground_getImage(m, v, T) \ virtual PTR(lsst::afw::image::Image) _getImage( \ lsst::afw::geom::Box2I const& bbox, \ Interpolate::Style const interpStyle, /* Style of the interpolation */ \ UndersampleStyle const undersampleStyle=THROW_EXCEPTION, /* Behaviour if there are too few points */\ T = 0 /* disambiguate */ \ ) const v; #define LSST_makeBackground_getApproximate(m, v, T) \ virtual PTR(Approximate) _getApproximate( \ ApproximateControl const& actrl, /* Approximation style */ \ UndersampleStyle const undersampleStyle=THROW_EXCEPTION, /* Behaviour if there are too few points */\ T = 0 /* disambiguate */ \ ) const v; BOOST_PP_SEQ_FOR_EACH(LSST_makeBackground_getImage, = 0, LSST_makeBackground_getImage_types) BOOST_PP_SEQ_FOR_EACH(LSST_makeBackground_getApproximate, = 0, LSST_makeBackground_getApproximate_types) #endif private: Background(Background const&); Background& operator=(Background const&); void _setCenOrigSize(int const width, int const height, int const nxSample, int const nySample); }; /** * @class BackgroundMI * @brief A class to evaluate %image background levels * * Break an image up into nx*ny sub-images and use a statistical to estimate the background levels in each * square. Then use a user-specified or algorithm to estimate background at a given pixel coordinate. * * Methods are available to return the background at a point (inefficiently), or an entire background image. * BackgroundControl contains a public StatisticsControl member to allow user control of how the backgrounds are computed. * @code math::BackgroundControl bctrl(7, 7); // number of sub-image squares in {x,y}-dimensions bctrl.sctrl.setNumSigmaClip(5.0); // use 5-sigma clipping for the sub-image means PTR(math::Background) backobj = math::makeBackground(img, bctrl); // get a whole background image Image back = backobj->getImage(math::Interpolate::NATURAL_SPLINE); * @endcode * * \deprecated * there is also * \code // get the background at a pixel at i_x,i_y double someValue = backobj.getPixel(math::Interpolate::LINEAR, i_x, i_y); * \endcode */ class BackgroundMI : public Background { public: template explicit BackgroundMI(ImageT const& img, BackgroundControl const& bgCtrl); explicit BackgroundMI(geom::Box2I const imageDimensions, image::MaskedImage const& statsImage); virtual void operator+=(float const delta); virtual void operator-=(float const delta); double getPixel(Interpolate::Style const style, int const x, int const y) const; /** * \brief Return the background value at a point * * \warning This is very inefficient -- only use it for debugging, if then. * * \deprecated New code should specify the interpolation style in getPixel, not the ctor */ double getPixel(int const x, int const y) const {
423 264e671e - return getPixel(_bctrl->getInterpStyle(), x, y);
? ^^
403 bbc73b85 + return getPixel(_bctrl.getInterpStyle(), x, y);
? ^ } /** * \brief Return the image of statistical quantities extracted from the image */ lsst::afw::image::MaskedImage getStatsImage() const { return _statsImage; } private: lsst::afw::image::MaskedImage _statsImage; // statistical properties for the grid of subimages mutable std::vector > _gridColumns; // interpolated columns for the bicubic spline void _setGridColumns(Interpolate::Style const interpStyle, UndersampleStyle const undersampleStyle, int const iX, std::vector const& ypix) const; #if !defined(SWIG) && defined(LSST_makeBackground_getImage) BOOST_PP_SEQ_FOR_EACH(LSST_makeBackground_getImage, , LSST_makeBackground_getImage_types) BOOST_PP_SEQ_FOR_EACH(LSST_makeBackground_getApproximate, , LSST_makeBackground_getApproximate_types) #if 0 // keep for use in Background instantiations #undef LSST_makeBackground_getImage_types #undef LSST_makeBackground_getApproximate_types #endif #undef LSST_makeBackground_getImage #undef LSST_makeBackground_getApproximate #endif // Here's the worker function for _getImage (non-virtual; it's templated in BackgroundMI, not Background) template PTR(image::Image) doGetImage(geom::Box2I const& bbox, Interpolate::Style const interpStyle_, UndersampleStyle const undersampleStyle) const; // and for _getApproximate template PTR(Approximate) doGetApproximate(ApproximateControl const& actrl, UndersampleStyle const undersampleStyle) const; }; /** * @brief A convenience function that uses function overloading to make the correct type of Background * * cf. std::make_pair() */ template PTR(Background) makeBackground(ImageT const& img, BackgroundControl const& bgCtrl) { return PTR(Background)(new BackgroundMI(img, bgCtrl)); } }}} #endif // LSST_AFW_MATH_BACKGROUND_H

Return to list

Commits in /Users/nate/repos_hsc/afw/

55878294

commit 558782943d12f5ccb489fbe9c405775552db7721
Author: Robert Lupton the Good 
Date:   Wed Oct 10 20:24:30 2012 -0400

    Only assert on bugs, not on user errors

13cd7b6a

commit 13cd7b6a7bcaaed466148aa40fa2db5fc4809d28
Author: Steven Bickerton 
Date:   Thu Oct 16 19:23:42 2014 +0900

    Allow background to persist info about approx

fd4b25a3

commit fd4b25a3402ad51327db111b22cb1ad75706db78
Author: Robert Lupton the Good 
Date:   Tue Oct 9 17:45:51 2012 -0400

    Add an API to BackgroundControl()/Background::getImage() that specifies the interpolation strategy in getImage
    
    The old design mixed background estimation (in the Background ctor) and interpolation (also in the ctor),
    and this is the first stage in disentangling them.  The old API is still supported (modulo the next
    paragraph).
    
    N.b. BackgroundControl can no longer be default-constructed. The 10x10 default wasn't generally useful, and
    the new API (#2074) nolonger has a style argument that happens to disambiguate the string and enum versions.

264e671e

commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
Author: Steven Bickerton 
Date:   Fri Oct 24 14:37:15 2014 +0900

    Use shared_ptr.  Add test.  Disable double,int backgrounds.

Commits in /Users/nate/repos_lsst/afw/

fd4b25a3

commit fd4b25a3402ad51327db111b22cb1ad75706db78
Author: Robert Lupton the Good 
Date:   Tue Oct 9 17:45:51 2012 -0400

    Add an API to BackgroundControl()/Background::getImage() that specifies the interpolation strategy in getImage
    
    The old design mixed background estimation (in the Background ctor) and interpolation (also in the ctor),
    and this is the first stage in disentangling them.  The old API is still supported (modulo the next
    paragraph).
    
    N.b. BackgroundControl can no longer be default-constructed. The 10x10 default wasn't generally useful, and
    the new API (#2074) nolonger has a style argument that happens to disambiguate the string and enum versions.

9118b4b1

commit 9118b4b10b049387776b83e24863c0eb025fe568
Author: Robert Lupton the Good 
Date:   Sun Oct 21 18:50:32 2012 -0400

    Give Background the ability return an Approximate object
    
    N.b. now that we need to auto-generate two sets of methods
    it seemed worth using boost pre-processor magic.  Note that
    we don't generate all possible Approximate pixel types,
    as Background only keeps one type in internal representation
    of its values (at least, BackgroundMI only keeps one type)

36a259f5

commit 36a259f57bfa56efb86ee93aac20de9ac1856aca
Author: Robert Lupton the Good 
Date:   Sun Oct 14 19:42:19 2012 -0400

    Split Background into Background and BackgroundBase
    
    The MaskedImage statsImage is really an implementation detail of this background model,
    and not a property of the Background.  I accordingly added a base class and kept the
    MaskedImage bits in the Background object.  Maybe I should have called them Background
    and BackgroundMI or something.  Note that we now need to return a pointer from makeBackground,
    hence the changes to the tests/examples

21597d88

commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
Author: Russell Owen 
Date:   Tue Jun 17 11:38:19 2014 -0700

    Rename exceptions

8a7896d8

commit 8a7896d806299f31c1d1c13987661dffeef6dd2c
Author: bick 
Date:   Tue Oct 5 21:44:26 2010 +0000

    Completed changes for #1463.

2b4b80a5

commit 2b4b80a531b4f37ae62b237534c8142eb3450449
Author: Robert Lupton the Good 
Date:   Sat Mar 9 07:01:06 2013 +0900

    Make it possible to round-trip a list of Backgrounds via disk
    
    This involved adding a ctor to make a BackgroundMI from a statsImage
    and the full-resolution image bounding box (n.b. the origin is
    still ignored).   Because much task code still uses legacy API where
    the interpolation style is specified in the ctor, not as arguments to
    getImage where it's actually used, it seemed out of scope to expect
    the list to be of tuples (Background, interpStyle, undersampleStyle)
    so I use the values that were last used to get an Image.  This is
    probably safe, but is a little ugly.

bbc73b85

commit bbc73b8543585dc03c6a791faa9db8977ec0908b
Author: Robert Lupton the Good 
Date:   Wed Oct 10 13:13:41 2012 -0400

    Allow strings as arguments to getImage()
    
    Also pass const strings by reference

Return to list

examples/timeWarpGpu.cc

Diff:

                // -*- lsst-c++ -*-
                
                /*
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 *
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 *
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 *
                 * You should have received a copy of the LSST License Statement and
                 * the GNU General Public License along with this program.  If not,
                 * see .
                 */
                
                /**
                * @file
                *
                * @brief Times the speedup of GPU accelerated convolution
                *
                * @author Kresimir Cosic
                *
                * @ingroup afw
                */
                
                
                #include 
                #include 
                
                #include 
                #include 
                #include 
                #include 
                #include 
                
45 a9aec7fc + #include "lsst/utils/Utils.h"
46 a9aec7fc + #include "lsst/pex/exceptions.h"
#include "lsst/utils/ieee.h" #include "lsst/daf/base.h" #include "lsst/pex/exceptions.h" #include "lsst/pex/logging/Trace.h" #include "lsst/afw/image.h" #include "lsst/afw/geom.h" #include "lsst/afw/math.h" #include "lsst/afw/gpu/IsGpuBuild.h" //Just for PrintCudaDeviceInfo #include "lsst/afw/gpu/detail/CudaQueryDevice.h" int const defaultInterpLen = 20; using namespace std; using lsst::pex::logging::Trace; namespace pexEx = lsst::pex::exceptions; namespace afwImage = lsst::afw::image; namespace afwMath = lsst::afw::math; namespace afwGeom = lsst::afw::geom; // returns time difference in seconds double DiffTime(clock_t start, clock_t end) { double tm; tm = (double)difftime(end, start); tm = abs(tm); tm /= CLOCKS_PER_SEC; return tm; } //Calculates relative RMSD (coefficient of variation of the root-mean-square deviation) template double CvRmsd(const afwImage::Image& imgA, const afwImage::Image& imgB) { int const dimX = imgA.getWidth(); int const dimY = imgA.getHeight(); if (dimX != imgB.getWidth() || dimY != imgB.getHeight()) return NAN; double sqSum = 0; double avgSum = 0; int cnt = 0; for (int x = 0; x < dimX; x++) { for (int y = 0; y < dimY; y++) { const double valA = imgA(x, y); const double valB = imgB(x, y); if (lsst::utils::isnan(valA) && lsst::utils::isnan(valB)) continue; if (lsst::utils::isinf(valA) && lsst::utils::isinf(valB)) continue; cnt++; avgSum += (valA + valB) / 2; double const diff = valA - valB; sqSum += diff * diff; } } double rmsd = sqrt(sqSum / cnt); double avg = avgSum / cnt; return rmsd / avg; } //Returns number of different values template double DiffCnt(afwImage::Mask const& imgA, afwImage::Mask const& imgB) { typedef long long unsigned int Bitint; int const dimX = imgA.getWidth(); int const dimY = imgA.getHeight(); if (dimX != imgB.getWidth() || dimY != imgB.getHeight()) return NAN; int cnt = 0; for (int x = 0; x < dimX; x++) { for (int y = 0; y < dimY; y++) { const T valA = imgA(x, y); const T valB = imgB(x, y); if (valA != valB) cnt++; } } return cnt; } void PrintSeparator() { for (int i = 0; i < 79; i++) cout << "="; cout << endl; }
139 94f92972 - string GetInputFileName(int argc, char **argv)
? ^^^ ^ ^^
141 a9aec7fc + string GetInputImagePath(int argc, char **argv)
? ^^^^ ^ ^^ {
141 94f92972 - string imgBaseFileName;
143 a9aec7fc + string inImagePath;
if (argc < 2) {
143 94f92972 - string afwdata = getenv("AFWDATA_DIR");
144 94f92972 - if (afwdata.empty()) {
145 a9aec7fc + try {
146 7cbb2bb9 + string dataDir = lsst::utils::getPackageDir("afwdata");
147 a9aec7fc + inImagePath = dataDir + "/data/med.fits";
148 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
145 94f92972 - std::cerr << "Usage: convolveGPU fitsFile" << endl;
? -----
149 a9aec7fc + cerr << "Usage: convolveGPU [fitsFile]" << endl;
? + +
150 a9aec7fc + cerr << "fitsFile is the path to a masked image" << endl;
151 a9aec7fc + cerr << "\nError: setup afwdata or specify fitsFile.\n" << endl;
146 94f92972 - std::cerr << "fitsFile excludes the \"_img.fits\" suffix" << endl;
147 94f92972 - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << endl;
148 94f92972 - std::cerr << "Is afwdata set up?\n" << endl;
exit(EXIT_FAILURE); }
151 94f92972 - else {
152 94f92972 - imgBaseFileName = afwdata + "/data/med";
153 94f92972 - //imgBaseFileName = afwdata + "/data/medsub";
154 94f92972 - //imgBaseFileName = afwdata + "/data/871034p_1_MI";
155 94f92972 - cout << "Using image: " << imgBaseFileName << endl;
156 94f92972 - }
} else {
159 94f92972 - imgBaseFileName = string(argv[1]);
? ^ ^^^^^^^^^^
156 a9aec7fc + inImagePath = string(argv[1]);
? ++ + ^^ ^^ }
161 94f92972 - return imgBaseFileName;
158 a9aec7fc + return inImagePath;
} string Sel(bool b, const char* onTrue, const char* onFalse) { return b ? string(onTrue) : string(onFalse); } string DecimalPlaces(int places, double val) { stringstream ss; ss << fixed << showpoint << setprecision(places) << val; return ss.str(); } template typename T::SinglePixel const GetEdgePixel(T& x) { return afwMath::edgePixel< T >( typename afwImage::detail::image_traits< T >::image_category() ); } template void TimeOneKernelMI( const afwImage::MaskedImage inImg, const afwImage::Wcs::Ptr destWcs, const afwImage::Wcs::Ptr srcWcs, afwMath::WarpingControl wctrlCPU, afwMath::WarpingControl wctrlGPU, int order // redundant, but easier this way ) { afwImage::MaskedImage resMI (inImg.getDimensions()); afwImage::MaskedImage resMIGpu(inImg.getDimensions()); int const sizeRepMax = 1; int const GPUrepMul = 20; int const repCpu = sizeRepMax * 5 / order; int const repGpu = GPUrepMul * sizeRepMax * 5 / order; // warp masked image time_t maskedImgCpuStart = clock(); for (int i = 0; i < repCpu; i++) { warpImage(resMI, *destWcs, inImg, *srcWcs, wctrlCPU); } double maskedImgCpuTime = DiffTime(maskedImgCpuStart, clock()) / repCpu; time_t maskedImgGpuStart = clock(); for (int i = 0; i < repGpu; i++) { warpImage(resMIGpu, *destWcs, inImg, *srcWcs, wctrlGPU); } double maskedImgGpuTime = DiffTime(maskedImgGpuStart, clock()) / repGpu; double diffMIImg = CvRmsd(*resMI.getImage() , *resMIGpu.getImage()); double diffMIVar = CvRmsd(*resMI.getVariance(), *resMIGpu.getVariance()); double diffMIMsk = DiffCnt(*resMI.getMask() , *resMIGpu.getMask()); cout << " " << setw(2) << setfill('0') << order << setfill(' ') << setw(8) << DecimalPlaces(3, maskedImgCpuTime) << " s " << setw(8) << DecimalPlaces(4, maskedImgGpuTime) << " s " << setw(6) << DecimalPlaces(1, maskedImgCpuTime / maskedImgGpuTime) << "x " << setw(16) << diffMIImg << setw(16) << diffMIVar << setw(9) << diffMIMsk << endl; } template void TimeOneKernelPI( const afwImage::Image inImg, int const order, const afwImage::Wcs::Ptr destWcs, const afwImage::Wcs::Ptr srcWcs, int const interpLen ) { const lsst::afw::gpu::DevicePreference selCPU = lsst::afw::gpu::USE_CPU; const lsst::afw::gpu::DevicePreference selGPU = lsst::afw::gpu::AUTO; afwMath::LanczosWarpingKernel lanKernel(order); afwMath::WarpingControl lanCPU( lanKernel, interpLen, selCPU); afwMath::WarpingControl lanGPU( lanKernel, interpLen, selGPU); afwImage::Image resPI (inImg.getDimensions()); afwImage::Image resPIGpu(inImg.getDimensions()); int const sizeRepMax = 1; int const GPUrepMul = 20; int const repCpu = sizeRepMax * 5 / order; int const repGpu = GPUrepMul * sizeRepMax * 5 / order; // warp plain image time_t plainImgCpuStart = clock(); for (int i = 0; i < repCpu; i++) { warpImage(resPI, *destWcs, inImg, *srcWcs, lanCPU); } double plainImgCpuTime = DiffTime(plainImgCpuStart, clock()) / repCpu; time_t plainImgGpuStart = clock(); for (int i = 0; i < repGpu; i++) { warpImage(resPIGpu, *destWcs, inImg, *srcWcs, lanGPU); } double plainImgGpuTime = DiffTime(plainImgGpuStart, clock()) / repGpu; double diffPI = CvRmsd(resPI, resPIGpu); cout << " " << setw(2) << setfill('0') << order << setfill(' '); cout << setw(8) << DecimalPlaces(3, plainImgCpuTime) << " s " ; cout << setw(8) << DecimalPlaces(4, plainImgGpuTime) << " s " ; cout << setw(6) << DecimalPlaces(1, plainImgCpuTime / plainImgGpuTime) << "x " ; cout << setw(16) << diffPI ; cout << endl; } void TestWarpGpu( const afwImage::MaskedImage inImgDbl, const afwImage::MaskedImage inImgFlt ) { const lsst::afw::gpu::DevicePreference selCPU = lsst::afw::gpu::USE_CPU; const lsst::afw::gpu::DevicePreference selGPU = lsst::afw::gpu::AUTO; const afwImage::MaskedImage inMIDbl = inImgDbl; const afwImage::MaskedImage inMIFlt = inImgFlt; int const sizeX = inMIDbl.getWidth(); int const sizeY = inMIDbl.getHeight(); const afwImage::Image inPIDbl = *inMIDbl.getImage(); const afwImage::Image inPIFlt = *inMIFlt.getImage(); cout << "Image size: " << sizeX << " x " << sizeY << endl; Eigen::Matrix2d m1(2, 2); Eigen::Matrix2d m2(2, 2); m1 << 1 , 0, 0, 1; m2 << 0.88 , 0.2, -0.4, 1.12; const afwGeom::Point2D origin(0, 0); afwImage::Wcs wcs1(origin, origin, m1); afwImage::Wcs wcs2(origin, origin, m2); { // do one warp and discard the result // because first warp has to initialize GPU, thus using aditional time afwMath::LanczosWarpingKernel lanKernel(2); afwImage::MaskedImage resGpu(15, 15); afwMath::WarpingControl lanGPU( lanKernel, 40, lsst::afw::gpu::USE_GPU); warpImage(resGpu, wcs1, inImgFlt, wcs2, lanGPU); } cout << endl; cout << " Plain Image, Lanczos kernel" << endl; cout << "Order CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 2; i < 6; i++) { TimeOneKernelPI(inPIFlt, i, wcs1.clone(), wcs2.clone(), defaultInterpLen); } cout << endl; cout << " Plain Image, Lanczos kernel" << endl; cout << "Order CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 2; i < 6; i++) { TimeOneKernelPI(inPIDbl, i, wcs1.clone(), wcs2.clone(), defaultInterpLen); } cout << endl; cout << " Masked Image, Lanczos kernel" << endl; cout << "Order CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 2; i < 6; i++) { afwMath::LanczosWarpingKernel lanKernel(i); afwMath::WarpingControl wctrlCPU( lanKernel, defaultInterpLen, selCPU); afwMath::WarpingControl wctrlGPU( lanKernel, defaultInterpLen, selGPU); TimeOneKernelMI(inMIFlt, wcs1.clone(), wcs2.clone(), wctrlCPU, wctrlGPU, i); } cout << endl; cout << " Masked Image, Lanczos kernel" << endl; cout << "Order CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 2; i < 6; i++) { afwMath::LanczosWarpingKernel lanKernel(i); afwMath::WarpingControl wctrlCPU( lanKernel, defaultInterpLen, selCPU); afwMath::WarpingControl wctrlGPU( lanKernel, defaultInterpLen, selGPU); TimeOneKernelMI(inMIDbl, wcs1.clone(), wcs2.clone(), wctrlCPU, wctrlGPU, i); } cout << endl; cout << " Masked Image, Lanczos kernel, bilinear mask kernel" << endl; cout << "Order CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 2; i < 6; i++) { char kernelNameBuf[30]; sprintf(kernelNameBuf, "lanczos%d",i); afwMath::WarpingControl wctrlCPU( kernelNameBuf, "bilinear", 0, defaultInterpLen, selCPU); afwMath::WarpingControl wctrlGPU( kernelNameBuf, "bilinear", 0, defaultInterpLen, selGPU); TimeOneKernelMI(inMIFlt, wcs1.clone(), wcs2.clone(), wctrlCPU, wctrlGPU, i); } cout << endl; cout << " Masked Image, Lanczos kernel, bilinear mask kernel" << endl; cout << "Order CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 2; i < 6; i++) { char kernelNameBuf[30]; sprintf(kernelNameBuf, "lanczos%d",i); afwMath::WarpingControl wctrlCPU( kernelNameBuf, "bilinear", 0, defaultInterpLen, selCPU); afwMath::WarpingControl wctrlGPU( kernelNameBuf, "bilinear", 0, defaultInterpLen, selGPU); TimeOneKernelMI(inMIDbl, wcs1.clone(), wcs2.clone(), wctrlCPU, wctrlGPU, i); } } void TimeGpu(int argc, char**argv) {
381 94f92972 - string baseFileName = GetInputFileName(argc, argv);
378 a9aec7fc + string inImagePath = GetInputImagePath(argc, argv);
383 94f92972 - const afwImage::MaskedImage inImgFlt(baseFileName);
? ^ ^ ^^^^^ ^^
380 a9aec7fc + const afwImage::MaskedImage inImgFlt(inImagePath);
? ^^^^ ^ ^ ^^
384 94f92972 - const afwImage::MaskedImage inImgDbl(baseFileName);
? ^ ^ ^^^^^ ^^
381 a9aec7fc + const afwImage::MaskedImage inImgDbl(inImagePath);
? ^^^^ ^ ^ ^^ TestWarpGpu(inImgDbl, inImgFlt); } int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (lsst::afw::gpu::isGpuBuild()) { lsst::afw::gpu::detail::PrintCudaDeviceInfo(); } else { cout << "AFW not compiled with GPU support. Exiting." << endl; return EXIT_SUCCESS; } PrintSeparator(); cout << endl; cout << "Note: Dev = coefficient of variation of RMSD" << endl; cout << "Note: Interpolation length set to " << defaultInterpLen << endl; cout << endl; TimeGpu(argc, argv); // Check for memory leaks if (lsst::daf::base::Citizen::census(0) == 0) { cerr << "No leaks detected" << endl; } else { cerr << "Leaked memory blocks:" << endl; lsst::daf::base::Citizen::census(cerr); status = EXIT_FAILURE; } return status; }

Return to list

Commits in /Users/nate/repos_hsc/afw/

94f92972

commit 94f92972a6b166c7f82085fa3b8d38477b19f415
Author: Kresimir Cosic 
Date:   Mon Feb 20 14:12:29 2012 +0100

    Added an example which benchmarks GPU warping

Commits in /Users/nate/repos_lsst/afw/

7cbb2bb9

commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
Author: Russell Owen 
Date:   Tue Apr 28 17:08:34 2015 -0700

    Use lsst.utils.getPackageDir instead of eups.productDir

a9aec7fc

commit a9aec7fccf43933d582b64486479b2a10a861329
Author: Russell Owen 
Date:   Tue Jul 8 11:41:49 2014 -0700

    Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
    
    afw was full of examples of std::string = getenv("AFWDATA_DIR")
    followed by testing for a non-empty string. This doesn't work as expected
    because getenv returns NULL if the environment variable does not exist.
    Fixed by calling eups::productDir("afwdata") and explicitly checking
    for the exception raised if the product is not setup.
    
    Also, most of that code used outdated paths to files in AFWDATA.
    In a few cases files were being read that no longer exist,
    so minor additional changes were needed.

Return to list

python/lsst/afw/geom/Point.i

Diff:

                /* 
                 * LSST Data Management System
                 * Copyright 2008, 2009, 2010 LSST Corporation.
                 * 
                 * This product includes software developed by the
                 * LSST Project (http://www.lsst.org/).
                 *
                 * This program is free software: you can redistribute it and/or modify
                 * it under the terms of the GNU General Public License as published by
                 * the Free Software Foundation, either version 3 of the License, or
                 * (at your option) any later version.
                 * 
                 * This program is distributed in the hope that it will be useful,
                 * but WITHOUT ANY WARRANTY; without even the implied warranty of
                 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                 * GNU General Public License for more details.
                 * 
                 * You should have received a copy of the LSST License Statement and 
                 * the GNU General Public License along with this program.  If not, 
                 * see .
                 */
                 
                
                %{
                #include "lsst/afw/geom/Extent.h"
                #include "lsst/afw/geom/Point.h"
                %}
                
29 747f909d - // This doesn't wrap "scalar OP extent" versions, but that's okay.
%define %Point_PREINCLUDE(T,N) %copyctor lsst::afw::geom::Point; %useValueEquality(lsst::afw::geom::Point)
33 747f909d - %rename(__add__) lsst::afw::geom::Point::operator+;
? -------------
32 4567a4cd + %ignore lsst::afw::geom::Point::operator+;
? ++++
34 747f909d - %rename(__sub__) lsst::afw::geom::Point::operator-;
? -------------
33 4567a4cd + %ignore lsst::afw::geom::Point::operator-;
? ++++
35 747f909d - %rename(__iadd__) lsst::afw::geom::Point::operator+=;
? --------------
34 4567a4cd + %ignore lsst::afw::geom::Point::operator+=;
? ++++
36 747f909d - %rename(__isub__) lsst::afw::geom::Point::operator-=;
? --------------
35 4567a4cd + %ignore lsst::afw::geom::Point::operator-=;
? ++++ %enddef %define %Point_POSTINCLUDE(T,N,SUFFIX) %template(PointCoordinateBase ## N ## SUFFIX) lsst::afw::geom::CoordinateBase,T,N>; %template(PointBase ## N ## SUFFIX) lsst::afw::geom::PointBase; %template(Point ## N ## SUFFIX) lsst::afw::geom::Point; %CoordinateBase_POSTINCLUDE(T, N, lsst::afw::geom::Point);
43 4567a4cd + %extend lsst::afw::geom::Point {
44 4567a4cd + lsst::afw::geom::Extent __sub__(lsst::afw::geom::Point const & other) const {
45 4567a4cd + return *self - other;
46 4567a4cd + }
47 4567a4cd + lsst::afw::geom::Point __add__(lsst::afw::geom::Extent const & other) const {
48 4567a4cd + return *self + other;
49 4567a4cd + }
50 4567a4cd + lsst::afw::geom::Point __sub__(lsst::afw::geom::Extent const & other) const {
51 4567a4cd + return *self - other;
52 4567a4cd + }
53 4567a4cd + PyObject * __iadd__(PyObject** PYTHON_SELF, lsst::afw::geom::Extent const & other) {
54 4567a4cd + *self += other;
55 4567a4cd + Py_INCREF(*PYTHON_SELF);
56 4567a4cd + return *PYTHON_SELF;
57 4567a4cd + }
58 4567a4cd + PyObject * __isub__(PyObject** PYTHON_SELF, lsst::afw::geom::Extent const & other) {
59 4567a4cd + *self -= other;
60 4567a4cd + Py_INCREF(*PYTHON_SELF);
61 4567a4cd + return *PYTHON_SELF;
62 4567a4cd + }
63 4567a4cd + }
%enddef
65 4567a4cd +
66 4567a4cd + %define %PointD_POSTINCLUDE(N)
67 4567a4cd + %Point_POSTINCLUDE(double,N,D)
68 4567a4cd + %extend lsst::afw::geom::Point {
69 4567a4cd + lsst::afw::geom::Point __add__(lsst::afw::geom::Extent const & other) const {
70 4567a4cd + return *self + other;
71 4567a4cd + }
72 4567a4cd + PyObject * __iadd__(PyObject** PYTHON_SELF, lsst::afw::geom::Extent const & other) {
73 4567a4cd + *self += other;
74 4567a4cd + Py_INCREF(*PYTHON_SELF);
75 4567a4cd + return *PYTHON_SELF;
76 4567a4cd + }
77 4567a4cd + lsst::afw::geom::Point __sub__(lsst::afw::geom::Extent const & other) const {
78 4567a4cd + return *self - other;
79 4567a4cd + }
80 4567a4cd + PyObject * __isub__(PyObject** PYTHON_SELF, lsst::afw::geom::Extent const & other) {
81 4567a4cd + *self -= other;
82 4567a4cd + Py_INCREF(*PYTHON_SELF);
83 4567a4cd + return *PYTHON_SELF;
84 4567a4cd + }
85 4567a4cd + lsst::afw::geom::Extent __sub__(lsst::afw::geom::Point const & other) const {
86 4567a4cd + return *self - other;
87 4567a4cd + }
88 4567a4cd + }
89 4567a4cd + %enddef
90 4567a4cd +
91 4567a4cd + %define %PointI_POSTINCLUDE(N)
92 4567a4cd + %Point_POSTINCLUDE(int,N,I)
93 4567a4cd + %extend lsst::afw::geom::Point {
94 4567a4cd + lsst::afw::geom::Point __add__(lsst::afw::geom::Extent const & other) const {
95 4567a4cd + return *self + other;
96 4567a4cd + }
97 4567a4cd + lsst::afw::geom::Point __sub__(lsst::afw::geom::Extent const & other) const {
98 4567a4cd + return *self - other;
99 4567a4cd + }
100 4567a4cd + lsst::afw::geom::Extent __sub__(lsst::afw::geom::Point const & other) const {
101 4567a4cd + return *self - other;
102 4567a4cd + }
103 4567a4cd + }
104 25e61ab4 + %enddef

Return to list

Commits in /Users/nate/repos_hsc/afw/

747f909d

commit 747f909d1d90b2597c9daf7151f661639cf63a71
Author: jbosch 
Date:   Thu Dec 17 03:45:00 2009 +0000

    afw/#892 - swig wrappers for Point and Extent

Commits in /Users/nate/repos_lsst/afw/

25e61ab4

commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
Author: jbosch 
Date:   Sun Jan 30 22:19:38 2011 +0000

    afw #1556 - implemented ticket #1240: direct construction of Point and Extent

4567a4cd

commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
Author: Jim Bosch 
Date:   Fri Apr 3 17:47:06 2015 -0400

    Support for mixed-type operations in Point and Extent
    
    This adds mixed-type operators for Point and Extent, as well as new
    floor, ceil, and truncate functions for Extent, to help deal with some
    unfortunate differences between C++ and Python in how division
    is expected to behave for integers.

Return to list

doc/imageDisplay.dox

Diff:

                namespace lsst { namespace afw { namespace image {
                /**
3 17f8580b - \page afwSecDisplay How to %display images
? -
3 bde0ab27 + \page afwSecDisplay How to display images
\section afwSecDisplay How to display images
6 bde0ab27 + - \ref afwSecImageDisplay
7 bde0ab27 + - \ref afwSecImageTypes
8 bde0ab27 + - \ref afwSecImageDisplayConfiguration
6 17f8580b - - \ref afwSecDs9Mosaics
? ^
9 bde0ab27 + - \ref afwSecImageDisplayMosaics
? +++++ + ^^^^
7 17f8580b - - \ref afwSecDs9Commands
- \ref afwSecDs9Firewall
10 17f8580b - \section afwSecDs9 Using DS9 in the LSST framework
12 bde0ab27 + \section afwSecImageDisplay Displaying images in the LSST framework
12 58dff8e1 - At present (July 2009) we are using ds9 (http://hea-www.harvard.edu/RD/ds9) to %display
13 58dff8e1 - Image%s, Mask%s, and MaskedImage%s. This has a number of drawbacks (slow; slightly
14 58dff8e1 - unstable API; awkward to use with firewalls) as well as a number of advantages: Supported
15 58dff8e1 - by the CfA; ubiquitous in astronomy; support for WCS; support for multiple frames).
14 bde0ab27 + In April 2015 we restructured the image display code to be backend agnostic, while still only supporting a
15 bde0ab27 + virtualDevice (which does nothing), and ds9 (http://hea-www.harvard.edu/RD/ds9) for the present. At
16 bde0ab27 + the same time we made the interface object oriented --- opening a display returns an object (the old
17 bde0ab27 + functional interface with a frame argument is supported for backward compatibility).
19 bde0ab27 + Although ds9 has a number of drawbacks (slow; slightly unstable API; awkward to use with firewalls) it
20 bde0ab27 + also as a number of advantages: Supported by the CfA; ubiquitous in astronomy; support for WCS; support
21 bde0ab27 + for multiple frames.
22 bde0ab27 +
17 58dff8e1 - The basic functionality is in \c lsst.afw.display.ds9, and the workhorse routine
? ----
23 bde0ab27 + The basic functionality is in \c lsst.afw.display, and the workhorse routine
18 88e1be34 - is \c mtv. The simplest use is simply to setup afw and ds9, start ds9 and python, and type:
? ---- - ------------
24 bde0ab27 + is \c mtv. The simplest use is simply to setup afw and display_ds9, start ds9 (you may have to
? ++++++++ ++++++ ++++++
25 bde0ab27 + install it yourself) and python, and type:
\code
20 58dff8e1 - import lsst.afw.display.ds9 as ds9
? ---- ^ ^
27 bde0ab27 + import lsst.afw.display as afwDisplay
? ^^^^^ ^^^^ import lsst.afw.image as afwImage im = afwImage.ImageF("myFile.fits")
31 bde0ab27 +
32 bde0ab27 + disp = afwDisplay.getDisplay()
24 58dff8e1 - ds9.mtv(im)
? ^
33 bde0ab27 + disp.mtv(im)
? + ^
34 bde0ab27 + \endcode
35 bde0ab27 + Rather than saving \c disp in a variable, you can say
25 58dff8e1 - \endcode
? ---
36 bde0ab27 + \code
37 bde0ab27 + afwDisplay.getDisplay().mtv(im)
38 bde0ab27 + \endcode
39 bde0ab27 + and if the display doesn't exist it'll be created for you. You can say e.g.
40 bde0ab27 + \code
41 bde0ab27 + disp = afwDisplay.getDisplay(2, "virtualDisplay")
42 58dff8e1 + \endcode
43 bde0ab27 + to create a rather useless display named "2" using the do-nothing \c virtualDisplay device;
44 bde0ab27 + you're more likely to specify \c "ds9" or (soon) \c "firefly".
You can %display images in multiple frames, either by explicitly specifying the
28 88e1be34 - frame, or by setting the default with \c ds9.setDefaultFrame(). If there's a
? ^ ^ ^^^^^^^^^
47 bde0ab27 + frame, or by setting the default with \c afwDisplay.setDefaultFrame(). If you
? ^^^^^ ^^^^ ^^^
48 bde0ab27 + are using the ds9 backend and there's a
strong desire for multiple instances of ds9 this could be supported (by choosing
30 88e1be34 - different tcp ports); file a ticket if this is really important for you.
50 bde0ab27 + different tcp ports); file a ticket if this is really important for you. ds9 uses integers as its `frame'
? ++++++++++++++++++++++++++++++++++
51 bde0ab27 + identifiers, but other display devices may use other types (e.g. strings).
52 bde0ab27 +
53 bde0ab27 + See the manual at \ref lsst.afw.display.interface.Display for all the supported commands, and the iPython
54 bde0ab27 + notebook at \ref examples/imageDisplay.ipynb for examples (we'll provide an nbviewer link once this is
55 bde0ab27 + pushed to github).
56 bde0ab27 +
57 bde0ab27 + Whenever you're writing more than a few glyphs
58 bde0ab27 + we \em strongly recommend that you turn on buffering (it's certainly necessary when you're using the
59 bde0ab27 + ds9 backend). The simplest way to do this is by using python's
60 bde0ab27 + \c with statement:
61 bde0ab27 + \code
62 bde0ab27 + with disp.Buffering():
63 bde0ab27 + for source in sourceList:
64 bde0ab27 + disp.dot("o", source.getXAstrom(), source.getYAstrom())
65 bde0ab27 + \endcode
66 bde0ab27 + You can explicitly flush the buffer at anytime with \c disp.flush()
67 bde0ab27 +
68 bde0ab27 + \subsection afwSecImageTypes How afwDisplay handles different Image types
The \c mtv command handles all of the LSST %image types:
Image
35 88e1be34 -
The pixels are displayed on ds9. Image%s don't have a Wcs, so no ? ^
73 bde0ab27 +
The pixels are displayed on your image display. Image%s don't have a Wcs, so no ? +++++++++++ + ^^^^ astronomical WCS information is available, but we do support \c WCSA and \c WCSB; the former is 0-indexed %pixel coordinates allowing for the Image's \c XY0; the latter is 0-indexed %pixel coordinates relative to the bottom left %pixel being \c (0, \c 0). \c mtv accepts an optional \c wcs argument, which allows you to provide an astronomical Wcs (but if you have an DecoratedImage or Exposure this is done for you)
DecoratedImage
Displayed like Image, but with the default WCS set from the DecoratedImage's \c Wcs
Mask
47 88e1be34 -
Overlay the current %display with the Mask. A bug in ds9 prevents you from displaying a pure Mask,
85 bde0ab27 +
Overlay the current %display with the Mask.
86 88e1be34 +
87 bde0ab27 + If you're using the ds9 backend there's a bug that
88 bde0ab27 + prevents you from displaying a pure Mask,
but you can use the \c isMask argument to force the Mask to be treated as a 16-bit %image.
49 88e1be34 -
50 88e1be34 - The Mask %display isn't as fast as you might like,
? ^
90 bde0ab27 + Also, the Mask %display isn't as fast as you might like,
? ^^^^^^^ as ds9's current API requires us to send each mask plane as a separate 16-bit %image (I have asked Bill Joy at CfA to change this). Each bitplane may be given a separate colour; you can inspect the current mapping with \c getMaskPlaneColor or set it with \c setMaskPlaneColor. If a mask plane has no defined colour, one will be chosen for you.
57 88e1be34 - Recent versions of ds9 allow you to vary the mask's transparency, either via the GUI or
? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^
97 bde0ab27 + You may vary the mask's transparency, either via the GUI or
? ^ ^^^ with e.g. \c setMaskTransparency(50).
MaskedImage
The image-plane pixels are displayed, overlaid with the mask. If you want to look at the variance too, you'll need to say something like: \code mi = afwImage.MaskedImageF("mi.fits")
65 88e1be34 - ds9.mtv(mi, frame=0)
66 88e1be34 - ds9.mtv(mi.getVariance(), frame=1)
67 88e1be34 - ds9.mtv(mi.getMask(), frame=1)
105 bde0ab27 + disp.mtv(mi)
106 bde0ab27 +
107 bde0ab27 + afwDisplay.getDisplay(1).mtv(mi.getVariance())
108 bde0ab27 + afwDisplay.getDisplay(1).mtv(mi.getMask())
\endcode
Exposure
Displayed like MaskedImage, but with the default WCS set from the MaskedImage's \c Wcs
115 bde0ab27 + \subsubsection afwSecImageDisplayConfiguration How to Configure the Display Device
116 bde0ab27 +
117 bde0ab27 + You won't need to configure the display code at all if you're happy with ds9, as it is
118 bde0ab27 + the default-default backend when available (\em i.e. if you have display_ds9 setup).
119 bde0ab27 +
120 bde0ab27 + At some point we may add a configuration mechanism using environment variables and/or dot files,
121 bde0ab27 + but for the present the recommended way to set your preferred display environment is by using
122 bde0ab27 + python's startup file. \em E.g. if you have the environment variable $PYTHONSTARTUP set to \c ~/.pythonrc,
123 bde0ab27 + you'd edit \c ~.pythonrc to say something like:
124 bde0ab27 + \code
125 bde0ab27 + try:
126 bde0ab27 + import lsst.afw.display as afwDisplay
127 bde0ab27 + except ImportError:
128 bde0ab27 + afwDisplay = None
129 bde0ab27 +
130 bde0ab27 + if afwDisplay:
131 bde0ab27 + try:
132 bde0ab27 + afwDisplay.setDefaultBackend("myDevice") # or "ds9"
133 bde0ab27 + except RuntimeError as e:
134 bde0ab27 + print e
135 bde0ab27 +
136 bde0ab27 + afwDisplay.setDefaultMaskTransparency(75)
137 bde0ab27 + \endcode
138 58dff8e1 +
74 17f8580b - \subsection afwSecDs9Mosaics How to build a mosaic image
? ^
139 bde0ab27 + \subsection afwSecImageDisplayMosaics How to build a mosaic image
? +++++ + ^^^^
76 58dff8e1 - There are facilities to build mosaics of %images in \c lsst.afw.display.utils
141 bde0ab27 + There are facilities to build mosaics of %images in \c lsst.afw.display.utils (n.b. these
? ++++++++++++
142 bde0ab27 + are mosaics in the sense of a tiled floor; we're not building astrophysical mosaics
143 bde0ab27 + projected on the sky.)
The basic class is \c Mosaic: \code m = Mosaic() m.setGutter(5) m.setBackground(10) m.setMode("square") # the default mosaic = m.makeMosaic(im1, im2, im3) # build the mosaic
153 bde0ab27 + display = afwDisplay.getDisplay()
86 88e1be34 - ds9.mtv(mosaic) # display it
? ^
154 bde0ab27 + display.mtv(mosaic) # display it
? + ^^^^
87 88e1be34 - m.drawLabels(["Label 1", "Label 2", "Label 3"]) # label the panels
155 bde0ab27 + m.drawLabels(["Label 1", "Label 2", "Label 3"], display) # label the panels
? +++++++++ # alternative way to build a mosaic images = [im1, im2, im3] labels = ["Label 1", "Label 2", "Label 3"] mosaic = m.makeMosaic(images)
94 88e1be34 - ds9.mtv(mosaic)
? ^
162 bde0ab27 + display.mtv(mosaic)
? + ^^^^
95 88e1be34 - m.drawLabels(labels)
163 bde0ab27 + m.drawLabels(labels, display)
? +++++++++ # Yet another way to build a mosaic (no need to build the images/labels lists) for i in range(len(images)): m.append(images[i], labels[i]) mosaic = m.makeMosaic()
102 88e1be34 - ds9.mtv(mosaic)
? ^
170 bde0ab27 + display.mtv(mosaic)
? + ^^^^
103 88e1be34 - m.drawLabels()
171 bde0ab27 + m.drawLabels(display=display)
\endcode You can return the (ix, iy)th (or nth) bounding box with getBBox()
175 bde0ab27 + See \ref lsst.afw.display.utils.Mosaic for more details; there are examples near the end of the iPython
176 bde0ab27 + notebook at \ref examples/imageDisplay.ipynb (we'll provide an nbviewer link once this is pushed to github).
107 88e1be34 -
  • The Mosaic class API
108 58dff8e1 -
109 58dff8e1 -
110 58dff8e1 -
__init__() [self, gutter=3, background=0, mode='square']
111 58dff8e1 -
112 58dff8e1 -
113 88e1be34 -
append() [self, %image, label=None]
114 88e1be34 -
115 88e1be34 - Add an %image to the list of images to be mosaiced
116 88e1be34 - Set may be cleared with Mosaic.reset()
117 88e1be34 -
118 88e1be34 -
drawLabels() [self, labels=None, frame=0]
119 88e1be34 -
120 88e1be34 - Draw the list labels at the corners of each panel. If labels is None, use the ones
121 88e1be34 - specified by Mosaic.append()
122 88e1be34 -
123 58dff8e1 -
drawLabels() [self, labels, frame=0]
124 58dff8e1 -
125 58dff8e1 - Draw the list labels at the corners of each panel
126 58dff8e1 -
127 58dff8e1 -
getBBox() [self, ix, iy=None]
128 58dff8e1 -
129 88e1be34 - Get the bounding box for the nth or (ix, iy)the panel
130 58dff8e1 -
131 58dff8e1 -
makeMosaic() [self, images, frame=None, mode=None]
132 58dff8e1 -
133 88e1be34 - Return a mosaic of all the images provided; if none are specified,
134 88e1be34 - use the list accumulated with Mosaic.append()
135 88e1be34 -
136 88e1be34 - If frame is specified, %display it
137 58dff8e1 -
138 58dff8e1 -
setBackground() [self, background]
139 58dff8e1 -
140 58dff8e1 - Set the value in the gutters
141 58dff8e1 -
142 58dff8e1 -
setGutter() [self, gutter]
143 58dff8e1 -
144 58dff8e1 - Set the number of pixels between panels in a mosaic
145 58dff8e1 -
146 58dff8e1 -
setMode() [self, mode]
147 58dff8e1 -
148 58dff8e1 - Set mosaicing mode. Valid options:
149 58dff8e1 -
150 58dff8e1 -
151 58dff8e1 -
152 58dff8e1 -
153 58dff8e1 -
squareMake mosaic as square as possible
x Make mosaic one %image high
y Make mosaic one %image wide
154 88e1be34 -
155 58dff8e1 -
156 17f8580b - \subsection afwSecDs9Commands All supported ds9 commands
157 58dff8e1 -
158 58dff8e1 -
    159 58dff8e1 -
  • %Image commands
  • 160 58dff8e1 -
    161 530d6f97 - It turns out that writing symbols to ds9 is very slow. Whenever you're writing more than a few glyphs
    162 530d6f97 - we \em strongly recommend that you turn on buffering. The simplest way to do this is by using python's
    163 530d6f97 - \c with statement:
    164 530d6f97 - \code
    165 530d6f97 - with ds9.Buffering():
    166 530d6f97 - for source in sourceList:
    167 530d6f97 - if display:
    168 530d6f97 - ds9.dot("o", source.getXAstrom(), source.getYAstrom())
    169 530d6f97 - \endcode
    170 530d6f97 - (note that \c ds9.Buffering() is safe even if no \c ds9 display is available). You can explicitly
    171 530d6f97 - flush the buffer at anytime with \c ds9.flush()
    172 530d6f97 -
    173 58dff8e1 -
    174 58dff8e1 -
    erase() [frame=-1]
    175 58dff8e1 -
    176 58dff8e1 - Erase the specified DS9 frame
    177 58dff8e1 -
    178 530d6f97 -
    flush() []
    179 530d6f97 -
    180 530d6f97 - Draw all pending glyphs; you shouldn't usually need to use this.
    181 530d6f97 -
    182 58dff8e1 -
    mtv() [data, frame=-1, init=True, wcs=None, isMask=False, lowOrderBits=False, title=None]
    183 58dff8e1 -
    184 88e1be34 - Display an Image or Mask on a DS9 %display
    185 58dff8e1 -
    186 88e1be34 - If lowOrderBits is True, give low-order-bits priority in %display (i.e.
    187 58dff8e1 - overlay them last)
    188 58dff8e1 -
    189 58dff8e1 - Historical note: the name "mtv" comes from Jim Gunn's forth imageprocessing
    190 58dff8e1 - system, Mirella (named after Mirella Freni); The "m" stands for Mirella.
    191 58dff8e1 -
    192 58dff8e1 -
    pan() [colc=None, rowc=None, frame=-1]
    193 58dff8e1 -
    194 58dff8e1 - Pan to (rowc, colc); see also zoom
    195 58dff8e1 -
    196 58dff8e1 -
    setDefaultFrame() [frame]
    197 58dff8e1 -
    198 58dff8e1 - Set the default frame for ds9
    199 58dff8e1 -
    200 58dff8e1 -
    setMaskColor() [color=GREEN]
    201 58dff8e1 -
    202 58dff8e1 - Set the ds9 mask colour to; eg. ds9.setMaskColor(ds9.RED)
    203 58dff8e1 -
    204 58dff8e1 -
    setMaskPlaneColor() [name, color=None]
    205 58dff8e1 -
    206 58dff8e1 - Request that mask plane name be displayed as color; name may be a dictionary
    207 58dff8e1 - (in which case color should be omitted
    208 58dff8e1 -
    209 58dff8e1 -
    setMaskPlaneVisibility() [name, show=True]
    210 58dff8e1 -
    211 58dff8e1 - Specify the visibility of a given mask plane; name may be a dictionary (in which case show w
    212 58dff8e1 - ill be ignored)
    213 58dff8e1 -
    214 58dff8e1 -
    setMaskTransparency() [transparency=None]
    215 58dff8e1 -
    216 58dff8e1 - Specify ds9's mask transparency (percent); or None to not set it when loading masks
    217 58dff8e1 -
    218 58dff8e1 -
    show() [frame=-1]
    219 58dff8e1 -
    220 58dff8e1 - Uniconify and Raise ds9. N.b. throws an exception if frame doesn't exit
    221 58dff8e1 -
    222 58dff8e1 -
    zoom() [zoomfac=None, colc=None, rowc=None, frame=-1]
    223 58dff8e1 -
    224 58dff8e1 - Zoom frame by specified amount, optionally panning also
    225 58dff8e1 -
    226 58dff8e1 -
    227 58dff8e1 -
  • Graphics commands
  • 228 58dff8e1 -
    229 58dff8e1 -
    230 58dff8e1 -
    dot() [symb, c, r, frame=-1, size=2, ctype=GREEN]
    231 58dff8e1 -
    232 58dff8e1 - Draw a symbol onto the specified DS9 frame at (col,row) = (c,r) [0-based coordinates]
    233 58dff8e1 - Possible values are:
    234 58dff8e1 -
    235 58dff8e1 -
    236 58dff8e1 -
    237 58dff8e1 -
    238 58dff8e1 -
    239 58dff8e1 -
    +Draw a +
    xDraw an x
    oDraw a circle
    @:Mxx,Mxy,MyyDraw an ellipse with moments (Mxx, Mxy, Myy) (size is ignored)
    240 58dff8e1 - Any other value is interpreted as a string to be drawn
    241 58dff8e1 -
    242 58dff8e1 -
    line() [points, frame=-1, symbs=False, ctype=GREEN]
    243 58dff8e1 -
    244 58dff8e1 - Draw a set of symbols or connect the points, a list of (col,row)
    245 58dff8e1 - If symbs is True, draw points at the specified points using the desired symbol,
    246 58dff8e1 - otherwise connect the dots. Ctype is the name of a colour (e.g. ds9.RED)
    247 58dff8e1 -
    248 58dff8e1 -
    249 58dff8e1 -
  • Internal commands that you shouldn't need to know
  • 250 58dff8e1 -
    251 58dff8e1 -
    252 58dff8e1 -
    Ds9Error
    253 58dff8e1 -
    Exception thrown if there's some problem talking to ds9
    254 58dff8e1 -
    255 58dff8e1 -
    ds9Cmd() [cmd, trap=True]
    256 58dff8e1 -
    257 58dff8e1 - Issue a ds9 command, raising errors as appropriate
    258 58dff8e1 -
    259 58dff8e1 -
    getDefaultFrame()
    260 58dff8e1 -
    261 58dff8e1 - Get the default frame for ds9
    262 58dff8e1 -
    263 58dff8e1 -
    getMaskPlaneColor() [name]
    264 58dff8e1 -
    265 58dff8e1 - Return the colour associated with the specified mask plane name
    266 58dff8e1 -
    267 58dff8e1 -
    getMaskPlaneVisibility() [name]
    268 58dff8e1 -
    269 88e1be34 - Should we %display the specified mask plane name?
    270 58dff8e1 -
    271 58dff8e1 -
    getMaskTransparency()
    272 58dff8e1 -
    273 58dff8e1 - Return ds9's mask transparency
    274 58dff8e1 -
    275 58dff8e1 -
    getXpaAccessPoint()
    276 58dff8e1 -
    277 58dff8e1 - Parse XPA_PORT and send return an identifier to send ds9 commands there, instead of "ds9"
    278 58dff8e1 - If you don't have XPA_PORT set, the usual xpans tricks will be played when we return "ds9".
    279 58dff8e1 -
    280 58dff8e1 -
    initDS9() [execDs9=True]
    281 58dff8e1 -
    282 58dff8e1 -
    283 58dff8e1 -
    284 58dff8e1 -
    285 58dff8e1 - Colours may be specified as any X11-compliant string (e.g. "orchid"), or by one
    286 58dff8e1 - of the following constants defined in \c ds9; the advantage of the latter
    287 58dff8e1 - approach is that the python interpreter can detect typos: \c BLACK, \c WHITE, \c RED, \c BLUE,
    288 58dff8e1 - \c GREEN, \c CYAN, \c MAGENTA, \c YELLOW.
    \subsection afwSecDs9Firewall How to use ds9 through a firewall
    179 58dff8e1 +
    180 bde0ab27 + If you're using ds9 you may want to use it through a firewall; here's how.
    On your home machine, type \code export XPA_PORT="DS9:ds9 22345 22346" # ^^^^^ ^^^^^ # Choose any 2 consecutive numbers over 4095 ssh -N -f lsstXXX.ncsa.uiuc.edu -R 22345:localhost:22345 -R 22346:localhost:22346 > /dev/null 2>&1 ds9 & \endcode (setenv XPA_PORT "DS9:ds9 22345 22346" for csh users, of course)
    302 58dff8e1 - On \c lsstXXX.ncsa.uiuc.edu, set \c XPA_PORT to the same value, start \c python,
    ? ^^^ ^^^
    192 bde0ab27 + On \c lsstXXX.ncsa.uiuc.edu, set \c XPA_PORT to the same value, setup \c display_ds9 and \c afw,
    ? + ^^ +++ ++ ^^^^^^ ++++++++
    303 58dff8e1 - import lsst.afw.display.ds9 and proceed:
    193 bde0ab27 + start \c python, import lsst.afw.display as afwDisplay and proceed:
    \code export XPA_PORT="DS9:ds9 22345 22346" python
    307 58dff8e1 - >>> import lsst.afw.display.ds9 as ds9
    ? ---- ^ ^
    197 bde0ab27 + >>> import lsst.afw.display as afwDisplay
    ? ^^^^^ ^^^^
    308 58dff8e1 - >>> ds9.erase()
    198 bde0ab27 + >>> afwDisplay.setBackend("ds9") # the default, so probably not needed
    199 bde0ab27 + >>> afwDisplay.getDisplay().erase()
    \endcode xpa afficianados will note that I'm bypassing the xpa name server; it needs another set of 2 or 3 ports tunnelled, and setting up ACLs.
    314 58dff8e1 - Here's \link tunnelDs9 a script\endlink (in \c afw/examples) to run on your home machine that should simplify setting
    ? -----------------
    205 bde0ab27 + Here's \link tunnelDs9 a script\endlink (in \c afw/examples) to run on your home machine that should
    315 58dff8e1 - up/tearing down the ssh tunnels. It's not great, so improvements would/will be welcomed.
    206 bde0ab27 + simplify setting up/tearing down the ssh tunnels. It's not great, so improvements would/will be welcomed.
    ? +++++++++++++++++ \example tunnelDs9 */ }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    88e1be34

    commit 88e1be348cabf5df13c47b5be62af4f66992e650
    Author: rhl 
    Date:   Fri Jul 10 19:29:01 2009 +0000
    
        Added more details
    

    530d6f97

    commit 530d6f975c6d7a2c00b023dfb142012b8360f04d
    Author: Robert Lupton the Good 
    Date:   Thu Feb 16 10:17:34 2012 -0500
    
        Noted ds9.Buffering()
    

    58dff8e1

    commit 58dff8e1c03c168dfb1b68e8e37996f59a2e6d47
    Author: rhl 
    Date:   Fri Jul 3 20:25:19 2009 +0000
    
        Worked on doxygenation for Rebel Day
    

    17f8580b

    commit 17f8580bd70bca38fc2eda8e893b7904936cb09f
    Author: rowen 
    Date:   Thu Oct 27 23:51:34 2011 +0000
    
        Prepended afw to all section names to avoid global conflicts
    

    Commits in /Users/nate/repos_lsst/afw/

    88e1be34

    commit 88e1be348cabf5df13c47b5be62af4f66992e650
    Author: rhl 
    Date:   Fri Jul 10 19:29:01 2009 +0000
    
        Added more details
    

    bde0ab27

    commit bde0ab27a9add858f810563213c1424f9e63ddde
    Author: Robert Lupton the Good 
    Date:   Sun Apr 12 16:00:47 2015 -0300
    
        Implement RFC-42
        
        N.b. that you need display_ds9 to use the ds9 backend
        N.b. support frame only in cameraGeom.utils top-level routine, showCamera
    

    58dff8e1

    commit 58dff8e1c03c168dfb1b68e8e37996f59a2e6d47
    Author: rhl 
    Date:   Fri Jul 3 20:25:19 2009 +0000
    
        Worked on doxygenation for Rebel Day
    

    Return to list

    python/lsst/afw/geom/Span.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    %{
                    #include "lsst/afw/geom/Span.h"
                    %}
                    %shared_ptr(lsst::afw::geom::Span);
                    
                    %warnfilter(509) lsst::afw::geom::Span;
                    
                    %include "lsst/afw/geom/Span.h"
                    
                    %ignore lsst::afw::geom::Span::begin;
                    %ignore lsst::afw::geom::Span::end;
                    
    
    37 42f4fa50 - %include "std_vector.i"
    38 42f4fa50 - // We don't actually need this vector, but we do need SWIG to generate
    39 42f4fa50 - // the traits classes needed to support iterators that yield points.
    40 42f4fa50 - // Presumably there's a more minimal way to do that, but it's the
    41 42f4fa50 - // opposite of well-documented.
    42 42f4fa50 - %template(Point2IVector) std::vector;
    43 42f4fa50 -
    %newobject lsst::afw::geom::Span::__iter__; %extend lsst::afw::geom::Span { %fragment("SwigPyIterator_T"); // This is the same recipe used to support the STL iterators in SWIG. swig::SwigPyIterator * __iter__(PyObject **PYTHON_SELF) { return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); }
    54 ca29c88b - %pythoncode {
    47 81c3bd10 + %pythoncode %{
    ? + def __len__(self): return self.getWidth() def __str__(self): """Print this Span""" return self.toString()
    60 ca29c88b - }
    53 81c3bd10 + %}
    ? + }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ca29c88b

    commit ca29c88b92eb9ddf614f44da6dee2d2466ddc6cc
    Author: Jim Bosch 
    Date:   Fri Nov 2 14:44:39 2012 -0400
    
        Move Span Python bindings to afw::geom.
    

    42f4fa50

    commit 42f4fa50d4c8033601b60365ea006020249e23b3
    Author: Jim Bosch 
    Date:   Tue Nov 6 16:14:29 2012 -0500
    
        swig-fu to make Span iterable in Python
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    src/image/TanWcs.cc

    Diff:

                    // -*- lsst-c++ -*-
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/format.hpp"
                    
                    #include "wcslib/wcs.h"
                    #include "wcslib/wcsfix.h"
                    #include "wcslib/wcshdr.h"
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/afw/formatters/Utils.h"
                    #include "lsst/afw/formatters/TanWcsFormatter.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Log.h"
                    #include "lsst/afw/geom/AffineTransform.h"
                    #include "lsst/afw/image/TanWcs.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/table/io/InputArchive.h"
                    #include "lsst/afw/table/io/CatalogVector.h"
                    
                    namespace lsst { namespace afw { namespace image {
                    
                    const int lsstToFitsPixels = +1;
                    const int fitsToLsstPixels = -1;
                    
                    TanWcs::TanWcs() :
                        Wcs(),
                        _hasDistortion(false),
                        _sipA(), _sipB(), _sipAp(), _sipBp()
                    {}
                    
                    geom::Angle TanWcs::pixelScale() const {
                        // HACK -- assume "CD" elements are set (and are in degrees)
                        double* cd = _wcsInfo->m_cd;
                        assert(cd);
                        return sqrt(fabs(cd[0]*cd[3] - cd[1]*cd[2])) * geom::degrees;
                    }
                    
                    TanWcs::TanWcs(CONST_PTR(daf::base::PropertySet) const& fitsMetadata) :
                        Wcs(fitsMetadata),
                        _hasDistortion(false),
                        _sipA(), _sipB(), _sipAp(), _sipBp() {
                    
                        //Internal params for wcslib. These should be set via policy - but for the moment...
                        _relax = 1;
                        _wcsfixCtrl = 2;
                        _wcshdrCtrl = 2;
                    
                        //Check that the header isn't empty
                        if(fitsMetadata->nameCount() == 0) {
                            std::string msg = "Fits metadata contains no cards";
    
    78 473b834b - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException, msg);
    ? ^^^^^^ ^
    78 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, msg);
    ? ^^ ^ } //Check for tangent plane projection std::string ctype1 = fitsMetadata->getAsString("CTYPE1"); std::string ctype2 = fitsMetadata->getAsString("CTYPE2"); if((ctype1.substr(5, 3) != "TAN") || (ctype2.substr(5, 3) != "TAN") ) { std::string msg = "One or more axes isn't in TAN projection (ctype1 = \"" + ctype1 + "\", ctype2 = \"" + ctype2 + "\")";
    87 473b834b - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException, msg);
    ? ^^^^^^ ^
    87 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, msg);
    ? ^^ ^ } //Check for distorton terms. With two ctypes, there are 4 alternatives, only //two of which are valid.. Both have distortion terms or both don't. int nSip = (((ctype1.substr(8, 4) == "-SIP") ? 1 : 0) + ((ctype2.substr(8, 4) == "-SIP") ? 1 : 0)); bool isTpv = false; { std::string key = "TPV_WCS"; if (fitsMetadata->exists(key) && fitsMetadata->getAsBool(key)) { isTpv = true; } } if (isTpv) { pex::logging::Log log = pex::logging::Log(pex::logging::Log::getDefaultLog(), "lsst.afw.wcs"); log.log(-1, "Ignoring TPV terms"); } switch (nSip) { case 0: _hasDistortion = false; break; case 1: {//Invalid case. Throw an exception std::string msg = "Distortion key found for only one CTYPE";
    116 473b834b - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException, msg);
    ? ^^^^^^ ^
    116 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, msg);
    ? ^^ ^ } break; //Not necessary, but looks naked without it. case 2: _hasDistortion = true; //Hide the distortion from wcslib //Make a copy that we can hack up PTR(daf::base::PropertySet) const& hackMetadata = fitsMetadata->deepCopy(); hackMetadata->set("CTYPE1", ctype1.substr(0,8)); hackMetadata->set("CTYPE2", ctype2.substr(0,8)); //Save SIP information decodeSipHeader(*hackMetadata, "A", _sipA); decodeSipHeader(*hackMetadata, "B", _sipB); decodeSipHeader(*hackMetadata, "AP", _sipAp); decodeSipHeader(*hackMetadata, "BP", _sipBp); // this gets called in the Wcs (base class) constructor // We just changed fitsMetadata, so we have to re-init wcslib initWcsLibFromFits(hackMetadata); break; } //Check that the existence of forward sip matrices <=> existence of reverse matrices if (_hasDistortion) { if (_sipA.rows() <= 1 || _sipB.rows() <= 1) { std::string msg = "Existence of forward distorton matrices suggested, but not found";
    145 473b834b - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException, msg);
    ? ^^^^^^ ^
    145 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, msg);
    ? ^^ ^ } if (_sipAp.rows() <= 1 || _sipBp.rows() <= 1) { std::string msg = "Forward distorton matrices present, but no reverse matrices";
    150 473b834b - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException, msg);
    ? ^^^^^^ ^
    150 21597d88 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, msg);
    ? ^^ ^ } } } void TanWcs::decodeSipHeader( daf::base::PropertySet const & fitsMetadata, std::string const& which, Eigen::MatrixXd & m ) { std::string header = which + "_ORDER"; if (!fitsMetadata.exists(header)) return; int order = fitsMetadata.getAsInt(header); m.resize(order + 1, order + 1); boost::format format("%1%_%2%_%3%"); for (int i = 0; i <= order; ++i) { for (int j = 0; j <= order; ++j) { header = (format % which % i % j).str(); if (fitsMetadata.exists(header)) { m(i,j) = fitsMetadata.getAsDouble(header); } else { m(i, j) = 0.0; } } } } TanWcs::TanWcs( geom::Point2D const & crval, geom::Point2D const & crpix, Eigen::Matrix2d const & cd, double equinox, std::string const & raDecSys, std::string const & cunits1, std::string const & cunits2 ) : Wcs(crval, crpix, cd, "RA---TAN", "DEC--TAN", equinox, raDecSys, cunits1, cunits2), _hasDistortion(false), _sipA(), _sipB(), _sipAp(), _sipBp() {} TanWcs::TanWcs( geom::Point2D const &crval, geom::Point2D const & crpix, Eigen::Matrix2d const & cd, Eigen::MatrixXd const & sipA, Eigen::MatrixXd const & sipB, Eigen::MatrixXd const & sipAp, Eigen::MatrixXd const & sipBp, double equinox, std::string const & raDecSys, std::string const & cunits1, std::string const & cunits2 ) : Wcs(crval, crpix, cd, "RA---TAN", "DEC--TAN", equinox, raDecSys, cunits1, cunits2), _hasDistortion(true), //Sip's set by a dedicated method that does error checking _sipA(), _sipB(), _sipAp(), _sipBp() { //Input checking is done constructor of base class, so don't need to do any here. //Set the distortion terms setDistortionMatrices(sipA, sipB, sipAp, sipBp); } TanWcs::TanWcs(TanWcs const & rhs) : Wcs(rhs), _hasDistortion(rhs._hasDistortion), _sipA(rhs._sipA), _sipB(rhs._sipB), _sipAp(rhs._sipAp), _sipBp(rhs._sipBp) { } bool TanWcs::_isSubset(Wcs const & rhs) const { if (!Wcs::_isSubset(rhs)) { return false; } // We only care about the derived-class part if we have a distortion; this could mean // a TanWcs with no distortion may be equal to a plain Wcs, but that doesn't happen // in practice because have different wcslib data structures. if (this->hasDistortion()) { TanWcs const * other = dynamic_cast(&rhs); return other && other->_hasDistortion && _sipA == other->_sipA && _sipB == other->_sipB && _sipAp == other->_sipAp && _sipBp == other->_sipBp; } return true; } PTR(Wcs) TanWcs::clone(void) const { return PTR(Wcs)(new TanWcs(*this)); } // // Accessors // geom::Point2D TanWcs::skyToPixelImpl( geom::Angle sky1, // RA geom::Angle sky2 // Dec ) const { if(_wcsInfo == NULL) {
    257 473b834b - throw(LSST_EXCEPT(pex::exceptions::RuntimeErrorException, "Wcs structure not initialised"));
    ? ---------
    257 21597d88 + throw(LSST_EXCEPT(pex::exceptions::RuntimeError, "Wcs structure not initialised"));
    } double skyTmp[2]; double imgcrd[2]; double phi, theta; double pixTmp[2]; //Estimate undistorted pixel coordinates int stat[1]; int status = 0; skyTmp[_wcsInfo->lng] = sky1.asDegrees(); skyTmp[_wcsInfo->lat] = sky2.asDegrees(); status = wcss2p(_wcsInfo, 1, 2, skyTmp, &phi, &theta, imgcrd, pixTmp, stat); if (status > 0) {
    274 473b834b - throw LSST_EXCEPT(pex::exceptions::RuntimeErrorException,
    ? ---------
    274 21597d88 + throw LSST_EXCEPT(pex::exceptions::RuntimeError,
    (boost::format("Error: wcslib returned a status code of %d at sky %s, %s deg: %s") % status % sky1.asDegrees() % sky2.asDegrees() % wcs_errmsg[status]).str()); } //Correct for distortion. We follow the notation of Shupe et al. here, including //capitalisation if( _hasDistortion) { geom::Point2D pix = geom::Point2D(pixTmp[0], pixTmp[1]); geom::Point2D dpix = distortPixel(pix); pixTmp[0] = dpix[0]; pixTmp[1] = dpix[1]; } // wcslib assumes 1-indexed coords double offset = PixelZeroPos + fitsToLsstPixels; return geom::Point2D(pixTmp[0]+offset, pixTmp[1]+offset); } namespace { /// Generate a vector of polynomial elements, x^i /// /// This is useful for optimising polynomial evaluations std::vector polynomialElements(size_t const order, double const value) { std::vector poly(order + 1); poly[0] = 1.0; if (order == 0) { return poly; } poly[1] = value; for (int i = 2; i <= order; ++i) { poly[i] = poly[i-1]*value; } return poly; } } // anonymous namespace geom::Point2D TanWcs::undistortPixel(geom::Point2D const & pix) const { if (!_hasDistortion) { return geom::Point2D(pix); } //If the following assertions aren't true then something has gone seriously wrong. assert(_sipB.rows() > 0 ); assert(_sipA.rows() == _sipA.cols()); assert(_sipB.rows() == _sipB.cols()); // Polynomial orders for U = f(u,v) and V = g(u,v) // Note these may be different in general, but not usually in practise. size_t const fOrder = _sipA.rows(); size_t const gOrder = _sipB.rows(); double u = pix[0] - _wcsInfo->crpix[0]; //Relative pixel coords double v = pix[1] - _wcsInfo->crpix[1]; std::vector uPoly = polynomialElements(std::max(fOrder, gOrder), u); std::vector vPoly = polynomialElements(std::max(fOrder, gOrder), v); double f = 0; for (int i = 0; i < fOrder; ++i) { for (int j = std::max(0, 2-i); j < fOrder - i; ++j) { f += _sipA(i,j)*uPoly[i]*vPoly[j]; } } double g = 0; for (int i = 0; i < gOrder; ++i) { for(int j = std::max(0, 2-i); j < gOrder - i; ++j) { g += _sipB(i,j)*uPoly[i]*vPoly[j]; } } return geom::Point2D(pix[0] + f, pix[1] + g); } geom::Point2D TanWcs::distortPixel(geom::Point2D const & pix) const { if (!_hasDistortion) { return geom::Point2D(pix); } //If the following assertions aren't true then something has gone seriously wrong. assert(_sipBp.rows() > 0 ); assert(_sipAp.rows() == _sipAp.cols()); assert(_sipBp.rows() == _sipBp.cols()); // Polynomial orders for u = F(U,V) and v = G(U,V) // Note these may be different in general, but not usually in practise. size_t const fOrder = _sipAp.rows(); size_t const gOrder = _sipBp.rows(); double U = pix[0] - _wcsInfo->crpix[0]; //Relative, undistorted pixel coords double V = pix[1] - _wcsInfo->crpix[1]; std::vector uPoly = polynomialElements(std::max(fOrder, gOrder), U); std::vector vPoly = polynomialElements(std::max(fOrder, gOrder), V); double F = 0; for (int i = 0; i< fOrder; ++i) { for (int j = 0; j < fOrder; ++j) { F += _sipAp(i,j)*uPoly[i]*vPoly[j]; } } double G = 0; for (int i = 0; i < gOrder; ++i) { for (int j = 0; j< gOrder; ++j) { G += _sipBp(i,j)*uPoly[i]*vPoly[j]; } } return geom::Point2D(U + F + _wcsInfo->crpix[0], V + G + _wcsInfo->crpix[1]); } /************************************************************************************************************/ /* * Worker routine for pixelToSky */ void TanWcs::pixelToSkyImpl(double pixel1, double pixel2, geom::Angle sky[2]) const { if(_wcsInfo == NULL) {
    398 054f091f - throw(LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Wcs structure not initialised"));
    ? ---------
    398 21597d88 + throw(LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Wcs structure not initialised"));
    } // wcslib assumes 1-indexed coordinates double pixTmp[2] = { pixel1 - PixelZeroPos + lsstToFitsPixels, pixel2 - PixelZeroPos + lsstToFitsPixels}; double imgcrd[2]; double phi, theta; //Correct pixel positions for distortion if necessary if( _hasDistortion) { geom::Point2D pix = geom::Point2D(pixTmp[0], pixTmp[1]); geom::Point2D dpix = undistortPixel(pix); pixTmp[0] = dpix[0]; pixTmp[1] = dpix[1]; } int status = 0; double skyTmp[2]; if (wcsp2s(_wcsInfo, 1, 2, pixTmp, imgcrd, &phi, &theta, skyTmp, &status) > 0) {
    418 054f091f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    418 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Error: wcslib returned a status code of %d at pixel %s, %s: %s") % status % pixel1 % pixel2 % wcs_errmsg[status]).str()); } sky[0] = skyTmp[0] * geom::degrees; sky[1] = skyTmp[1] * geom::degrees; } /************************************************************************************************************/ PTR(daf::base::PropertyList) TanWcs::getFitsMetadata() const { return formatters::TanWcsFormatter::generatePropertySet(*this); } // // Mutators // void TanWcs::setDistortionMatrices( Eigen::MatrixXd const & sipA, Eigen::MatrixXd const & sipB, Eigen::MatrixXd const & sipAp, Eigen::MatrixXd const & sipBp ) { if (sipA.rows() != sipA.cols() ){
    444 054f091f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    444 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Error: Matrix sipA must be square"); } if (sipB.rows() != sipB.cols() ){
    449 054f091f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    449 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Error: Matrix sipB must be square"); } if (sipAp.rows() != sipAp.cols() ){
    454 054f091f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    454 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Error: Matrix sipAp must be square"); } if (sipBp.rows() != sipBp.cols() ){
    459 054f091f - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    459 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Error: Matrix sipBp must be square"); } //Set the SIP terms _hasDistortion = true; _sipA = sipA; _sipB = sipB; _sipAp = sipAp; _sipBp = sipBp; } // -------------- Table-based Persistence ------------------------------------------------------------------- /* * We use the Wcs base class persistence to write one table, and then add another containing * the SIP coefficients only if hasDistortion() is true. * * The second table's schema depends on the SIP orders, so it will not necessarily be the same * for all TanWcs objects. */ class TanWcsFactory : public table::io::PersistableFactory { public: explicit TanWcsFactory(std::string const & name) : table::io::PersistableFactory(name) {} virtual PTR(table::io::Persistable) read( InputArchive const & archive, CatalogVector const & catalogs ) const { LSST_ARCHIVE_ASSERT(catalogs.size() >= 1u); CONST_PTR(table::BaseRecord) sipRecord; if (catalogs.size() > 1u) { LSST_ARCHIVE_ASSERT(catalogs.size() == 2u); LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.back().size() == 1u); sipRecord = catalogs.back().begin(); } PTR(TanWcs) result(new TanWcs(catalogs.front().front(), sipRecord)); return result; } }; namespace { std::string getTanWcsPersistenceName() { return "TanWcs"; } TanWcsFactory registration(getTanWcsPersistenceName()); } // anonymous std::string TanWcs::getPersistenceName() const { return getTanWcsPersistenceName(); } void TanWcs::write(OutputArchiveHandle & handle) const { Wcs::write(handle); if (hasDistortion()) { afw::table::Schema schema; afw::table::Key< afw::table::Array > keyA( schema.addField< afw::table::Array >( "A", "x forward transform coefficients (column-major)", _sipA.size() ) ); afw::table::Key< afw::table::Array > keyB( schema.addField< afw::table::Array >( "B", "y forward transform coefficients (column-major)", _sipB.size() ) ); afw::table::Key< afw::table::Array > keyAp( schema.addField< afw::table::Array >( "Ap", "x reverse transform coefficients (column-major)", _sipAp.size() ) ); afw::table::Key< afw::table::Array > keyBp( schema.addField< afw::table::Array >( "Bp", "y reverse transform coefficients (column-major)", _sipBp.size() ) ); afw::table::BaseCatalog catalog = handle.makeCatalog(schema); PTR(afw::table::BaseRecord) record = catalog.addNew(); Eigen::Map mapA((*record)[keyA].getData(), _sipA.rows(), _sipA.cols()); mapA = _sipA; Eigen::Map mapB((*record)[keyB].getData(), _sipB.rows(), _sipB.cols()); mapB = _sipB; Eigen::Map mapAp((*record)[keyAp].getData(), _sipAp.rows(), _sipAp.cols()); mapAp = _sipAp; Eigen::Map mapBp((*record)[keyBp].getData(), _sipBp.rows(), _sipBp.cols()); mapBp = _sipBp; handle.saveCatalog(catalog); } } TanWcs::TanWcs( afw::table::BaseRecord const & mainRecord, CONST_PTR(afw::table::BaseRecord) sipRecord ) : Wcs(mainRecord), _hasDistortion(sipRecord) { if (_hasDistortion) { typedef afw::table::Array Array; afw::table::Key kA; afw::table::Key kB; afw::table::Key kAp; afw::table::Key kBp; try { kA = sipRecord->getSchema()["A"]; kB = sipRecord->getSchema()["B"]; kAp = sipRecord->getSchema()["Ap"]; kBp = sipRecord->getSchema()["Bp"]; } catch (...) { throw LSST_EXCEPT( afw::table::io::MalformedArchiveError, "Incorrect schema for TanWcs distortion terms" ); } // Adding 0.5 and truncating the result here guarantees we'll get the right answer // for small ints even when round-off error is involved. int nA = int(std::sqrt(kA.getSize() + 0.5)); int nB = int(std::sqrt(kB.getSize() + 0.5)); int nAp = int(std::sqrt(kAp.getSize() + 0.5)); int nBp = int(std::sqrt(kBp.getSize() + 0.5)); if (nA * nA != kA.getSize()) { throw LSST_EXCEPT( afw::table::io::MalformedArchiveError, "Forward X SIP matrix is not square." ); } if (nB * nB != kB.getSize()) { throw LSST_EXCEPT( afw::table::io::MalformedArchiveError, "Forward Y SIP matrix is not square." ); } if (nAp * nAp != kAp.getSize()) { throw LSST_EXCEPT( afw::table::io::MalformedArchiveError, "Reverse X SIP matrix is not square." ); } if (nBp * nBp != kBp.getSize()) { throw LSST_EXCEPT( afw::table::io::MalformedArchiveError, "Reverse Y SIP matrix is not square." ); } Eigen::Map mapA((*sipRecord)[kA].getData(), nA, nA); _sipA = mapA; Eigen::Map mapB((*sipRecord)[kB].getData(), nB, nB); _sipB = mapB; Eigen::Map mapAp((*sipRecord)[kAp].getData(), nAp, nAp); _sipAp = mapAp; Eigen::Map mapBp((*sipRecord)[kBp].getData(), nBp, nBp); _sipBp = mapBp; } } }}} // namespace lsst::afw::image

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    473b834b

    commit 473b834bd398778eb0bf090b3a6da22e5a4d504a
    Author: Jim Bosch 
    Date:   Mon Nov 26 14:06:58 2012 -0500
    
        Lots of cleanup for TanWcs.
        
        Includes:
         - Indentation
         - Doxygen moved to .h file, made prettier.
         - Replace some pass-by-const-value with pass-by-const-reference.
         - Make decodeSipHeaders public (will reduce code duplication in meas_mosaic in future).
    

    054f091f

    commit 054f091f5cab6a42ea6677888c5f1a44ee35ab3a
    Author: fergal 
    Date:   Fri Feb 12 19:26:26 2010 +0000
    
        Changed Wcs to be a general base class, and TanWcs to extend that class for the case of TAN and TAN-SIP projections.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/display/simpleFits.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief Write a FITS image to a file descriptor; useful for talking to DS9
                     *
                     * This version knows about LSST data structures
                     */
                    #ifndef DOXYGEN // Doxygen doesn't like includes inside namespaces
                    namespace posix {                       // here so no-one includes them first outside namespace posix {} 
                    #   include 
                    #   include 
                    }
                    #endif //!DOXYGEN
                    using namespace posix;
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "boost/any.hpp"
                    #include "lsst/afw/fits.h"
                    
                    #include "simpleFits.h"
                    
                    namespace image = lsst::afw::image;
                    using lsst::daf::base::PropertySet;
                    
                    #define FITS_SIZE 2880
                    
                    /// \cond
                    class Card {
                    public:
                        Card(const std::string &name, bool val, const char *commnt = ""
                            ) : keyword(name), value(val), comment(commnt) { }
                        Card(const std::string &name, int val, const char *commnt = ""
                            ) : keyword(name), value(val), comment(commnt) { }
                        Card(const std::string &name, double val, const char *commnt = ""
                            ) : keyword(name), value(val), comment(commnt) { }
                        Card(const std::string &name, float val, const char *commnt = ""
                            ) : keyword(name), value(val), comment(commnt) { }
                        Card(const std::string &name, const std::string &val, const char *commnt = ""
                            ) : keyword(name), value(val), comment(commnt) { }
                        Card(const std::string &name, const char *val, const char *commnt = ""
                            ) : keyword(name), value(std::string(val)), comment(commnt) { }
                    
                        ~Card() {}
                    
                        int write(int fd, int ncard, char *record) const;
                        
                        std::string keyword;
                        boost::any value;
                        std::string comment;
                    };
                    
                    /*****************************************************************************/
                    /*
                     * Write a Card
                     */
                    int Card::write(int fd,
                                    int ncard,
                                    char *record
                                   ) const {
                        char *card = &record[80*ncard];
                    
                        if (value.type() == typeid(std::string)) {
                            const char *str = boost::any_cast(value).c_str();
                            if (keyword == "" ||
                               keyword == "COMMENT" || keyword == "END" || keyword == "HISTORY") {
                                sprintf(card, "%-8.8s%-72s", keyword.c_str(), str);
                            } else {
                                sprintf(card,"%-8.8s= '%s' %c%-*s",
                                        keyword.c_str(), str,
                                        (comment == "" ? ' ' : '/'),
                                        (int)(80 - 14 - strlen(str)), comment.c_str());
                            }
                        } else {
                            sprintf(card, "%-8.8s= ", keyword.c_str());
                            card += 10;
                            if (value.type() == typeid(bool)) {
                                sprintf(card, "%20s", boost::any_cast(value) ? "T" : "F");
                            } else if (value.type() == typeid(int)) {
                                sprintf(card, "%20d", boost::any_cast(value));
                            } else if (value.type() == typeid(double)) {
                                sprintf(card, "%20.10f", boost::any_cast(value));
                            } else if (value.type() == typeid(float)) {
                                sprintf(card, "%20.7f", boost::any_cast(value));
                            }
                            card += 20;
                            sprintf(card, " %c%-48s", (comment == "" ? ' ' : '/'), comment.c_str());
                        }
                    /*
                     * Write record if full
                     */
                        if (++ncard == 36) {
                            if (posix::write(fd, record, FITS_SIZE) != FITS_SIZE) {
    
    119 2eb9dac3 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Cannot write header record");
    ? ---------
    119 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Cannot write header record");
    } ncard = 0; } return ncard; } /// \endcond /*****************************************************************************/ /* * Utilities * * Flip high-order bit so as to write unsigned short to FITS. Grrr. */ namespace { void flip_high_bit(char *arr, // array that needs bits swapped const int n) { // number of bytes in arr if (n%2 != 0) {
    138 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    138 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Attempt to bit flip odd number of bytes: %d") % n).str()); } unsigned short* uarr = reinterpret_cast(arr); for(unsigned short *end = uarr + n/2; uarr < end; ++uarr) { *uarr ^= 0x8000; } } } /* * Byte swap ABABAB -> BABABAB in place */ namespace { void swap_2(char *arr, // array to swap const int n) { // number of bytes if (n%2 != 0) {
    156 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    156 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Attempt to byte swap odd number of bytes: %d") % n).str()); } for(char *end = arr + n;arr < end;arr += 2) { char t = arr[0]; arr[0] = arr[1]; arr[1] = t; } } /* * Byte swap ABCDABCD -> DCBADCBA in place (e.g. sun <--> vax) */ void swap_4(char *arr, // array to swap const int n) { // number of bytes if (n%4 != 0) {
    172 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    172 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Attempt to byte swap non-multiple of 4 bytes: %d") % n).str()); } for(char *end = arr + n;arr < end;arr += 4) { char t = arr[0]; arr[0] = arr[3]; arr[3] = t; t = arr[1]; arr[1] = arr[2]; arr[2] = t; } } /* * Byte swap ABCDEFGH -> HGFEDCBA in place (e.g. sun <--> vax) */ void swap_8(char *arr, // array to swap const int n) { // number of bytes if (n%8 != 0) {
    192 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    192 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Attempt to byte swap non-multiple of 8 bytes: %d") % n).str()); } for(char *end = arr + n;arr < end;arr += 8) { char t = arr[0]; arr[0] = arr[7]; arr[7] = t; t = arr[1]; arr[1] = arr[6]; arr[6] = t; t = arr[2]; arr[2] = arr[5]; arr[5] = t; t = arr[3]; arr[3] = arr[4]; arr[4] = t; } } /*****************************************************************************/ int write_fits_hdr(int fd, int bitpix, int naxis, int *naxes, std::list& cards, /* extra header cards */ int primary) /* is this the primary HDU? */ { int i; char record[FITS_SIZE + 1]; /* write buffer */ int ncard = 0; if (primary) { Card card("SIMPLE", true); ncard = card.write(fd, ncard, record); } else { Card card("XTENSION", "IMAGE"); ncard = card.write(fd, ncard, record); } { Card card("BITPIX", bitpix); ncard = card.write(fd, ncard, record); } { Card card("NAXIS", naxis); ncard = card.write(fd, ncard, record); } for(i = 0; i < naxis; i++) { char key[] = "NAXIS."; sprintf(key, "NAXIS%d", i + 1); Card card(key, naxes[i]); ncard = card.write(fd, ncard, record); } if (primary) { Card card("EXTEND", true, "There may be extensions"); ncard = card.write(fd,ncard,record); } /* * Write extra header cards */ for (std::list::const_iterator card = cards.begin(); card != cards.end(); card++) { ncard = card->write(fd,ncard,record); } { Card card("END", ""); ncard = card.write(fd,ncard,record); } while(ncard != 0) { Card card("", ""); ncard = card.write(fd,ncard,record); } return 0; } /* * Pad out to a FITS record boundary */ void pad_to_fits_record(int fd, // output file descriptor int npixel, // number of pixels already written to HDU int bitpix // bitpix for this datatype ) { const int bytes_per_pixel = (bitpix > 0 ? bitpix : -bitpix)/8; int nbyte = npixel*bytes_per_pixel; if (nbyte%FITS_SIZE != 0) { char record[FITS_SIZE + 1]; /* write buffer */ nbyte = FITS_SIZE - nbyte%FITS_SIZE; memset(record, ' ', nbyte); if (write(fd, record, nbyte) != nbyte) {
    286 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    286 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "error padding file to multiple of fits block size"); } } } int write_fits_data(int fd, int bitpix, char *begin, char *end ) { const int bytes_per_pixel = (bitpix > 0 ? bitpix : -bitpix)/8; int swap_bytes = 0; // the default #if defined(LSST_LITTLE_ENDIAN) // we'll need to byte swap FITS if (bytes_per_pixel > 1) { swap_bytes = 1; } #endif char *buff = NULL; // I/O buffer bool allocated = false; // do I need to free it? if (swap_bytes || bitpix == 16) { buff = new char[FITS_SIZE*bytes_per_pixel]; allocated = true; } int nbyte = end - begin; int nwrite = (nbyte > FITS_SIZE) ? FITS_SIZE : nbyte; for (char *ptr = begin; ptr != end; nbyte -= nwrite, ptr += nwrite) { if (end - ptr < nwrite) { nwrite = end - ptr; } if (swap_bytes) { memcpy(buff, ptr, nwrite); if (bitpix == 16) { // flip high-order bit flip_high_bit(buff, nwrite); } if (bytes_per_pixel == 2) { swap_2(buff, nwrite); } else if (bytes_per_pixel == 4) { swap_4(buff, nwrite); } else if (bytes_per_pixel == 8) { swap_8(buff, nwrite); } else { fprintf(stderr,"You cannot get here\n"); abort(); } } else { if (bitpix == 16) { // flip high-order bit memcpy(buff, ptr, nwrite); flip_high_bit(buff, nwrite); } else { buff = ptr; } } if (write(fd, buff, nwrite) != nwrite) { perror("Error writing image: "); break; } } if (allocated) { delete buff; } return (nbyte == 0 ? 0 : -1); } } namespace lsst { namespace afw { namespace display { template void writeBasicFits(int fd, // file descriptor to write to ImageT const& data, // The data to write image::Wcs const* Wcs, // which Wcs to use for pixel char const *title // title to write to DS9 ) { /* * Allocate cards for FITS headers */ std::list cards; /* * What sort if image is it? */ int bitpix = lsst::afw::fits::getBitPix(); if (bitpix == 20) { // cfitsio for "Unsigned short" cards.push_back(Card("BZERO", 32768.0, "")); cards.push_back(Card("BSCALE", 1.0, "")); bitpix = 16; } else if (bitpix == 0) {
    379 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unsupported image type");
    ? ---------
    379 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unsupported image type");
    } /* * Generate WcsA, pixel coordinates, allowing for X0 and Y0 */ std::string wcsName = "A"; cards.push_back(Card(str(boost::format("CRVAL1%s") % wcsName), data.getX0(), "(output) Column pixel of Reference Pixel")); cards.push_back(Card(str(boost::format("CRVAL2%s") % wcsName), data.getY0(), "(output) Row pixel of Reference Pixel")); cards.push_back(Card(str(boost::format("CRPIX1%s") % wcsName), 1.0, "Column Pixel Coordinate of Reference")); cards.push_back(Card(str(boost::format("CRPIX2%s") % wcsName), 1.0, "Row Pixel Coordinate of Reference")); cards.push_back(Card(str(boost::format("CTYPE1%s") % wcsName), "LINEAR", "Type of projection")); cards.push_back(Card(str(boost::format("CTYPE1%s") % wcsName), "LINEAR", "Type of projection")); cards.push_back(Card(str(boost::format("CUNIT1%s") % wcsName), "PIXEL", "Column unit")); cards.push_back(Card(str(boost::format("CUNIT2%s") % wcsName), "PIXEL", "Row unit")); /* * Now WcsB, so that pixel (0,0) is correctly labelled (but ignoring XY0) */ wcsName = "B"; cards.push_back(Card(str(boost::format("CRVAL1%s") % wcsName), 0, "(output) Column pixel of Reference Pixel")); cards.push_back(Card(str(boost::format("CRVAL2%s") % wcsName), 0, "(output) Row pixel of Reference Pixel")); cards.push_back(Card(str(boost::format("CRPIX1%s") % wcsName), 1.0, "Column Pixel Coordinate of Reference")); cards.push_back(Card(str(boost::format("CRPIX2%s") % wcsName), 1.0, "Row Pixel Coordinate of Reference")); cards.push_back(Card(str(boost::format("CTYPE1%s") % wcsName), "LINEAR", "Type of projection")); cards.push_back(Card(str(boost::format("CTYPE1%s") % wcsName), "LINEAR", "Type of projection")); cards.push_back(Card(str(boost::format("CUNIT1%s") % wcsName), "PIXEL", "Column unit")); cards.push_back(Card(str(boost::format("CUNIT2%s") % wcsName), "PIXEL", "Row unit")); if (title) { cards.push_back(Card("OBJECT", title, "Image being displayed")); } /* * Was there something else? */ if (Wcs != NULL) { typedef std::vector NameList; image::Wcs::Ptr newWcs = Wcs->clone(); //Create a copy newWcs->shiftReferencePixel(-data.getX0(), -data.getY0()); lsst::daf::base::PropertySet::Ptr metadata = newWcs->getFitsMetadata(); NameList paramNames = metadata->paramNames(); for (NameList::const_iterator i = paramNames.begin(), end = paramNames.end(); i != end; ++i) { if (*i == "SIMPLE" || *i == "BITPIX" || *i == "NAXIS" || *i == "NAXIS1" || *i == "NAXIS2" || *i == "XTENSION" || *i == "PCOUNT" || *i == "GCOUNT" ) { continue; } std::type_info const &type = metadata->typeOf(*i); if (type == typeid(bool)) { cards.push_back(Card(*i, metadata->get(*i))); } else if (type == typeid(int)) { cards.push_back(Card(*i, metadata->get(*i))); } else if (type == typeid(float)) { cards.push_back(Card(*i, metadata->get(*i))); } else if (type == typeid(double)) { cards.push_back(Card(*i, metadata->get(*i))); } else { cards.push_back(Card(*i, metadata->get(*i))); } } } /* * Basic FITS stuff */ const int naxis = 2; // == NAXIS int naxes[naxis]; /* values of NAXIS1 etc */ naxes[0] = data.getWidth(); naxes[1] = data.getHeight(); write_fits_hdr(fd, bitpix, naxis, naxes, cards, 1); for (int y = 0; y != data.getHeight(); ++y) { if (write_fits_data(fd, bitpix, (char *)(data.row_begin(y)), (char *)(data.row_end(y))) < 0){
    465 2eb9dac3 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    465 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Error writing data for row %d") % y).str()); } } pad_to_fits_record(fd, data.getWidth()*data.getHeight(), bitpix); } /******************************************************************************/ template void writeBasicFits(std::string const& filename, // file to write, or "| cmd" ImageT const& data, // The data to write image::Wcs const* Wcs, // which Wcs to use for pixel char const* title // title to write to DS9 ) { int fd; if ((filename.c_str())[0] == '|') { // a command const char *cmd = filename.c_str() + 1; while (isspace(*cmd)) { cmd++; } fd = fileno(popen(cmd, "w")); } else { fd = creat(filename.c_str(), 777); } if (fd < 0) {
    494 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    494 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Cannot open \"%s\"") % filename).str()); } try { writeBasicFits(fd, data, Wcs, title); } catch(lsst::pex::exceptions::Exception &) { (void)close(fd); throw; } (void)close(fd); } /// \cond #define INSTANTIATE(IMAGET) \ template void writeBasicFits(int, IMAGET const&, image::Wcs const *, char const *); \ template void writeBasicFits(std::string const&, IMAGET const&, image::Wcs const *, char const *) #define INSTANTIATE_IMAGE(T) INSTANTIATE(lsst::afw::image::Image) #define INSTANTIATE_MASK(T) INSTANTIATE(lsst::afw::image::Mask) INSTANTIATE_IMAGE(boost::uint16_t); INSTANTIATE_IMAGE(int); INSTANTIATE_IMAGE(float); INSTANTIATE_IMAGE(double); INSTANTIATE_IMAGE(boost::uint64_t); INSTANTIATE_MASK(boost::uint16_t); /// \endcond }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    2eb9dac3

    commit 2eb9dac33eec6f13a73c03cc2827aa9884ff06cc
    Author: rowen 
    Date:   Mon Sep 28 22:55:55 2009 +0000
    
        Removed all tabs.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/matchFits.py

    Diff:

    1 2fbdae84 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2012 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Test for match persistence via FITS """ try: debug except NameError: debug = False import unittest import lsst.utils.tests as utilsTests import lsst.afw.table as afwTable class MatchFitsTestCase(unittest.TestCase): def setUp(self): self.size = 10 self.numMatches = self.size//2 self.filename = "matches.fits" self.schema = afwTable.SimpleTable.makeMinimalSchema() self.cat1 = afwTable.SimpleCatalog(self.schema) self.cat2 = afwTable.SimpleCatalog(self.schema) for i in range(self.size): record1 = self.cat1.table.makeRecord() record2 = self.cat2.table.makeRecord() record1.setId(i + 1) record2.setId(self.size - i) self.cat1.append(record1) self.cat2.append(record2) self.matches = afwTable.SimpleMatchVector() for i in range(self.numMatches): index = 2*i match = afwTable.SimpleMatch(self.cat1[index], self.cat2[self.size - index - 1], index) if debug: print "Inject:", match.first.getId(), match.second.getId() self.matches.push_back(match) def tearDown(self): del self.schema del self.cat1 del self.cat2 del self.matches def testMatches(self, matches=None): if matches is None: matches = self.matches self.assertEqual(len(matches), self.numMatches) for m in matches:
    73 b4c7305a + str(m) # Check __str__ works
    if debug: print "Test:", m.first.getId(), m.second.getId() self.assertEqual(m.first.getId(), m.second.getId()) def testIO(self): packed = afwTable.packMatches(self.matches) packed.writeFits(self.filename) matches = afwTable.BaseCatalog.readFits(self.filename) cat1 = self.cat1.copy() cat2 = self.cat2.copy() cat1.sort() cat2.sort() unpacked = afwTable.unpackMatches(matches, cat1, cat2) self.testMatches(unpacked) def testTicket2080(self): packed = afwTable.packMatches(self.matches) cat1 = self.cat1.copy() cat2 = afwTable.SimpleCatalog(self.schema) cat1.sort() cat2.sort() # just test that the next line doesn't segv afwTable.unpackMatches(packed, cat1, cat2) ################################################################# # Test suite boiler plate ################################################################# def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(MatchFitsTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    2fbdae84

    commit 2fbdae84096daf1f1c1cd823b3cb54bc9f581351
    Author: Paul Price 
    Date:   Thu Mar 22 13:50:14 2012 -0400
    
        Add test for match persistence.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    b4c7305a

    commit b4c7305a3d3ddc3973f6a26920525a3a564c511a
    Author: Paul Price 
    Date:   Mon Jun 23 14:48:57 2014 -0400
    
        Match: fix *Match.__str__ for missing x,y
        
        ReferenceMatch.first does not have getX and getY methods.
    

    Return to list

    src/table/io/FitsWriter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    #include "boost/cstdint.hpp"
                    
                    #include "lsst/afw/table/io/FitsWriter.h"
                    #include "lsst/afw/table/BaseTable.h"
                    #include "lsst/afw/table/BaseRecord.h"
                    
                    namespace lsst { namespace afw { namespace table { namespace io {
                    
                    namespace {
                    
                    typedef FitsWriter::Fits Fits;
                    
                    //----- Code to write FITS headers --------------------------------------------------------------------------
                    
                    // The driver code is at the bottom of this section; it's easier to understand if you start there
                    // and work your way up.
                    
                    // A Schema::forEach functor that writes FITS header keys for a field when it is called.
                    struct ProcessSchema {
                    
                        template 
                        void operator()(SchemaItem const & item) const {
                            std::string name = item.field.getName();
    
    26 aa977b5e + if (version < 1) {
    26 d6480e01 - std::replace(name.begin(), name.end(), '.', '_');
    27 aa977b5e + std::replace(name.begin(), name.end(), '.', '_');
    ? ++++
    28 aa977b5e + }
    int n = fits->addColumn::Element>( name, item.field.getElementCount(), item.field.getDoc() ); if (!item.field.getDoc().empty()) { // We use a separate key TDOCn for documentation (in addition to the TTYPEn comments) // so we can have long strings via the CONTINUE convention. // When reading, if there is no TDOCn, we'll just use the TTYPEn comment. fits->writeColumnKey("TDOC", n, item.field.getDoc()); } specialize(item, n); // delegate to other member functions that are specialized on field tag types } void operator()(SchemaItem const & item) const { std::string name = item.field.getName();
    44 aa977b5e + if (version < 1) {
    42 99ffef18 - std::replace(name.begin(), name.end(), '.', '_');
    45 aa977b5e + std::replace(name.begin(), name.end(), '.', '_');
    ? ++++
    46 aa977b5e + }
    int n = fits->addColumn( name, item.field.getElementCount(), item.field.getDoc() ); if (!item.field.getDoc().empty()) { fits->writeColumnKey("TDOC", n, item.field.getDoc()); } specialize(item, n); } void operator()(SchemaItem const & item) const { std::string name = item.field.getName();
    59 aa977b5e + if (version < 1) {
    55 d6480e01 - std::replace(name.begin(), name.end(), '.', '_');
    60 aa977b5e + std::replace(name.begin(), name.end(), '.', '_');
    ? ++++
    61 aa977b5e + }
    fits->writeColumnKey("TFLAG", nFlags, name); if (!item.field.getDoc().empty()) { // We use a separate key TFDOCn for documentation instead of the comment on TFLAGn so // we can have long strings via the CONTINUE convention. // When reading, if there is no TFDOCn, we'll use the TTYPEn comment. fits->writeColumnKey("TFDOC", nFlags, item.field.getDoc()); } ++nFlags; } // Create and apply the functor to a schema.
    67 d6480e01 - static void apply(Fits & fits, Schema const & schema) {
    73 aa977b5e + static void apply(Fits & fits, Schema const & schema, int version) {
    ? +++++++++++++
    68 d6480e01 - ProcessSchema f = { &fits, 0 };
    74 aa977b5e + ProcessSchema f = { &fits, 0, version };
    ? +++++++++ schema.forEach(boost::ref(f)); } template void specialize(SchemaItem const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits()); fits->writeColumnKey("TCCLS", n, "Scalar", "Field template used by lsst.afw.table"); } void specialize(SchemaItem const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits()); fits->writeColumnKey("TCCLS", n, "Angle", "Field template used by lsst.afw.table"); } template void specialize(SchemaItem< Array > const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits()); fits->writeColumnKey("TCCLS", n, "Array", "Field template used by lsst.afw.table"); } void specialize(SchemaItem const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits()); fits->writeColumnKey("TCCLS", n, "Coord", "Field template used by lsst.afw.table"); } template void specialize(SchemaItem< Point > const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits(), "{x, y}"); fits->writeColumnKey("TCCLS", n, "Point", "Field template used by lsst.afw.table"); } template void specialize(SchemaItem< Moments > const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits(), "{xx, yy, xy}"); fits->writeColumnKey("TCCLS", n, "Moments", "Field template used by lsst.afw.table"); } template void specialize(SchemaItem< Covariance > const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits(), "{(0,0), (0,1), (1,1), (0,2), (1,2), (2,2), ...}"); fits->writeColumnKey("TCCLS", n, "Covariance", "Field template used by lsst.afw.table"); } template void specialize(SchemaItem< Covariance< Point > > const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits(), "{(x,x), (x,y), (y,y)}"); fits->writeColumnKey("TCCLS", n, "Covariance(Point)", "Field template used by lsst.afw.table"); } template void specialize(SchemaItem< Covariance< Moments > > const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits(), "{(xx,xx), (xx,yy), (yy,yy), (xx,xy), (yy,xy), (xy,xy)}"); fits->writeColumnKey("TCCLS", n, "Covariance(Moments)", "Field template used by lsst.afw.table"); } void specialize(SchemaItem< std::string > const & item, int n) const { if (!item.field.getUnits().empty()) fits->writeColumnKey("TUNIT", n, item.field.getUnits()); fits->writeColumnKey("TCCLS", n, "String", "Field template used by lsst.afw.table"); } Fits * fits; mutable int nFlags;
    150 aa977b5e + int version;
    };
    152 dbc20e58 +
    153 a5b331c9 + void writeAliasMap(Fits & fits, AliasMap const & aliases) {
    154 a5b331c9 + for (AliasMap::Iterator i = aliases.begin(); i != aliases.end(); ++i) {
    155 a5b331c9 + fits.writeKey("ALIAS", i->first + ":" + i->second);
    156 a5b331c9 + }
    157 a5b331c9 + }
    } // anonymous // the driver for all the above machinery void FitsWriter::_writeTable(CONST_PTR(BaseTable) const & table, std::size_t nRows) { Schema schema = table->getSchema(); _fits->createTable(); LSST_FITS_CHECK_STATUS(*_fits, "creating table"); int nFlags = schema.getFlagFieldCount(); if (nFlags > 0) { int n = _fits->addColumn("flags", nFlags, "bits for all Flag fields; see also TFLAGn"); _fits->writeKey("FLAGCOL", n + 1, "Column number for the bitflags."); }
    158 d6480e01 - ProcessSchema::apply(*_fits, schema);
    171 bd692192 + ProcessSchema::apply(*_fits, schema, schema.getVersion());
    ? +++++++++++++++++++++
    159 e5027507 - if (table->getMetadata())
    172 a7452ce2 + writeAliasMap(*_fits, *schema.getAliasMap());
    173 4ff18d60 + // write the version number to the fits header, plus any other metadata
    174 4ff18d60 + PTR(daf::base::PropertyList) metadata = table->getMetadata();
    175 4ff18d60 + if (!metadata) {
    176 4ff18d60 + metadata = boost::make_shared();
    177 4ff18d60 + }
    178 4ff18d60 + int version = table->getVersion();
    179 4ff18d60 + metadata->set("AFW_TABLE_VERSION", version);
    160 e5027507 - _fits->writeMetadata(*table->getMetadata());
    ? ---- ^^^^^^^^^^^ --
    180 4ff18d60 + _fits->writeMetadata(*metadata);
    ? ^
    181 bc5cccae + // In case the metadata was attached to the table, clean it up.
    182 4ff18d60 + metadata->remove("AFW_TABLE_VERSION");
    _row = -1; _fits->addRows(nRows); _processor = boost::make_shared(_fits, schema, nFlags, _row); } //----- Code for writing FITS records ----------------------------------------------------------------------- // The driver code is at the bottom of this section; it's easier to understand if you start there // and work your way up. // A Schema::forEach functor that writes table data for a single record when it is called. // We instantiate one of these, then reuse it on all the records after updating the data // members that tell it which record and row number it's on. struct FitsWriter::ProcessRecords { template void operator()(SchemaItem const & item) const { fits->writeTableArray(row, col, item.key.getElementCount(), record->getElement(item.key)); ++col; } template void operator()(SchemaItem< Array > const & item) const { if (item.key.isVariableLength()) { ndarray::Array array = record->get(item.key); fits->writeTableArray(row, col, array.template getSize<0>(), array.getData()); } else { fits->writeTableArray(row, col, item.key.getElementCount(), record->getElement(item.key)); } ++col; } void operator()(SchemaItem const & item) const { fits->writeTableScalar(row, col, record->get(item.key)); ++col; } void operator()(SchemaItem const & item) const { flags[bit] = record->get(item.key); ++bit; } ProcessRecords(Fits * fits_, Schema const & schema_, int nFlags_, std::size_t const & row_) : row(row_), col(0), bit(0), nFlags(nFlags_), fits(fits_), schema(schema_) { if (nFlags) flags.reset(new bool[nFlags]); } void apply(BaseRecord const * r) { record = r; col = 0; bit = 0; if (nFlags) ++col; schema.forEach(boost::ref(*this)); if (nFlags) fits->writeTableArray(row, 0, nFlags, flags.get()); } std::size_t const & row; mutable int col; mutable int bit; int nFlags; Fits * fits; boost::scoped_array flags; BaseRecord const * record; Schema schema; }; void FitsWriter::_writeRecord(BaseRecord const & record) { ++_row; _processor->apply(&record); } }}}} // namespace lsst::afw::table::io

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    99ffef18

    commit 99ffef18edcb18e8d841ec58b508bbd345f223b8
    Author: Jim Bosch 
    Date:   Sat Nov 24 23:37:19 2012 -0500
    
        Add support for string fields in afw::table, not including column arrays.  Also fixed botched merge of tableLib.i.
    

    d6480e01

    commit d6480e01cf98ec6e6ebea9b7f58d2d9dcef6beef
    Author: Jim Bosch 
    Date:   Sun Feb 5 23:11:25 2012 -0500
    
        lots of documentation, and a little refactoring to improve readability
    

    e5027507

    commit e5027507fece1d7b1ff924fe082c00f91e6c2c59
    Author: Jim Bosch 
    Date:   Wed Feb 8 23:45:58 2012 -0500
    
        added FITS write support for table flexible metadata
    

    Commits in /Users/nate/repos_lsst/afw/

    a5b331c9

    commit a5b331c97e6edf3d5c012f6d99dd1b39f494c9fa
    Author: Jim Bosch 
    Date:   Thu Jul 10 11:24:55 2014 -0400
    
        Add persistence for Schema aliases
    

    bc5cccae

    commit bc5cccaefd7b295975759bfd5213afb4e79a8f9e
    Author: Perry Gee 
    Date:   Mon Apr 14 12:45:10 2014 -0500
    
        Change to the _readTable routines in these 4 types plus BaseTable so that the
        AFW_TABLE_VERSION entry in the header is used to version each type of table.
        The getVersion() routine from BaseTable is used to get the version number during
        save, and it is written to the metadata of the table before the metadata is persisted.
        
        On read, the metadata is searched at the beginning of FitsReader::_startRecords,
        and the version number is set on the table then.  The table-getMetadata() is cleansed.
        I also moved the removal code for AFW_TYPE to here.
        
        Jim, please check the code to be sure that there are not unintended consquences from
        moving the table->setMetadata to the middle of the _readTable routines
    

    a7452ce2

    commit a7452ce222551998eaff639f457528a35a31dd54
    Author: Jim Bosch 
    Date:   Thu Jul 10 11:36:08 2014 -0400
    
        Rename AliasMap accessors
    

    4ff18d60

    commit 4ff18d602c2e595e9c8569d78a2fd5246c4145ce
    Author: Perry Gee 
    Date:   Fri Apr 4 00:24:27 2014 -0500
    
        Changes to create a versioning scheme for AFW_TABLE, and to save it to disk
    

    bd692192

    commit bd692192367d33bb64a79ca008bff10eb9b41932
    Author: pgee 
    Date:   Mon Aug 18 15:06:04 2014 -0700
    
        Move API version number from BaseTable to Schema
        
        In FitsReader, move reading the AFW_TABLE_VERSION header key into the
        Schema-from-metadata constructor.
        In FitsWriter, use the version attached to the table schema to write the
        metadata.
    

    aa977b5e

    commit aa977b5e9cec2808c5751ba795da4ce21c066e7b
    Author: Jim Bosch 
    Date:   Sun Apr 20 10:44:26 2014 -0400
    
        Stop replacing periods with underscores in table I/O (DM-242)
    

    dbc20e58

    commit dbc20e585ec07b70b8c9dc3bbf9707ee3c200480
    Author: Jim Bosch 
    Date:   Wed Jan 25 20:07:49 2012 -0500
    
        lots of shuffling code around.  FITS table support now much better organized
    

    Return to list

    include/lsst/afw/detection/FootprintSet.h

    Diff:

                    //  -*- lsst-c++ -*-
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #if !defined(LSST_DETECTION_FOOTPRINT_SET_H)
                    #define LSST_DETECTION_FOOTPRINT_SET_H
                    /**
                     * \file
                     * \brief Represent a collections of footprints associated with image data
                     */
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/detection/Threshold.h"
                    #include "lsst/afw/detection/Footprint.h"
                    #include "lsst/afw/detection/FootprintCtrl.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/table/Source.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace detection {
                    
                    /// Pixel type for FootprintSet::insertIntoImage()
                    ///
                    /// This is independent of the template parameters for FootprintSet, and
                    /// including it within FootprintSet makes it difficult for SWIG to interpret
                    /// the type.
                    typedef boost::uint64_t FootprintIdPixel;
                    
                    /************************************************************************************************************/
                    /*!
                     * \brief A set of Footprints, associated with a MaskedImage
                     *
                     */
                    class FootprintSet : public lsst::daf::base::Citizen {
                    public:
                    
                        /// The FootprintSet's set of Footprint%s
                        typedef std::vector FootprintList;
                    
    
    59 ff27aae1 + #ifndef SWIG
    template FootprintSet(image::Image const& img, Threshold const& threshold, int const npixMin=1, bool const setPeaks=true);
    64 4afba64d - #ifndef SWIG
    template FootprintSet(image::Mask const& img, Threshold const& threshold, int const npixMin=1);
    69 4afba64d - #else // SWIG can't disambiguate this from the Image version when doing %template.
    70 4afba64d - FootprintSet(image::Mask const& img,
    71 4afba64d - Threshold const& threshold,
    72 4afba64d - int const npixMin=1);
    73 4afba64d - #endif
    template FootprintSet(image::MaskedImage const& img, Threshold const& threshold, std::string const& planeName = "", int const npixMin=1, bool const setPeaks=true);
    75 4afba64d +
    76 ff27aae1 + #else // workaround for https://github.com/swig/swig/issues/245
    77 ff27aae1 + // if that bug is fixed then you may update footprintset.i by uncommenting two lines
    78 ff27aae1 + // and removing this section. However, you must continue to provide SWIG
    79 ff27aae1 + // the alternate version of the template constructor, because
    80 ff27aae1 + // SWIG cannot disambiguate that from the template constructor.
    81 ff27aae1 +
    82 ff27aae1 + FootprintSet(image::Mask const& img,
    83 ff27aae1 + Threshold const& threshold,
    84 ff27aae1 + int const npixMin=1);
    85 ff27aae1 +
    86 ff27aae1 + FootprintSet(image::Image const& img,
    87 ff27aae1 + Threshold const& threshold,
    88 ff27aae1 + int const npixMin=1, bool const setPeaks=true);
    89 ff27aae1 + FootprintSet(image::MaskedImage const& img,
    90 ff27aae1 + Threshold const& threshold,
    91 ff27aae1 + std::string const& planeName = "",
    92 ff27aae1 + int const npixMin=1, bool const setPeaks=true);
    93 ff27aae1 +
    94 ff27aae1 + FootprintSet(image::Image const& img,
    95 ff27aae1 + Threshold const& threshold,
    96 ff27aae1 + int const npixMin=1, bool const setPeaks=true);
    97 ff27aae1 + FootprintSet(image::MaskedImage const& img,
    98 ff27aae1 + Threshold const& threshold,
    99 ff27aae1 + std::string const& planeName = "",
    100 ff27aae1 + int const npixMin=1, bool const setPeaks=true);
    101 ff27aae1 +
    102 ff27aae1 + FootprintSet(image::Image const& img,
    103 ff27aae1 + Threshold const& threshold,
    104 ff27aae1 + int const npixMin=1, bool const setPeaks=true);
    105 ff27aae1 + FootprintSet(image::MaskedImage const& img,
    106 ff27aae1 + Threshold const& threshold,
    107 ff27aae1 + std::string const& planeName = "",
    108 ff27aae1 + int const npixMin=1, bool const setPeaks=true);
    109 ff27aae1 +
    110 ff27aae1 + FootprintSet(image::Image const& img,
    111 ff27aae1 + Threshold const& threshold,
    112 ff27aae1 + int const npixMin=1, bool const setPeaks=true);
    113 ff27aae1 + FootprintSet(image::MaskedImage const& img,
    114 ff27aae1 + Threshold const& threshold,
    115 ff27aae1 + std::string const& planeName = "",
    116 ff27aae1 + int const npixMin=1, bool const setPeaks=true);
    117 ff27aae1 +
    118 ff27aae1 + #endif
    FootprintSet(geom::Box2I region); FootprintSet(FootprintSet const&); FootprintSet(FootprintSet const& set, int rGrow, FootprintControl const& ctrl); FootprintSet(FootprintSet const& set, int rGrow, bool isotropic=true); FootprintSet(FootprintSet const& footprints1, FootprintSet const& footprints2, bool const includePeaks); FootprintSet& operator=(FootprintSet const& rhs); void swap(FootprintSet& rhs) { using std::swap; // See Meyers, Effective C++, Item 25 swap(*_footprints, *rhs.getFootprints()); geom::Box2I rhsRegion = rhs.getRegion(); rhs.setRegion(getRegion()); setRegion(rhsRegion); } void swapFootprintList(FootprintList& rhs) { using std::swap; swap(*_footprints, rhs); } /**: * Return the Footprint%s of detected objects */ PTR(FootprintList) getFootprints() { return _footprints; } /**: * Set the Footprint%s of detected objects */ void setFootprints(PTR(FootprintList) footprints) { _footprints = footprints; } /** * Retun the Footprint%s of detected objects */ CONST_PTR(FootprintList) const getFootprints() const { return _footprints; } /** * @brief Add a new record corresponding to each footprint to a SourceCatalog. * * @param[in,out] catalog Catalog to append new sources to. * * The new sources will have their footprints set to point to the footprints in the * footprint set; they will not be deep-copied. */ void makeSources(afw::table::SourceCatalog & catalog) const; void setRegion(geom::Box2I const& region); /** * Return the corners of the MaskedImage */ geom::Box2I const getRegion() const { return _region; } PTR(image::Image) insertIntoImage( const bool relativeIDs ) const; template void setMask( image::Mask *mask, ///< Set bits in the mask std::string const& planeName ///< Here's the name of the mask plane to fit ) { setMaskFromFootprintList( mask, _footprints, // calling getFootprints() confuses clang++ 3.0 and leaks memory image::Mask::getPlaneBitMask(planeName) ); } template void setMask( PTR(image::Mask) mask, ///< Set bits in the mask std::string const& planeName ///< Here's the name of the mask plane to fit ) { setMask(mask.get(), planeName); } void merge(FootprintSet const& rhs, int tGrow=0, int rGrow=0, bool isotropic=true); template void makeHeavy(image::MaskedImage const& mimg, HeavyFootprintCtrl const* ctrl=NULL ); private: boost::shared_ptr _footprints; //!< the Footprints of detected objects geom::Box2I _region; //!< The corners of the MaskedImage that the detections live in }; }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4afba64d

    commit 4afba64d7fe74d4c1ed99f21d17cbb2008c4b024
    Author: Jim Bosch 
    Date:   Mon Jan 30 19:32:36 2012 -0500
    
        removed template parameters from FootprintSet class (now constructors and a few member functions are templated); removed now-pointless(?) makeFootprintSet functions
    

    Commits in /Users/nate/repos_lsst/afw/

    4afba64d

    commit 4afba64d7fe74d4c1ed99f21d17cbb2008c4b024
    Author: Jim Bosch 
    Date:   Mon Jan 30 19:32:36 2012 -0500
    
        removed template parameters from FootprintSet class (now constructors and a few member functions are templated); removed now-pointless(?) makeFootprintSet functions
    

    ff27aae1

    commit ff27aae1e2414be9ca96bdc36703f28f02d52122
    Author: Russell Owen 
    Date:   Thu Oct 16 09:27:57 2014 -0700
    
        Added a rather ugly workaround for a SWIG 3 bug
    

    Return to list

    python/lsst/afw/geom/CoordinateBase.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    %{
                    #include "lsst/afw/geom/CoordinateBase.h"
                    %}
                    
                    %define %CoordinateBase_POSTINCLUDE(T, N, CLASS...)
                    %extend CLASS {
                        %feature("shadow") _getitem_nochecking %{
                            def __getitem__(self, k):
                                if k < 0 or k >= N: raise IndexError(k)
                                return $action(self, k)
                        %}
                        T _getitem_nochecking(int i) {
                            return (*self)[i];
                        }
                    
                        %feature("shadow") _setitem_nochecking %{
                            def __setitem__(self, k, v):
                                if k < 0 or k >= N: raise IndexError(k)
                                $action(self, k, v)
                        %}
                        void _setitem_nochecking(int i, T value) {
                            (*self)[i] = value;
                        }    
                        CLASS clone() {
                            return CLASS(static_cast(*self));
                        }
    
    50 747f909d - %pythoncode {
    50 81c3bd10 + %pythoncode %{
    ? + def __len__(self): return N; def __repr__(self): return "%s(%s)" % (self.__class__.__name__, ", ".join("%0.10g" % v for v in self)) def __str__(self): return "(%s)" % (", ".join("%0.5g" % v for v in self),)
    57 747f909d - }
    57 81c3bd10 + %}
    ? + } %enddef

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    747f909d

    commit 747f909d1d90b2597c9daf7151f661639cf63a71
    Author: jbosch 
    Date:   Thu Dec 17 03:45:00 2009 +0000
    
        afw/#892 - swig wrappers for Point and Extent
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    python/lsst/gdb/afw/printers.py

    Diff:

                    import gdb
                    import math, re
                    
                    try:
                        debug
                    except:
                        debug = False
                    
                    import optparse
                    argparse = None                         # we're using optparse
                    
                    class GdbOptionParser(optparse.OptionParser):
                        """A subclass of the standard optparse OptionParser for gdb
                    
                    GdbOptionParser raises GdbError rather than exiting when asked for help, or
                    when given an illegal value. E.g.
                    
                    parser = gdb.printing.GdbOptionParser("show image")
                    parser.add_option("-a", "--all", action="store_true",
                                      help="Display the whole image")
                    parser.add_option("-w", "--width", type="int", default=8,
                                      help="Field width for pixels")
                    
                    opts, args =  parser.parse_args(args)
                    """
                    
                        def __init__(self, prog, *args, **kwargs):
                            """
                    Like optparse.OptionParser's API, but with an initial command name argument
                    """
                            # OptionParser is an old-style class, so no super
                            if not kwargs.get("prog"):
                                kwargs["prog"] = prog
                            optparse.OptionParser.__init__(self, *args, **kwargs)
                    
                        def parse_args(self, args, values=None):
                            """Call OptionParser.parse_args after running gdb.string_to_argv"""
                            if args is None:            # defaults to sys.argv
                                args = ""
                            try:
                                args = gdb.string_to_argv(args)
                            except TypeError:
                                pass
                    
                            help = ("-h" in args or "--help" in args)
                            opts, args = optparse.OptionParser.parse_args(self, args, values)
                            opts.help = help
                            if help:
                                args = []
                        
                            return opts, args
                    
                        def exit(self, status=0, msg=""):
                            """Raise GdbError rather than exiting"""
                            if status == 0:
                                if msg:
                                    print >> sys.stderr, msg
                            else:
                                raise gdb.GdbError(msg)
                    
                    try:
                        import gdb.printing
                    
                        class SharedPtrPrinter(object):
                            "Print a shared_ptr"
                    
                            def __init__(self, val):
                                self.val = val
                    
                            def to_string(self):
                                if self.val["px"]:
                                    return "shared_ptr(%s)" % self.val["px"].dereference()
                                else:
                                    return "NULL"
                    
                        class GilPixelPrinter(object):
                            "Print a boost::gil pixel"
                    
                            def __init__(self, val):
                                self.val = val
                    
                            def to_string(self):
                                import pdb; pdb.set_trace() 
                                return self.val["_v0"]
                    
                        #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                    
                        def getEigenMatrixDimensions(val):
                            m_storage = val["m_storage"]
                            try:
                                nx, ny = m_storage["m_cols"], m_storage["m_rows"]
                            except gdb.error:           # only available for dynamic Matrices
                                try:
                                    nx, ny = val.type.template_argument(1), val.type.template_argument(2)
                                except RuntimeError:
                                    # should get dimens from template, but that's gdb bug #11060
                                    size = m_storage["m_data"]["array"].type.sizeof
                                    size0 = m_storage["m_data"]["array"].dereference().type.sizeof
                                    # guess! Assume square
                                    nx = int(math.sqrt(size/size0))
                                    ny = size/(nx*size0)
                    
                            return nx, ny
                    
                        def getEigenValue(var, x, y=0):
                            if re.search(r"Matrix", str(var.type)):
                                if False:
                                    return var["operator()(int, int)"](x, y)
                    
                                NX, NY = getEigenMatrixDimensions(var)
                    
                                if x < 0 or x >= NX or y < 0 or y >= NY:
                                    raise gdb.GdbError("Element (%d, %d) is out of range 0:%d, 0:%d" %
                                                       (x, y, NX - 1, NY - 1))
                    
                                m_data = var["m_storage"]["m_data"]
                                if False:
                                    # convert to a pointer to the start of the array
                                    import pdb; pdb.set_trace() 
                                    m_data = m_data.address.cast(m_data.type)
                    
                                try:
                                    val = m_data[x + y*NX]
                                except:
                                    val = m_data["array"][x + y*NX]
                            else:                       # Vector
                                if False:
                                    return var["operator()(int)"](x)
                    
                                NX = getEigenMatrixDimensions(var)[0]
                    
                                if x < 0 or x >= NX:
                                    raise gdb.GdbError("Element (%d) is out of range 0:%d" % (x, NX - 1))
                    
                                m_data = var["m_storage"]["m_data"]
                    
                                if False:
                                    # convert to a pointer to the start of the array
                                    m_data = m_data.address.cast(m_data.type)
                    
                                try:
                                    val = m_data[x]
                                except:
                                    val = m_data["array"][x]
                    
                            if val.type.code == gdb.TYPE_CODE_INT:
                                val = int(val)
                            elif val.type.code == gdb.TYPE_CODE_FLT:
                                val = float(val)
                    
                            return val            
                    
                        class EigenMatrixPrinter(object):
                            "Print an Eigen Matrix"
                    
                            def __init__(self, val):
                                self.val = val
                    
                            def to_string(self):
                                nx, ny = getEigenMatrixDimensions(self.val)
                    
                                return "%s{%dx%d}" % (self.val.type, nx, ny)
                    
                        class EigenVectorPrinter(object):
                            "Print an Eigen Vector"
                    
                            def __init__(self, val):
                                self.val = val
                    
                            def to_string(self):
                                m_storage = self.val["m_storage"]
                    
                                try:
                                    n = m_storage["n"]
                                except gdb.error:           # only available for dynamic Matrices
                                    try:
                                        n = m_storage.type.template_argument(1)
                                    except RuntimeError:
                                        # should get dimens from template, but that's gdb bug #11060
                                        size = m_storage["m_data"]["array"].type.sizeof
                                        size0 = m_storage["m_data"]["array"].dereference().type.sizeof
                                        n = math.sqrt(size/size0)
                    
                                return "{%d}" % (n)
                    
                        class PrintEigenCommand(gdb.Command):
                            """Print an eigen Matrix or Vector
                        Usage: show eigen  [x0 y0 [nx ny]]
                               show eigen  [x0 [nx]]
                        """
                    
                            def __init__ (self):
                                super (PrintEigenCommand, self).__init__ ("show eigen",
                                                                          gdb.COMMAND_DATA,
                                                                          gdb.COMPLETE_SYMBOL)
                    
                    
                            def _mget(self, var, x, y=0):
                                return getEigenValue(var, x, y)
                    
                            def _vget(self, var, x):
                                return getEigenValue(var, x)
                    
                            def invoke (self, args, fromTty):
                                self.dont_repeat()
                    
                                parser = GdbOptionParser("show eigen")
                                parser.add_option("-d", "--dataFmt", default="%.2f", help="Format for values")
                                parser.add_option("-f", "--formatWidth", type="int", default=8, help="Field width for values")
                                parser.add_option("-o", "--origin", type="str", nargs="+",
                                                    help="Origin of the part of the object to print")
                                if False:
                                    parser.add_option("eigenObject", help="Expression giving Eigen::Matrix/Vector to show")
                                    parser.add_option("nx", help="Width of patch to print", type="int", default=0, nargs="?")
                                    parser.add_option("ny", help="Height of patch to print", type="int", default=0, nargs="?")
                                    
                                    opts =  parser.parse_args(args)
                                    if opts.help:
                                        return
                                else:
                                    (opts, args) = parser.parse_args(args)
                                    if opts.help:
                                        return
                                    
                                    if not args:
                                        raise gdb.GdbError("Please specify an object")
                                    opts.eigenObject = args.pop(0)
                    
                                    opts.nx, opts.ny = 0, 0
                                    if args:
                                        opts.nx = int(args.pop(0))
                                    if args:
                                        opts.ny = int(args.pop(0))
                    
                                    if args:
                                        raise gdb.GdbError("Unrecognised trailing arguments: %s" % " ".join(args))
                    
                                var = gdb.parse_and_eval(opts.eigenObject)
                    
                                if not re.search(r"(Eigen|LinearTransform)::(Matrix|Vector)", str(var.type)):
                                    raise gdb.GdbError("Please specify an eigen matrix or vector, not %s" % var.type)
                                    
                                if re.search(r"shared_ptr<", str(var.type)):
                                    var = var["px"].dereference()
                    
                                if var.type.code == gdb.TYPE_CODE_PTR:
                                    var = var.dereference()     # be nice
                    
                                isMatrix = re.search(r"Matrix", str(var.type))
                                if isMatrix:
                                    NX, NY = getEigenMatrixDimensions(var)
                    
                                    if opts.origin:
                                        if len(opts.origin) != 2:
                                            raise gdb.GdbError("Please specify both x0 and y0")
                                            
                                        x0 = gdb.parse_and_eval(opts.origin[0])
                                        y0 = gdb.parse_and_eval(opts.origin[1])
                                    else:
                                        x0, y0 = 0, 0
                                        
                                    nx = opts.nx
                                    ny = opts.ny
                                    if nx == 0:
                                        nx = NX
                                    if ny == 0:
                                        ny = NY
                                        
                                    if nx == 1 and ny == 1:
                                        print "%g" % self._vget(var, x0)
                                        return
                                else:
                                    NX = 0, var["m_storage"]["n"]
                    
                                    if opts.origin:
                                        if len(opts.origin) != 1:
                                            raise gdb.GdbError("Please only specify x0")
                    
                                        x0 = gdb.parse_and_eval(opts.origin[0])
                                    else:
                                        x0 = 0
                                        
                                    nx = opts.nx
                                    if nx == 0:
                                        nx = NX
                    
                                    if nx == 1:
                                        print "%g" % self._vget(var, x0)
                                        return
                                #
                                # OK, finally time to print
                                #
                                if isMatrix:
                                    print "%-4s" % "",
                                    for x in range(x0, min(NX, x0 + nx)):
                                        print "%*d" % (opts.formatWidth, x),
                                    print ""
                    
                                    for y in range(y0, min(NY, y0 + ny)):
                                        print "%-4d" % y,
                                        for x in range(x0, min(NX, x0 + nx)):
                                            print "%*s" % (opts.formatWidth, (opts.dataFmt % self._mget(var, x, y))),
                                        print ""
                                else:
                                    for x in range(x0, min(NX, x0 + nx)):
                                        print "%*s" % (opts.formatWidth, (opts.dataFmt % self._vget(var, x))),
                                    print ""
                    
                        PrintEigenCommand()
                    
                        #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                    
                        class CitizenPrinter(object):
                            "Print a Citizen"
                    
                            def __init__(self, val):
                                self.val = val
                    
                            def to_string(self):
                                sentinel = long(self.val["_sentinel"].cast(gdb.lookup_type("unsigned int")))
                                return "{%s %d 0x%x}" % (self.val.address, self.val["_CitizenId"], sentinel)
                    
                        class PrintCitizenCommand(gdb.Command):
                            """Print a Citizen
                        Usage: show citizen 
                        """
                    
                            def __init__ (self):
                                super (PrintCitizenCommand, self).__init__ ("show citizen",
                                                                            gdb.COMMAND_DATA,
                                                                            gdb.COMPLETE_SYMBOL)
                    
                            def invoke (self, args, fromTty):
                                self.dont_repeat()
                    
                                parser = GdbOptionParser("show citizen")
                                if False:
                                    parser.add_option("object", help="The object in question")
                    
                                    opts =  parser.parse_args(args)
                                    if opts.help:
                                        return
                                else:
                                    opts, args =  parser.parse_args(args)
                                    if opts.help:
                                        return
                                    
                                    if not args:
                                        raise gdb.GdbError("Please specify an object")
                                    opts.object = args.pop(0)
                    
                                    if args:
                                        raise gdb.GdbError("Unrecognised trailing arguments: %s" % " ".join(args))
                                
                                var = gdb.parse_and_eval(opts.object)
                                if re.search(r"shared_ptr<", str(var.type)):
                                    var = var["px"]
                    
                                if var.type.code != gdb.TYPE_CODE_PTR:
                                    var = var.address
                    
                                citizen = var.dynamic_cast(gdb.lookup_type("lsst::daf::base::Citizen").pointer())
                    
                                if not citizen:
                                    raise gdb.GdbError("Failed to cast %s to Citizen -- is it a subclass?" % opts.object)
                                
                                citizen = citizen.dereference()
                    
                                print citizen
                    
                        PrintCitizenCommand()
                    
                        #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                        # afw
                    
                        class BaseSourceAttributesPrinter(object):
                            "Print a BaseSourceAttributes"
                    
                            def __init__(self, val):
                                self.val = val
                    
                            def to_string(self):
                                return "Base: {id=%d astrom=(%.3f, %.3f)}" % (self.val["_id"], self.val["_xAstrom"], self.val["_yAstrom"])
                    
                        class SourcePrinter(object):
                            "Print a Source"
                    
                            def __init__(self, val):
                                self.val = val
                    
                            def to_string(self):
                                return "Source{id=%d astrom=(%.3f, %.3f)}" % (self.val["_id"],
                                                                              self.val["_xAstrom"], self.val["_yAstrom"])
                    
    
    395 6722031e - class cgIdPrinter(object):
    396 6722031e - "Print a cameraGeom::Id"
    397 6722031e -
    398 6722031e - def __init__(self, val):
    399 6722031e - self.val = val
    400 6722031e -
    401 6722031e - def to_string(self):
    402 6722031e - return "Id{%d %s}" % (self.val["_serial"], self.val["_name"])
    403 6722031e -
    class DetectorPrinter(object): "Print a cameraGeom::Detector" def __init__(self, val): self.val = val def to_string(self):
    411 6722031e - return "Detector{%s Centre: %smm %spix %s}" % (self.val["_id"], self.val["_center"]["_p"],
    412 6722031e - self.val["_centerPixel"], self.val["_trimmedAllPixels"])
    402 b9f8baff + return "Detector{name: %s id: %s type: %s bbox: %s}" % (self.val["_name"], self.val["_id"],
    403 b9f8baff + self.val["_type"], self.val["_bbox"])
    class FootprintPrinter(object): "Print a Footprint" def __init__(self, val): self.val = val def to_string(self): if False: nspan = self.val["_spans"]["size"]() # Fails (as its type is METHOD, not CODE) else: vec_impl = self.val["_spans"]["_M_impl"] nspan = vec_impl["_M_finish"] - vec_impl["_M_start"] return "Footprint{id=%d, nspan=%d, area=%d; BBox %s}" % (self.val["_fid"], nspan, self.val["_area"], self.val["_bbox"]) class FootprintSetPrinter(object): "Print a FootprintSet" def __init__(self, val): self.val = val def to_string(self): return "FootprintSet{%s; %s}" % (self.val["_region"], self.val["_footprints"]) class PeakPrinter(object): "Print a Peak" def __init__(self, val): self.val = val def to_string(self): return "Peak{%d, (%.2f, %.2f)}" % (self.val["_id"], self.val["_fx"], self.val["_fy"]) class PsfPrinter(object): "Print a Psf" def to_string(self): return "%s" % (self.typeName()) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class Box2Printer(object): "Print a Box2" def __init__(self, val): self.val = val def to_string(self): # Make sure &foo works, too. type = self.val.type if type.code == gdb.TYPE_CODE_REF: type = type.target () llc = [getEigenValue(self.val["_minimum"]["_vector"], i) for i in range(2)] dims = [getEigenValue(self.val["_dimensions"]["_vector"], i) for i in range(2)] return "Box2{(%s,%s)--(%s,%s)}" % (llc[0], llc[1], llc[0] + dims[0] - 1, llc[1] + dims[1] - 1) def display_hint (self): return "array" class CoordinateBasePrinter(object): "Print a CoordinateBase" def __init__(self, val): self.val = val def to_string(self): return self.val["_vector"]["m_storage"]["m_data"]["array"] def display_hint (self): return "array" #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class AxesPrinter(object): "Print an ellipse::Axes" def __init__(self, val): self.val = val def to_string(self): vec = self.val["_vector"] return "[%g, %g, %g]" % (getEigenValue(vec, 0), getEigenValue(vec, 1), getEigenValue(vec, 2)) class QuadrupolePrinter(object): "Print an ellipse::Quadrupole" def __init__(self, val): self.val = val def to_string(self): mat = self.val["_matrix"] if False: return mat else: return "[[%g, %g], [%g, %g]]" % (getEigenValue(mat, 0, 0), getEigenValue(mat, 0, 1), getEigenValue(mat, 1, 0), getEigenValue(mat, 1, 1)) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ImagePrinter(object): "Print an ImageBase or derived class" def dimenStr(self, val=None): if val is None: val = self.val # Make sure &foo works, too. type = val.type if type.code == gdb.TYPE_CODE_REF: type = type.target() gilView = val["_gilView"] arr = val["_origin"]["_vector"]["m_storage"]["m_data"]["array"] x0, y0 = arr[0], arr[1] return "%dx%d%s%d%s%d" % ( #val["getWidth"](), val["getHeight"](), gilView["_dimensions"]["x"], gilView["_dimensions"]["y"], ["", "+"][x0 >= 0], x0, # i.e. "+" if x0 >= 0 else "" in python >= 2.5 ["", "+"][y0 >= 0], y0) def typeName(self): return self.typename.split(":")[-1] def __init__(self, val): self.typename = str(val.type) self.val = val def to_string(self): return "%s(%s)" % (self.typeName(), self.dimenStr()) class MaskedImagePrinter(ImagePrinter): "Print a MaskedImage" def to_string(self): return "%s(%s)" % (self.typeName(), self.dimenStr(self.val["_image"]["px"].dereference())) class ExposurePrinter(ImagePrinter): "Print an Exposure" def to_string(self): return "%s(%s)" % (self.typeName(), self.dimenStr(self.val["_maskedImage"]["_image"]["px"].dereference())) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class PrintImageCommand(gdb.Command): """Print an Image""" def __init__ (self): super (PrintImageCommand, self).__init__ ("show image", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL) def get(self, var, x, y): if False: return var["operator()(int, int, bool)"](x, y, True) else: dimensions = var["_gilView"]["_dimensions"] if x < 0 or x >= dimensions["x"] or y < 0 or y >= dimensions["y"]: raise gdb.GdbError("Pixel (%d, %d) is out of range 0:%d, 0:%d" % (x, y, dimensions["x"] - 1, dimensions["y"] - 1)) pixels = var["_gilView"]["_pixels"]["_p"] step = pixels["_step_fn"]["_step"]/var.type.template_argument(0).sizeof return pixels["m_iterator"][x + y*step]["_v0"] def invoke (self, args, fromTty): self.dont_repeat() parser = GdbOptionParser("show image" + ("" if argparse else " [ []]")) parser.add_option("-a", "--all", action="store_true", help="Display the whole image/mask") parser.add_option("-c", "--center", type="str", nargs=2, default=(None, None,), help="Center the output at (x, y)") parser.add_option("-o", "--origin", type="str", nargs=2, default=(None, None,), help="Print the region starting at (x, y)") parser.add_option("-x", "--xy0", action="store_true", help="Obey the image's (x0, y0)") parser.add_option("-f", "--formatWidth", type="int", default=8, help="Field width for values") parser.add_option("-d", "--dataFmt", default="%.2f", help="Format for values") if argparse: parser.add_option("image", help="Expression giving image to show") parser.add_option("width", help="Width of patch to print", default=1, nargs="?") parser.add_option("height", help="Height of patch to print", default=1, nargs="?") opts = parser.parse_args(args) if opts.help: return else: opts, args = parser.parse_args(args) if opts.help: return if not args: raise gdb.GdbError("Please specify an image") opts.image = args.pop(0) opts.width, opts.height = 1, 1 if args: opts.width = int(args.pop(0)) if args: opts.height = int(args.pop(0)) if args: raise gdb.GdbError("Unrecognised trailing arguments: %s" % " ".join(args)) for i in range(2): val = "0" if opts.origin[i] is None: if opts.center[i] is not None: val = opts.center[i] else: val = opts.origin[i] if opts.center[i] is not None: raise gdb.GdbError("You may not specify both --center and --origin") val = gdb.parse_and_eval(val) if i == 0: x0 = val else: y0 = val if opts.all: nx, ny = 0, 0 else: nx, ny = opts.width, opts.height var = gdb.parse_and_eval(opts.image) if re.search(r"shared_ptr<", str(var.type)): var = var["px"].dereference() if not re.search(r"(lsst::afw::image::)?(Image|Mask|MaskedImage)", str(var.type.unqualified())): raise gdb.GdbError("Please specify an image, not %s" % var.type) if re.search(r"MaskedImage", str(var.type)) and \ not re.search(r"::Image(\s*&)?$", str(var.type)): print "N.b. %s is a MaskedImage; showing image" % (opts.image) var = var["_image"] if re.search(r"shared_ptr<", str(var.type)): var = var["px"].dereference() if var.type.code == gdb.TYPE_CODE_PTR: var = var.dereference() # be nice pixelTypeName = str(var.type.template_argument(0)) if opts.dataFmt: dataFmt = opts.dataFmt elif pixelTypeName in ["short", "unsigned short"]: dataFmt = "0x%x" elif pixelTypeName in ["int", "unsigned int"]: dataFmt = "%d" else: dataFmt = "%.2f" if nx == 0: nx = var["_gilView"]["_dimensions"]["x"] if ny == 0: ny = var["_gilView"]["_dimensions"]["y"] if opts.center[0]: x0 -= nx//2 y0 -= ny//2 if opts.xy0 and not opts.all: arr = var["_origin"]["_vector"]["m_storage"]["m_data"]["array"] x0 -= arr[0] y0 -= arr[1] # # OK, finally time to print # print "%-4s" % "", for x in range(x0, x0 + nx): print "%*d" % (opts.formatWidth, x), print "" for y in reversed(range(y0, y0 + ny)): print "%-4d" % y, for x in range(x0, x0 + nx): print "%*s" % (opts.formatWidth, dataFmt % self.get(var, x, y)), print "" PrintImageCommand() #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class BackgroundPrinter(object): "Print a Background" def __init__(self, val): self.typename = str(val.type) self.val = val def to_string(self): return "Background(%dx%d) %s %s" % ( self.val["_imgWidth"], self.val["_imgHeight"], self.val["_bctrl"]) class BackgroundControlPrinter(object): "Print a BackgroundControl" def __init__(self, val): self.typename = str(val.type) self.val = val def to_string(self): return "{%s %s %s %s}" % (re.sub(r"lsst::afw::math::Interpolate::", "", str(self.val["_style"])), re.sub(r"lsst::afw::math::", "", str(self.val["_prop"])), re.sub(r"lsst::afw::math::", "", str(self.val["_undersampleStyle"])), self.val["_sctrl"]["px"].dereference()) class KernelPrinter(object): "Print a Kernel" def __init__(self, val): self.typename = str(val.type) self.val = val def to_string(self): return "%s(%dx%d)" % (self.typename, self.val["_width"], self.val["_height"]) class StatisticsControlPrinter(object): "Print a StatisticsControl" def __init__(self, val): self.typename = str(val.type) self.val = val def to_string(self): return "{nSigma=%g nIter=%d ignore=0x%x}" % (self.val["_numSigmaClip"], self.val["_numIter"], self.val["_andMask"]) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class TablePrinter(object): "Print a table::Table" def __init__(self, val): self.typename = str(val.type) self.val = val def to_string(self): return "{schema = %s, md=%s}" % (self.val["_schema"], self.val["_metadata"]) class TableSchemaPrinter(object): "Print a table::Schema" def __init__(self, val): self.typename = str(val.type) self.val = val def to_string(self): names = str(self.val["_impl"]["px"]["_names"]) names = re.sub(r"^[^{]*{|}|[\[\]\"\"]|\s*=\s*[^,]*", "", names) return "%s" % (names) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- printers = [] def register(obj=None): "Register my pretty-printers with objfile Obj." if obj is None: obj = gdb for p in printers: gdb.printing.register_pretty_printer(obj, p, replace=True) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def build_boost_dictionary(): """Surely this must be somewhere standard?""" printer = gdb.printing.RegexpCollectionPrettyPrinter("rhl-boost") printer.add_printer('boost::shared_ptr', '^(boost|tr1|std)::shared_ptr', SharedPtrPrinter) printer.add_printer('boost::gil::pixel', 'boost::gil::.*pixel_t', GilPixelPrinter) return printer printers.append(build_boost_dictionary()) def build_eigen_dictionary(): """Surely this must be somewhere standard?""" printer = gdb.printing.RegexpCollectionPrettyPrinter("rhl-eigen") printer.add_printer('eigen::Matrix', '^Eigen::Matrix', EigenMatrixPrinter) printer.add_printer('eigen::Vector', '^Eigen::Vector', EigenVectorPrinter) return printer printers.append(build_eigen_dictionary()) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def build_afw_dictionary(): printer = gdb.printing.RegexpCollectionPrettyPrinter("afw")
    830 6722031e - printer.add_printer('lsst::afw::cameraGeom::Id',
    831 6722031e - '^lsst::afw::cameraGeom::Id$', cgIdPrinter)
    printer.add_printer('lsst::afw::cameraGeom::Detector', '^lsst::afw::cameraGeom::(Amp|Ccd|Detector|DetectorMosaic)$', DetectorPrinter) printer.add_printer('lsst::afw::detection::Footprint', '^lsst::afw::detection::Footprint$', FootprintPrinter) printer.add_printer('lsst::afw::detection::FootprintSet', '^lsst::afw::detection::FootprintSet', FootprintSetPrinter) printer.add_printer('lsst::afw::detection::Peak', '^lsst::afw::detection::Peak$', PeakPrinter) printer.add_printer('lsst::afw::detection::Psf', '^lsst::afw::detection::Psf$', PsfPrinter) printer.add_printer('lsst::afw::detection::Source', '^lsst::afw::detection::Source$', SourcePrinter) printer.add_printer('lsst::afw::detection::BaseSourceAttributes', '^lsst::afw::detection::BaseSourceAttributes$', BaseSourceAttributesPrinter) printer.add_printer('lsst::afw::geom::Box', '^lsst::afw::geom::Box', Box2Printer) printer.add_printer('lsst::afw::geom::Extent', '^lsst::afw::geom::Extent', CoordinateBasePrinter) printer.add_printer('lsst::afw::geom::Point', '^lsst::afw::geom::Point', CoordinateBasePrinter) printer.add_printer('lsst::afw::geom::ellipses::Axes', '^lsst::afw::geom::ellipses::Axes', AxesPrinter) printer.add_printer('lsst::afw::geom::ellipses::Quadrupole', '^lsst::afw::geom::ellipses::Quadrupole', QuadrupolePrinter) printer.add_printer('lsst::afw::image::ImageBase', 'lsst::afw::image::ImageBase<[^>]+>$', ImagePrinter) printer.add_printer('lsst::afw::image::Image', 'lsst::afw::image::Image<[^>]+>$', ImagePrinter) printer.add_printer('lsst::afw::image::Mask', '^lsst::afw::image::Mask<[^>]+>$', ImagePrinter) printer.add_printer('lsst::afw::image::MaskedImage', '^lsst::afw::image::MaskedImage<[^>]+>$', MaskedImagePrinter) printer.add_printer('lsst::afw::image::Exposure', '^lsst::afw::image::Exposure', ExposurePrinter) printer.add_printer('lsst::afw::math::Background', '^lsst::afw::math::Background$', BackgroundPrinter) printer.add_printer('lsst::afw::math::BackgroundControl', '^lsst::afw::math::BackgroundControl$', BackgroundControlPrinter) printer.add_printer('lsst::afw::math::Kernel', '^lsst::afw::math::.*Kernel', KernelPrinter) printer.add_printer('lsst::afw::math::StatisticsControl', '^lsst::afw::math::StatisticsControl', StatisticsControlPrinter) printer.add_printer('lsst::afw::table::Table', '^lsst::afw::table::.*Table$', TablePrinter) printer.add_printer('lsst::afw::table::Schema', '^lsst::afw::table::Schema$', TableSchemaPrinter) return printer printers.append(build_afw_dictionary()) def build_daf_base_dictionary(): printer = gdb.printing.RegexpCollectionPrettyPrinter("daf::base") printer.add_printer('lsst::daf::base::Citizen', 'lsst::daf::base::Citizen', CitizenPrinter) return printer printers.append(build_daf_base_dictionary()) except ImportError, e: print "RHL", e from printers_oldgdb import *

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6722031e

    commit 6722031e89f80b33f44eebb43195b3cc160db7fc
    Author: Robert Lupton the Good 
    Date:   Fri Feb 17 13:13:23 2012 -0500
    
        Added Detector pretty printer
    

    Commits in /Users/nate/repos_lsst/afw/

    b9f8baff

    commit b9f8baff159500cc0451ddb82eb2b0715fe66396
    Author: Russell Owen 
    Date:   Tue Mar 11 15:22:54 2014 -0700
    
        Improve documentation of DetectorWrapper (especially constructor argument types).
        Update gdb printer for CameraGeom changes.
    

    Return to list

    python/lsst/afw/cameraGeom/init.py

    Diff:

                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    
                    """Application Framework classes to handle a mosaic camera's geometry
                    """
    
    25 d8db2778 - from cameraGeomLib import *
    25 8cea9ad2 + from .cameraGeomLib import *
    ? +
    26 8cea9ad2 + from .cameraConfig import *
    27 8cea9ad2 + from .detectorCollection import *
    28 8cea9ad2 + from .camera import *
    29 7c7144b0 + from .cameraConfig import *
    30 f6e303b1 + from .cameraFactory import *
    31 c575c8cf + from .cameraGeomEnumDicts import *
    32 c575c8cf + from .makePixelToTanPixel import *
    33 9372e552 + from .assembleImage import *
    34 322ab936 + from .rotateBBoxBy90 import *

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d8db2778

    commit d8db2778553cfde55e65aa366b2f8a91e7932d48
    Author: rhl 
    Date:   Tue Jan 5 22:53:38 2010 +0000
    
        Added a missing __init__.py; Switched all afwImage::Points to afwGeom::Points
    

    Commits in /Users/nate/repos_lsst/afw/

    f6e303b1

    commit f6e303b125a3f1d2a8184b0ebe408254dd5c2402
    Author: Simon Krughoff 
    Date:   Wed Mar 12 18:37:25 2014 -0500
    
        Changes to address code review from Jim
    

    8cea9ad2

    commit 8cea9ad2e43b75b6765b8d43c9a5d2b2d7bc4efa
    Author: Simon Krughoff 
    Date:   Wed Feb 19 21:09:15 2014 -0600
    
        Python code for building cameras.
    

    322ab936

    commit 322ab936a503294f4239a71591f68cdf4358858c
    Author: Russell Owen 
    Date:   Wed Mar 5 09:50:34 2014 -0800
    
        Move rotateBBoxBy90 out of __init__.py
        Change run methods in CameraFactoryTask to share more code.
    

    9372e552

    commit 9372e55278b23ff8990145914b5807675b26d769
    Author: Simon Krughoff 
    Date:   Tue Mar 4 18:29:47 2014 -0600
    
        More work on cameraGeom.utils and the camera geom unit test
    

    7c7144b0

    commit 7c7144b09d8838393f1f1cc2f7fabd0d034df19c
    Author: Russell Owen 
    Date:   Tue Feb 25 10:56:44 2014 -0800
    
        Reversed the direction of transforms in TransformMap: forward is now native -> other.
        This seems to match our use cases for CameraGeom better.
        Orientation.makeFpPixelTransform now returns an AffineXYTransform.
    

    c575c8cf

    commit c575c8cfcc876de7853dac12b2394d877238b888
    Author: Russell Owen 
    Date:   Tue Mar 4 15:46:49 2014 -0800
    
        Added makePixelToTanPixel function and a test for it.
    

    Return to list

    python/lsst/afw/table/Exposure.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    /*
                     * Wrappers for ExposureTable, ExposureRecord, and ExposureCatalog (and, via Base.i, their dependencies).
                     *
                     * This file does not include Simple- or Source- Record/Table/Catalog, or the matching functions.
                     */
                    
                    %include "lsst/afw/table/Base.i"
                    
                    %{
                    #include "lsst/afw/table/Exposure.h"
                    %}
                    
                    namespace lsst { namespace afw { namespace image {
                    class Wcs;
                    class Calib;
                    }
                    namespace detection {
                    class Psf;
                    }
                    }}
                    %shared_ptr(lsst::afw::image::Wcs);
                    %shared_ptr(lsst::afw::image::Calib);
    
    45 18d4b1ff - %shared_ptr(lsst::afw::image::ApCorrMap);
    %shared_ptr(lsst::afw::detection::Psf);
    47 fd15d1dd - %shared_ptr(lsst::afw::geom::polygon::Polygon)
    // =============== ExposureTable and ExposureRecord ========================================================= %shared_ptr(lsst::afw::table::ExposureTable) %shared_ptr(lsst::afw::table::ExposureRecord) %include "lsst/afw/table/Exposure.h" %addCastMethod(lsst::afw::table::ExposureTable, lsst::afw::table::BaseTable) %addCastMethod(lsst::afw::table::ExposureRecord, lsst::afw::table::BaseRecord) %template(ExposureColumnView) lsst::afw::table::ColumnViewT; // =============== Catalogs ================================================================================= %include "lsst/afw/table/SortedCatalog.i" namespace lsst { namespace afw { namespace table { template class ExposureCatalogT : public SortedCatalogT { public: typedef typename RecordT::Table Table; explicit ExposureCatalogT(PTR(Table) const & table); explicit ExposureCatalogT(Schema const & table); ExposureCatalogT(ExposureCatalogT const & other); %feature( "autodoc", "Constructors: __init__(self, table) -> empty catalog with the given table\n" " __init__(self, schema) -> empty catalog with a new table with the given schema\n" " __init__(self, catalog) -> shallow copy of the given catalog\n" ) SortedCatalogT; static ExposureCatalogT readFits(std::string const & filename, int hdu=0, int flags=0); static ExposureCatalogT readFits(fits::MemFileManager & manager, int hdu=0, int flags=0); ExposureCatalogT subset(ndarray::Array const & mask) const; ExposureCatalogT subset(std::ptrdiff_t start, std::ptrdiff_t stop, std::ptrdiff_t step) const;
    92 b1eace8a - ExposureCatalogT subsetContaining(Coord const & coord, bool includeValidPolygon=false) const;
    ? --------------------------------
    90 38ad08ad + ExposureCatalogT subsetContaining(Coord const & coord) const;
    93 b1eace8a - ExposureCatalogT subsetContaining(geom::Point2D const & point, image::Wcs const & wcs,
    ? ^
    91 38ad08ad + ExposureCatalogT subsetContaining(geom::Point2D const & point, image::Wcs const & wcs) const;
    ? ^^^^^^^^
    94 b1eace8a - bool includeValidPolygon=false) const;
    }; %pythondynamic; %template (_ExposureCatalogBase) CatalogT; %template (_ExposureCatalogSortedBase) SortedCatalogT; %pythonnondynamic; %declareCatalog(ExposureCatalogT, Exposure) }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    fd15d1dd

    commit fd15d1dd03c8a1d1b06864fe90ad7d962bc7e567
    Author: Bob Armstrong 
    Date:   Mon Sep 15 08:34:26 2014 -0400
    
        Exposure: Add a Polygon object to Exposure.
        
        Polygons will be used to define valid regions for each CCD to
        reject vignetted regions when building the Coadd Psf.
    

    b1eace8a

    commit b1eace8a7638ea7da5a900139e30cc162734533c
    Author: Paul Price 
    Date:   Fri Dec 19 21:24:16 2014 +0000
    
        ExposureCatalogT: additional arguments for subsetContaining in SWIG
        
        The header file had been updated with the additional arguments, but
        the SWIG interface file doesn't read that.
    

    18d4b1ff

    commit 18d4b1ff87ba59ac01d68d655548a78c2a04ac9f
    Author: Jim Bosch 
    Date:   Tue Jun 3 18:05:37 2014 -0400
    
        Add ApCorrMap to ExposureRecord
    

    Commits in /Users/nate/repos_lsst/afw/

    38ad08ad

    commit 38ad08ad2101e9cc2f59a107b39c5baad77c1c82
    Author: Jim Bosch 
    Date:   Thu Feb 28 12:52:12 2013 +0900
    
        Minor fixes to reflect code review for #2467.
        
        Removed trailing whitespace.
        Renamed ExposureCatalog::findContains to subsetContaining.
        Miscellaneous doc fixes.
        Added check on input sizes in SchemaMapper::join.
        OutputArchive::put overloads needed to forward permissive flag when delegating.
    

    Return to list

    include/lsst/afw/math/ConvolveImage.h

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    #ifndef LSST_AFW_MATH_CONVOLVEIMAGE_H
                    #define LSST_AFW_MATH_CONVOLVEIMAGE_H
                    /**
                     * @file
                     *
                     * @brief Convolve and convolveAtAPoint functions for Image and Kernel
                     *
                     * @todo Consider adding a flag to convolve indicating which specialized version of basicConvolve was used.
                     *   This would only be used for unit testing and trace messages suffice (barely), so not a high priority.
                     *
                     * @author Russell Owen
                     *
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/gpu/DevicePreference.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    
                        /**
                         * @brief Parameters to control convolution
                         *
                         * @ingroup afw
                         */
                        class ConvolutionControl {
                        public:
                            ConvolutionControl(
                                    bool doNormalize = true,    ///< normalize the kernel to sum=1?
                                    bool doCopyEdge = false,    ///< copy edge pixels from source image
                                        ///< instead of setting them to the standard edge pixel?
                                    int maxInterpolationDistance = 10,  ///< maximum width or height of a region
                                        ///< over which to use linear interpolation interpolate
                                    lsst::afw::gpu::DevicePreference devicePreference = lsst::afw::gpu::DEFAULT_DEVICE_PREFERENCE  ///<
                                        ///< use Gpu acceleration?
                                    )
                            :
                                _doNormalize(doNormalize),
                                _doCopyEdge(doCopyEdge),
                                _maxInterpolationDistance(maxInterpolationDistance),
                                _devicePreference(devicePreference)
                            { }
                    
                            bool getDoNormalize() const { return _doNormalize; }
                            bool getDoCopyEdge() const { return _doCopyEdge; }
                            int getMaxInterpolationDistance() const { return _maxInterpolationDistance; };
                            lsst::afw::gpu::DevicePreference getDevicePreference() const { return _devicePreference; };
                    
                            void setDoNormalize(bool doNormalize) {_doNormalize = doNormalize; }
                            void setDoCopyEdge(bool doCopyEdge) { _doCopyEdge = doCopyEdge; }
                            void setMaxInterpolationDistance(int maxInterpolationDistance) {
                                _maxInterpolationDistance = maxInterpolationDistance; }
                            void setDevicePreference(lsst::afw::gpu::DevicePreference devicePreference) { _devicePreference = devicePreference; }
                    
                        private:
                            bool _doNormalize;  ///< normalize the kernel to sum=1?
                            bool _doCopyEdge;   ///< copy edge pixels from source image
                                        ///< instead of setting them to the standard edge pixel?
                            int _maxInterpolationDistance;  ///< maximum width or height of a region
                                        ///< over which to attempt interpolation
                            lsst::afw::gpu::DevicePreference _devicePreference; ///< choose CPU or GPU acceleration
                        };
                    
                        template 
                        void scaledPlus(
                                OutImageT &outImage,
                                double c1,
                                InImageT const &inImage1,
                                double c2,
                                InImageT const &inImage2);
                    
                        template 
                        inline typename OutImageT::SinglePixel convolveAtAPoint(
                                typename InImageT::const_xy_locator inImageLocator,
                                typename lsst::afw::image::Image::const_xy_locator kernelLocator,
                                int kWidth,
                                int kHeight);
                    
                        template 
                        inline typename OutImageT::SinglePixel convolveAtAPoint(
                                typename InImageT::const_xy_locator inImageLocator,
                                std::vector const& kernelColList,
                                std::vector const& kernelRowList);
                    
                        template 
                        void convolve(
                                OutImageT& convolvedImage,
                                InImageT const& inImage,
                                KernelT const& kernel,
                                ConvolutionControl const& convolutionControl = ConvolutionControl());
                    
                        template 
                        void convolve(
                                OutImageT& convolvedImage,
                                InImageT const& inImage,
                                KernelT const& kernel,
                                bool doNormalize,
                                bool doCopyEdge = false);
                    
                        /**
    
    133 73fb00fd - * \brief Return an off-the-edge pixel appropriate for a given Image type
    ? --------
    133 84d4fa7d + * \brief Return an edge pixel appropriate for a given Image type
    * * The value is quiet_NaN if that exists for the pixel type, else 0 */ template typename ImageT::SinglePixel edgePixel( lsst::afw::image::detail::Image_tag ///< lsst::afw::image::detail::image_traits::image_category() ) { typedef typename ImageT::SinglePixel SinglePixelT; return SinglePixelT( std::numeric_limits::has_quiet_NaN ? std::numeric_limits::quiet_NaN() : 0); } /**
    149 73fb00fd - * \brief Return an off-the-edge pixel appropriate for a given MaskedImage type
    ? --------
    149 84d4fa7d + * \brief Return an edge pixel appropriate for a given MaskedImage type
    * * The components are: * - %image = quiet_NaN if that exists for the pixel type, else 0
    153 73fb00fd - * - mask = NO_DATA bit set
    ? ^^^ ^^^
    153 9272a4ae + * - mask = EDGE bit set
    ? ^ ^^ * - variance = infinity */ template typename MaskedImageT::SinglePixel edgePixel( lsst::afw::image::detail::MaskedImage_tag ///< lsst::afw::image::detail::image_traits::image_category() ) { typedef typename MaskedImageT::Image::Pixel ImagePixelT; typedef typename MaskedImageT::Variance::Pixel VariancePixelT; return typename MaskedImageT::SinglePixel( std::numeric_limits::has_quiet_NaN ? std::numeric_limits::quiet_NaN() : 0,
    167 73fb00fd - MaskedImageT::Mask::getPlaneBitMask("NO_DATA"),
    ? ^^^ ^^^
    167 84d4fa7d + MaskedImageT::Mask::getPlaneBitMask("EDGE"),
    ? ^ ^^ std::numeric_limits::infinity()); } }}} // lsst::afw::math /* * Define inline functions */ /** * @brief Apply convolution kernel to an %image at one point * * @note This subroutine sacrifices convenience for performance. The user is expected to figure out * the kernel center and adjust the supplied pixel accessors accordingly. * For an example of how to do this see convolve(). * * @ingroup afw */ template inline typename OutImageT::SinglePixel lsst::afw::math::convolveAtAPoint( typename InImageT::const_xy_locator inImageLocator, ///< locator for %image pixel that overlaps ///< pixel (0,0) of kernel (the origin of the kernel, not its center) lsst::afw::image::Image::const_xy_locator kernelLocator, ///< locator for (0,0) pixel of kernel (the origin of the kernel, not its center) int kWidth, ///< number of columns in kernel int kHeight) ///< number of rows in kernel { typename OutImageT::SinglePixel outValue = 0; for (int kRow = 0; kRow != kHeight; ++kRow) { for (lsst::afw::image::Image::const_xy_locator kEnd = kernelLocator + lsst::afw::image::detail::difference_type(kWidth, 0); kernelLocator != kEnd; ++inImageLocator.x(), ++kernelLocator.x()) { typename lsst::afw::math::Kernel::Pixel const kVal = kernelLocator[0]; if (kVal != 0) { outValue += *inImageLocator*kVal; } } inImageLocator += lsst::afw::image::detail::difference_type(-kWidth, 1); kernelLocator += lsst::afw::image::detail::difference_type(-kWidth, 1); } return outValue; } /** * @brief Apply separable convolution kernel to an %image at one point * * @note This subroutine sacrifices convenience for performance. The user is expected to figure out * the kernel center and adjust the supplied pixel accessors accordingly. * For an example of how to do this see convolve(). * * @ingroup afw */ template inline typename OutImageT::SinglePixel lsst::afw::math::convolveAtAPoint( typename InImageT::const_xy_locator inImageLocator, ///< locator for %image pixel that overlaps ///< pixel (0,0) of kernel (the origin of the kernel, not its center) std::vector const &kernelXList, ///< kernel column vector std::vector const &kernelYList) ///< kernel row vector { typedef typename std::vector::const_iterator k_iter; typedef typename OutImageT::SinglePixel OutT; OutT outValue = 0; for (k_iter kernelYIter = kernelYList.begin(), yEnd = kernelYList.end(); kernelYIter != yEnd; ++kernelYIter) { OutT outValueY = 0; for (k_iter kernelXIter = kernelXList.begin(), xEnd = kernelXList.end(); kernelXIter != xEnd; ++kernelXIter, ++inImageLocator.x()) { typename lsst::afw::math::Kernel::Pixel const kValX = *kernelXIter; if (kValX != 0) { outValueY += *inImageLocator*kValX; } } double const kValY = *kernelYIter; if (kValY != 0) { outValue += outValueY*kValY; } inImageLocator += lsst::afw::image::detail::difference_type(-kernelXList.size(), 1); } return outValue; } #endif // !defined(LSST_AFW_MATH_CONVOLVEIMAGE_H)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    73fb00fd

    commit 73fb00fd8b3533247dad52e9a46e2470b77fe48f
    Author: Paul Price 
    Date:   Thu May 22 11:08:42 2014 -0400
    
        add NO_DATA mask plane, and use in warping/convolution
        
        The EDGE mask plane was originally intended to mean "pixel near the
        edge of the detector, so we haven't been able to properly convolve to
        search for sources", but it was hijacked to mean "pixels in a warped
        image that are off the edge of the original".  It has since had both
        meanings, which should be distinct.
        
        We introduce the NO_DATA mask plane to mean "pixels off the edge of
        the original", and reserve "EDGE" to mean "pixels near the edge".
        afw::math::edgePixel (used for pixels with no good inputs when
        warping) now returns a value for pixels *off* the edge (should it
        be renamed? but that's changing a public API).  Convolution now
        masks pixels near the edge as EDGE if copying edge pixels, and
        NO_DATA otherwise.
    

    Commits in /Users/nate/repos_lsst/afw/

    84d4fa7d

    commit 84d4fa7def01e40f6674bb7ebd2eca93cd7b2741
    Merge: 19ed381 846aff9
    Author: rowen 
    Date:   Thu May 14 00:07:00 2009 +0000
    
        Implemented warpImage, including unit tests.
        Note:
        - The new unit tests show some disagreement with swarp around bad columns;
          this was masked by bad pixels in the MaskedImage tests.
        - Edge pixels have value (NaN, EDGE, infinity), based on ticket #806 and as implemented by new
          edgePixel function. This is a change from the trunk, so I prefer to hold off merging
          this ticket to the trunk until after DC3a. (If necessary we can hack the edgePixel method
          to match the old behavior, but I would prefer to wait if we can.)
          Hence it is probably not safe to merge to the trunk until after DC3a.
        - The convolve functions have not yet been modified to use the new edge pixel function;
          (ticket #806); this will involve removing the edge bit mask argument.
    

    9272a4ae

    commit 9272a4ae115a300c24474a2834c5b277bc0cc021
    Author: rowen 
    Date:   Wed Jul 8 21:20:41 2009 +0000
    
        Improved documentation of convolution and image/exposure warping
        including adding links from the Mathematical Operations page.
    

    Return to list

    tests/sourceMatch1.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #define BOOST_TEST_DYN_LINK
                    #define BOOST_TEST_MODULE SourceMatch
                    
                    #include 
                    
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/test/unit_test.hpp"
                    #pragma clang diagnostic pop
                    #include "boost/test/floating_point_comparison.hpp"
                    
                    #include "lsst/afw/table/Source.h"
                    #include "lsst/afw/table/Match.h"
                    #include "lsst/afw/math/Random.h"
    
    39 54624a89 - #include "lsst/afw/coord/Utils.h"
    #include "lsst/afw/geom/Angle.h" namespace math = lsst::afw::math; namespace coord = lsst::afw::coord; namespace afwGeom = lsst::afw::geom; namespace afwTable = lsst::afw::table; namespace { math::Random & rng() { static math::Random * generator = 0; if (generator == 0) { generator = new math::Random(math::Random::MT19937); } return *generator; } PTR(afwTable::SourceTable) getGlobalTable() { static PTR(afwTable::SourceTable) table; if (!table) { afwTable::Schema schema = afwTable::SourceTable::makeMinimalSchema();
    60 bd692192 + schema.setVersion(0);
    afwTable::addCentroidFields(schema, "centroid", "dummy centroid"); table = afwTable::SourceTable::make(schema); table->defineCentroid("centroid"); } return table; } // Randomly generate a set of sources that are uniformly distributed across // the unit sphere (ra/dec space) and the unit box (x,y space). void makeSources(afwTable::SourceCatalog &set, int n) { for (int i = 0; i < n; ++i) { PTR(afwTable::SourceRecord) src = set.addNew(); src->setId(i); src->set(set.getTable()->getCentroidKey(), afwGeom::Point2D(rng().uniform(), rng().uniform())); double z = rng().flat(-1.0, 1.0); src->set(afwTable::SourceTable::getCoordKey().getRa(), rng().flat(0.0, 360.) * afwGeom::degrees); src->set(afwTable::SourceTable::getCoordKey().getDec(), std::asin(z) * afwGeom::radians); } } struct CmpSourceMatch { bool operator()(afwTable::SourceMatch const &m1, afwTable::SourceMatch const &m2) { if (m1.first->getId() == m2.first->getId()) { return m1.second->getId() < m2.second->getId(); } return m1.first->getId() < m2.first->getId(); } }; struct DistRaDec { double operator()(PTR(afwTable::SourceRecord) const &s1, PTR(afwTable::SourceRecord) const &s2) const { // halversine distance formula double sinDeltaRa = std::sin(0.5*(s2->getRa() - s1->getRa())); double sinDeltaDec = std::sin(0.5*(s2->getDec() - s1->getDec())); double cosDec1CosDec2 = std::cos(s1->getDec())*std::cos(s2->getDec()); double a = sinDeltaDec*sinDeltaDec + cosDec1CosDec2*sinDeltaRa*sinDeltaRa; double b = std::sqrt(a); double c = b > 1 ? 1 : b; // radians return 2.0 * std::asin(c); } }; struct DistXy { double operator()(PTR(afwTable::SourceRecord) const &s1, PTR(afwTable::SourceRecord) const &s2) const { double dx = s2->getX() - s1->getX(); double dy = s2->getY() - s1->getY(); return std::sqrt(dx*dx + dy*dy); } }; template std::vector bruteMatch(afwTable::SourceCatalog const &set, double radius, DistFunctorT const &distFun) { std::vector matches; for (afwTable::SourceCatalog::const_iterator i1(set.begin()), e(set.end()); i1 != e; ++i1) { for (afwTable::SourceCatalog::const_iterator i2(i1); i2 != e; ++i2) { if (i1 == i2) { continue; } double d = distFun(i1, i2); if (d <= radius) { matches.push_back(afwTable::SourceMatch(i1, i2, d)); matches.push_back(afwTable::SourceMatch(i2, i1, d)); } } } return matches; } template std::vector bruteMatch(afwTable::SourceCatalog const &set1, afwTable::SourceCatalog const &set2, double radius, DistFunctorT const &distFun) { if (&set1 == &set2) { return bruteMatch(set1, radius, distFun); } std::vector matches; for (afwTable::SourceCatalog::const_iterator i1(set1.begin()), e1(set1.end()); i1 != e1; ++i1) { for (afwTable::SourceCatalog::const_iterator i2(set2.begin()), e2(set2.end()); i2 != e2; ++i2) { double d = distFun(i1, i2); if (d <= radius) { matches.push_back(afwTable::SourceMatch(i1, i2, d)); } } } return matches; } // The distance computation for the brute-force and actual match algorithm is different, // so we cannot naively test whether both match lists are identical. Instead, check // that any tuple in one result set but not the other has a match distance very close // to the match radius. void compareMatches(std::vector &matches, std::vector &refMatches, double radius) { double const tolerance = 1e-6; // 1 micro arcsecond CmpSourceMatch lessThan; std::sort(matches.begin(), matches.end(), lessThan); std::sort(refMatches.begin(), refMatches.end(), lessThan); std::vector::const_iterator i(matches.begin()); std::vector::const_iterator j(refMatches.begin()); std::vector::const_iterator const iend(matches.end()); std::vector::const_iterator const jend(refMatches.end()); while (i < iend && j < jend) { if (lessThan(*i, *j)) { BOOST_CHECK(std::fabs(i->distance - radius) <= tolerance); ++i; } else if (lessThan(*j, *i)) { BOOST_CHECK(std::fabs(j->distance - radius) <= tolerance); ++j; } else { BOOST_CHECK(std::fabs(i->distance - j->distance) <= tolerance); ++i; ++j; } } for (; i < iend; ++i) { BOOST_CHECK(std::fabs(i->distance - radius) <= tolerance); } for (; j < jend; ++j) { BOOST_CHECK(std::fabs(j->distance - radius) <= tolerance); } } } // namespace BOOST_AUTO_TEST_CASE(matchRaDec) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ int const N = 500; // # of points to generate double const M = 8.0; // avg. # of matches afwGeom::Angle radius = std::acos(1.0 - 2.0*M/N) * afwGeom::radians; afwTable::SourceCatalog set1(getGlobalTable()), set2(getGlobalTable()); makeSources(set1, N); makeSources(set2, N); std::vector matches = afwTable::matchRaDec(set1, set2, radius, false); std::vector refMatches = bruteMatch(set1, set2, radius, DistRaDec()); compareMatches(matches, refMatches, radius); } BOOST_AUTO_TEST_CASE(matchSelfRaDec) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ int const N = 500; // # of points to generate double const M = 8.0; // avg. # of matches afwGeom::Angle radius = std::acos(1.0 - 2.0*M/N) * afwGeom::radians; afwTable::SourceCatalog set(getGlobalTable()); makeSources(set, N); std::vector matches = afwTable::matchRaDec(set, radius, true); std::vector refMatches = bruteMatch(set, radius, DistRaDec()); compareMatches(matches, refMatches, radius); } BOOST_AUTO_TEST_CASE(matchXy) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ int const N = 500; // # of points to generate double const M = 8.0; // avg. # of matches double const radius = std::sqrt(M/(afwGeom::PI*static_cast(N))); afwTable::SourceCatalog set1(getGlobalTable()), set2(getGlobalTable()); makeSources(set1, N); makeSources(set2, N); std::vector matches = afwTable::matchXy(set1, set2, radius, false); std::vector refMatches = bruteMatch(set1, set2, radius, DistXy()); compareMatches(matches, refMatches, radius); } BOOST_AUTO_TEST_CASE(matchSelfXy) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ int const N = 500; // # of points to generate double const M = 8.0; // avg. # of matches double const radius = std::sqrt(M/(afwGeom::PI*static_cast(N))); afwTable::SourceCatalog set(getGlobalTable()); makeSources(set, N); std::vector matches = afwTable::matchXy(set, radius, true); std::vector refMatches = bruteMatch(set, radius, DistXy()); compareMatches(matches, refMatches, radius); } static void normalizeRaDec(afwTable::SourceCatalog & ss) { for (size_t i=0; i afwGeom::HALFPI) { d = afwGeom::PI - d; r = r + afwGeom::PI; } ss[i].set(afwTable::SourceTable::getCoordKey().getRa(), r * afwGeom::radians); ss[i].set(afwTable::SourceTable::getCoordKey().getDec(), d * afwGeom::radians); } } BOOST_AUTO_TEST_CASE(matchNearPole) { afwTable::SourceCatalog set1(getGlobalTable()); afwTable::SourceCatalog set2(getGlobalTable()); // for each source, add a true match right on top, plus one within range // and one outside range in each direction. afwGeom::Angle rad = 0.1 * afwGeom::degrees; int id1 = 0; int id2 = 1000000; for (double j=0.1; j<1; j+=0.1) { for (int i=0; i<360; i+=45) { afwGeom::Angle ra = i * afwGeom::degrees; afwGeom::Angle dec = (90 - j) * afwGeom::degrees; afwGeom::Angle ddec1 = rad; afwGeom::Angle dra1 = rad / cos(dec); afwGeom::Angle ddec2 = 2. * rad; afwGeom::Angle dra2 = 2. * rad / cos(dec); PTR(afwTable::SourceRecord) src1 = set1.addNew(); src1->setId(id1); id1++; src1->set(afwTable::SourceTable::getCoordKey().getRa(), ra); src1->set(afwTable::SourceTable::getCoordKey().getDec(), dec); // right on top PTR(afwTable::SourceRecord) src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec); // +Dec 1 src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec + ddec1); // +Dec 2 src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec + ddec2); // -Dec 1 src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec - ddec1); // -Dec 2 src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec - ddec2); // +RA 1 src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra + dra1); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec); // +RA 2 src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra + dra2); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec); // -RA 1 src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra - dra1); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec); // -RA 2 src2 = set2.addNew(); src2->setId(id2); id2++; src2->set(afwTable::SourceTable::getCoordKey().getRa(), ra - dra2); src2->set(afwTable::SourceTable::getCoordKey().getDec(), dec); } } normalizeRaDec(set1); normalizeRaDec(set2); std::vector matches = afwTable::matchRaDec(set1, set2, rad, false); std::vector refMatches = bruteMatch(set1, set2, rad, DistRaDec()); compareMatches(matches, refMatches, rad); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    54624a89

    commit 54624a892718174de7765abd1c41bd4cd3935445
    Author: dstn 
    Date:   Tue Apr 19 15:32:08 2011 +0000
    
        add failing north-pole test case
    

    Commits in /Users/nate/repos_lsst/afw/

    bd692192

    commit bd692192367d33bb64a79ca008bff10eb9b41932
    Author: pgee 
    Date:   Mon Aug 18 15:06:04 2014 -0700
    
        Move API version number from BaseTable to Schema
        
        In FitsReader, move reading the AFW_TABLE_VERSION header key into the
        Schema-from-metadata constructor.
        In FitsWriter, use the version attached to the table schema to write the
        metadata.
    

    Return to list

    tests/minimize.py

    Diff:

    1 9881fc3c - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import unittest import numpy import lsst.utils.tests as utilsTests import lsst.afw.math as afwMath
    32 9881fc3c -
    33 9881fc3c - __all__ = ["computePsfMatchingKernelForMaskedImage"]
    class MinimizeTestCase(unittest.TestCase): def testMinimize2(self): variances = numpy.array([0.01, 0.01, 0.01, 0.01]) xPositions = numpy.array([0.0, 1.0, 0.0, 1.0]) yPositions = numpy.array([0.0, 0.0, 1.0, 1.0]) polyOrder = 1 polyFunc = afwMath.PolynomialFunction2D(polyOrder) modelParams = [0.1, 0.2, 0.3] polyFunc.setParameters(modelParams) measurements = [] for x, y in zip(xPositions, yPositions): measurements.append(polyFunc(x, y)) print "measurements=", measurements # Set up initial guesses nParameters = polyFunc.getNParameters() initialParameters = numpy.zeros(nParameters, float) stepsize = numpy.ones(nParameters, float) stepsize *= 0.1 # Minimize! fitResults = afwMath.minimize( polyFunc, initialParameters, stepsize, measurements, variances, xPositions, yPositions, 0.1, ) print "modelParams=", modelParams print "fitParams =", fitResults.parameterList self.assert_(fitResults.isValid, "fit failed") if not numpy.allclose(modelParams, fitResults.parameterList): self.fail("fit not accurate") #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(MinimizeTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) if __name__ == "__main__": utilsTests.run(suite())

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9881fc3c

    commit 9881fc3c67e22bcc4da7a682a235681a5579dd43
    Author: rowen 
    Date:   Mon Oct 22 18:52:40 2007 +0000
    
        Merged ticket 190
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    src/detection/Footprint.cc

    Diff:

                    /* 
                     * LSST Data Management System
    
    3 a6d55f08 - * Copyright 2008, 2009, 2010 LSST Corporation.
    ? ^^^^^^^^ ^
    3 c839d0f2 + * Copyright 2008-2015 LSST Corporation.
    ? ^ ^ * * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the LSST License Statement and * the GNU General Public License along with this program. If not, * see . */ /*****************************************************************************/ /** \file * * \brief Footprint and associated classes */ #include #include #include #include #include "boost/format.hpp" #include "lsst/pex/logging/Trace.h" #include "lsst/pex/exceptions.h" #include "lsst/afw/image/Mask.h" #include "lsst/afw/math/Kernel.h" #include "lsst/afw/math/KernelFunctions.h" #include "lsst/afw/detection/Footprint.h" #include "lsst/afw/detection/FootprintFunctor.h" #include "lsst/afw/detection/FootprintSet.h" #include "lsst/afw/geom/Point.h" #include "lsst/afw/geom/ellipses/PixelRegion.h" #include "lsst/afw/table/io/CatalogVector.h" #include "lsst/afw/table/io/InputArchive.h" #include "lsst/afw/table/io/OutputArchive.h" #include "lsst/utils/ieee.h" namespace lsst { namespace afw { namespace detection { // anonymous namespace namespace { /* * Compare two Span%s by y, then x0, then x1 * * A utility functor passed to sort; needed to dereference the boost::shared_ptrs. */ struct compareSpanByYX : public std::binary_function { int operator()(Span::ConstPtr a, Span::ConstPtr b) { return (*a) < (*b); } }; /// Transform x,y in the frame of one image to another, via their WCSes geom::Point2D transformPoint(double x, double y, image::Wcs const& source, image::Wcs const& target){ return target.skyToPixel(*source.pixelToSky(x, y)); } } //end namespace /*****************************************************************************/ /// Counter for Footprint IDs int Footprint::id = 0;
    81 f8edfe90 - /**
    82 f8edfe90 - * Create a Footprint
    83 f8edfe90 - *
    84 3771b5eb - * \throws lsst::pex::exceptions::InvalidParameterException in nspan is < 0
    85 f8edfe90 - */
    Footprint::Footprint(
    87 17d1d529 - int nspan, //!< initial number of Span%s in this Footprint
    88 c9c89e06 - geom::Box2I const & region //!< Bounding box of MaskedImage footprint
    82 94770baf + int nspan,
    83 94770baf + geom::Box2I const & region
    ) : lsst::daf::base::Citizen(typeid(this)), _fid(++id), _area(0), _bbox(geom::Box2I()), _peaks(PeakTable::makeMinimalSchema()), _region(region), _normalized(true) { if (nspan < 0) { throw LSST_EXCEPT(
    99 17d1d529 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    94 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("Number of spans requested is -ve: %d") % nspan)); } } /** * Create a Footprint, using a custom Schema for Peaks *
    107 a64e361f - * \throws lsst::pex::exceptions::InvalidParameterException in nspan is < 0
    102 c12d3b48 + * \throws lsst::pex::exceptions::InvalidParameterError Exception in nspan is < 0
    ? ++++++ */ Footprint::Footprint( afw::table::Schema const & peakSchema, //!< Schema to use for PeakRecords int nspan, //!< initial number of Span%s in this Footprint geom::Box2I const & region //!< Bounding box of MaskedImage footprint ) : lsst::daf::base::Citizen(typeid(this)), _fid(++id), _area(0), _bbox(geom::Box2I()), _peaks(peakSchema), _region(region), _normalized(true) { if (nspan < 0) { throw LSST_EXCEPT(
    123 a64e361f - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    118 c12d3b48 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("Number of spans requested is -ve: %d") % nspan)); } } /** * Create a rectangular Footprint */ Footprint::Footprint( geom::Box2I const& bbox, //!< The bounding box defining the rectangle geom::Box2I const& region //!< Bounding box of MaskedImage footprint ) : lsst::daf::base::Citizen(typeid(this)), _fid(++id), _area(0), _bbox(bbox), _peaks(PeakTable::makeMinimalSchema()), _region(region) { int const x0 = bbox.getMinX(); int const y0 = bbox.getMinY(); int const x1 = bbox.getMaxX(); int const y1 = bbox.getMaxY();
    145 17d1d529 - for (int i = y0; i <= y1; i++) {
    ? -
    140 94770baf + for (int i = y0; i <= y1; ++i) {
    ? + addSpan(i, x0, x1); } _normalized=true; } Footprint::Footprint( geom::Point2I const & center, double const radius, geom::BoxI const & region ) : lsst::daf::base::Citizen(typeid(this)), _fid(++id), _area(0), _bbox(geom::BoxI()), _peaks(PeakTable::makeMinimalSchema()), _region(region) { int const r2 = static_cast(radius*radius + 0.5); // rounded radius^2 int const r = static_cast(std::sqrt(static_cast(r2))); // truncated radius; r*r <= r2
    165 2af73d7d - for (int i = -r; i <= r; i++) {
    ? -
    160 94770baf + for (int i = -r; i <= r; ++i) {
    ? + int hlen = static_cast(std::sqrt(static_cast(r2 - i*i))); addSpan(center.getY() + i, center.getX() - hlen, center.getX() + hlen); } _normalized = true; }
    166 94770baf +
    Footprint::Footprint( geom::ellipses::Ellipse const & ellipse, geom::Box2I const & region ) : lsst::daf::base::Citizen(typeid(this)), _fid(++id), _area(0), _bbox(geom::Box2I()), _peaks(PeakTable::makeMinimalSchema()), _region(region), _normalized(true) { geom::ellipses::PixelRegion pr(ellipse); for ( geom::ellipses::PixelRegion::Iterator spanIter = pr.begin(), end = pr.end(); spanIter != end; ++spanIter ) { if (!spanIter->isEmpty()) { addSpan(*spanIter); } } _normalized = true; }
    195 f8edfe90 - /**
    196 b635df09 - * Construct a footprint from a list of spans. Resulting Footprint is not
    197 b635df09 - * normalized
    198 b635df09 - */
    Footprint::Footprint( Footprint::SpanList const & spans, geom::Box2I const & region ) : lsst::daf::base::Citizen(typeid(this)), _fid(++id), _area(0), _bbox(geom::Box2I()), _peaks(PeakTable::makeMinimalSchema()), _region(region), _normalized(false) { _spans.reserve(spans.size()); for(SpanList::const_iterator i(spans.begin()); i != spans.end(); ++i) { addSpan(**i); } } Footprint::Footprint(Footprint const & other) : lsst::daf::base::Citizen(typeid(this)), _fid(++id), _bbox(other._bbox), // peaks are deep-copied, but use the same Table as other _peaks(other.getPeaks().getTable(), other.getPeaks().begin(), other.getPeaks().end(), true), _region(other._region) { //deep copy spans _spans.reserve(other._spans.size()); for(SpanList::const_iterator i(other._spans.begin()); i != other._spans.end(); ++i ) { addSpan(**i); } _area = other._area; _normalized = other._normalized; }
    236 b635df09 - /**
    237 f8edfe90 - * Destroy a Footprint
    238 f8edfe90 - */
    Footprint::~Footprint() { } PTR(PeakRecord) Footprint::addPeak(float fx, float fy, float value) { PTR(PeakRecord) p = getPeaks().addNew(); p->setIx(fx); p->setIy(fy); p->setFx(fx); p->setFy(fy); p->setPeakValue(value); return p;
    251 6ac35e07 - }
    252 6ac35e07 -
    253 4dface89 - namespace {
    254 4dface89 -
    255 4dface89 - // comparison function to sort peaks from most positive to most negative.
    256 4dface89 - struct SortPeaks {
    257 4dface89 -
    258 4dface89 - SortPeaks(afw::table::Key const & key) : _key(key) {}
    259 4dface89 -
    260 4dface89 - bool operator()(detection::PeakRecord const & a, detection::PeakRecord const & b) const {
    261 4dface89 - return a.get(_key) > b.get(_key);
    262 4dface89 - }
    263 4dface89 -
    264 4dface89 - private:
    265 4dface89 - afw::table::Key _key;
    266 4dface89 - };
    267 4dface89 -
    268 4dface89 - } // anonymous
    269 4dface89 -
    270 4dface89 - void Footprint::sortPeaks(afw::table::Key const & key) {
    271 4dface89 - getPeaks().sort(SortPeaks(key.isValid() ? key : PeakTable::getPeakValueKey()));
    } /** * Does this Footprint contain this pixel? */ bool Footprint::contains( lsst::afw::geom::Point2I const& pix ///< Pixel to check ) const { if (_bbox.contains(pix)) { for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) { if ((*siter)->contains(pix.getX(), pix.getY())) { return true; } } } return false; } namespace { /// Predicate for removing peaks outside a bbox struct ClipPredicate : public std::unary_function { geom::Box2I const& bbox; ClipPredicate(geom::Box2I const& _bbox) : bbox(_bbox) {} bool operator()(PTR(PeakRecord) const& peak) const {
    298 95043065 - return !bbox.contains(geom::Point2I(peak->getIx(), peak->getIy()));
    ? -
    266 007ca4a2 + return bbox.contains(geom::Point2I(peak->getIx(), peak->getIy()));
    } }; } void Footprint::clipTo(geom::Box2I const& bbox) { Footprint::SpanList::iterator it = _spans.begin(); for (; it != _spans.end();) { Span *sp = it->get();
    307 2e46fcbb - //printf("span: y=%i (x=[%i,%i]), vs bbox [%i,%i]\n", sp->getY(), sp->getX0(), sp->getX1(), bbox.getMinY(), bbox.getMaxY());
    if ((sp->getY() < bbox.getMinY()) || (sp->getY() > bbox.getMaxY())) {
    310 2e46fcbb - //printf(" --> out of bounds in y; erasing.\n");
    277 94770baf + // out of bounds in y -- erase
    it = _spans.erase(it); continue; }
    314 2e46fcbb - //printf("span: x=[%i,%i], vs bbox [%i,%i]\n", sp->getX0(), sp->getX1(), bbox.getMinX(), bbox.getMaxX());
    if ((sp->getX0() > bbox.getMaxX()) || (sp->getX1() < bbox.getMinX())) {
    317 2e46fcbb - //printf(" --> out of bounds in x; erasing.\n");
    ? ------------- ^^^^^^^^^
    283 94770baf + // out of bounds in x; erase
    ? ^ it = _spans.erase(it); continue; }
    321 2e46fcbb -
    // clip if (sp->getX0() < bbox.getMinX()) {
    324 2e46fcbb - //printf(" -> clipped span x0 to bbox\n");
    ? ------------ --- -----
    289 94770baf + // clip span x0 to bbox
    sp->_x0 = bbox.getMinX(); } if (sp->getX1() > bbox.getMaxX()) {
    328 2e46fcbb - //printf(" -> clipped span x1 to bbox\n");
    ? ------------ --- -----
    293 94770baf + // clip span x1 to bbox
    sp->_x1 = bbox.getMaxX(); }
    331 2e46fcbb - it++;
    ? --
    296 94770baf + ++it;
    ? ++ } // Remove peaks not in the new bbox _peaks.getInternal().erase(std::remove_if(_peaks.getInternal().begin(), _peaks.getInternal().end(), ClipPredicate(bbox)), _peaks.getInternal().end()); if (_spans.empty()) { _bbox = geom::Box2I(); _area = 0; _normalized = true; } else { _normalized = false; normalize(); } }
    348 35570270 - /**
    349 fac13aff - * Normalise a Footprint, sorting spans and setting the BBox
    350 f8edfe90 - */
    void Footprint::normalize() { if (_normalized) { return; }
    355 79337bb6 - if (_spans.empty()) {
    ? ^^^ ^^
    317 2e46fcbb + assert(!_spans.empty());
    ? ^^^^^^ + ^
    356 79337bb6 - _bbox = geom::Box2I();
    357 79337bb6 - _normalized = true;
    358 79337bb6 - _area = 0;
    359 79337bb6 - return;
    360 79337bb6 - }
    // // Check that the spans are sorted, and (more importantly) that each pixel appears // in only one span // sort(_spans.begin(), _spans.end(), compareSpanByYX()); Footprint::SpanList::iterator ptr = _spans.begin(), end = _spans.end(); Span *lspan = ptr->get(); // Left span int y = lspan->_y; int x1 = lspan->_x1; _area = lspan->getWidth(); int minX = lspan->_x0, minY=y, maxX=x1; ++ptr; for (; ptr != end; ++ptr) { Span *rspan = ptr->get(); // Right span if (rspan->_y == y) { if (rspan->_x0 <= x1 + 1) { // Spans overlap or touch if (rspan->_x1 > x1) { // right span extends left span //update area _area += rspan->_x1 - x1; //update end of current span x1 = lspan->_x1 = rspan->_x1; //update bounds if(x1 > maxX) maxX = x1; } ptr = _spans.erase(ptr); end = _spans.end(); // delete the right span if (ptr == end) { break; } --ptr; continue; } else{ _area += rspan->getWidth(); if(rspan->_x1 > maxX) maxX = rspan->_x1; } } else { _area += rspan->getWidth(); } y = rspan->_y; x1 = rspan->_x1; lspan = rspan; if(lspan->_x0 < minX) minX = lspan->_x0; if(x1 > maxX) maxX = x1; } _bbox = geom::Box2I(geom::Point2I(minX, minY), geom::Point2I(maxX, y)); _normalized = true; }
    418 f8edfe90 - /**
    419 f8edfe90 - * Add a Span to a footprint, returning a reference to the new Span.
    420 f8edfe90 - */
    Span const& Footprint::addSpan( int const y, //!< row value int const x0, //!< starting column int const x1 //!< ending column ) { if (x1 < x0) {
    427 f8edfe90 - return this->addSpan(y, x1, x0);
    ? ------
    381 94770baf + return addSpan(y, x1, x0);
    }
    430 17d1d529 - Span::Ptr sp(new Span(y, x0, x1));
    ? ^^^^^
    384 94770baf + PTR(Span) sp(new Span(y, x0, x1));
    ? ++++ ^ _spans.push_back(sp); _area += sp->getWidth(); _normalized = false; _bbox.include(geom::Point2I(x0, y)); _bbox.include(geom::Point2I(x1, y)); return *sp.get(); }
    395 94770baf +
    441 f8edfe90 - /**
    442 f8edfe90 - * Add a Span to a Footprint returning a reference to the new Span
    443 f8edfe90 - */
    const Span& Footprint::addSpan( Span const& span ///< new Span being added ) { return addSpan(span._y, span._x0, span._x1); }
    450 90219c90 - /**
    451 90219c90 - * Add a Span to a Footprint returning a reference to the new Span
    452 90219c90 - */
    const Span& Footprint::addSpan( Span const& span, ///< new Span being added int dx, ///< Add dx to span's x coords int dy ///< Add dy to span's y coords ) { return addSpan(span._y + dy, span._x0 + dx, span._x1 + dx); }
    461 097386fc - /**
    462 097386fc - * Add a Span to a Footprint, where the Spans MUST be added in order
    463 097386fc - * (first in increasing y, then increasing x), and MUST NOT be
    464 097386fc - * overlapping. This method does NOT reset the _normalized boolean.
    465 097386fc - */
    const Span& Footprint::addSpanInSeries( int const y, //!< row value int const x0, //!< starting column int const x1 //!< ending column ) { if (x1 < x0) {
    472 097386fc - return this->addSpanInSeries(y, x1, x0);
    ? ------
    416 94770baf + return addSpanInSeries(y, x1, x0);
    } if (_spans.size() == 0) {
    475 097386fc - const Span& s = this->addSpan(y, x0, x1);
    ? ------
    419 94770baf + const Span& s = addSpan(y, x0, x1);
    _normalized = true; return s; } // merge contiguous spans
    480 097386fc - Span::Ptr lastspan = _spans.back();
    ? ^^^^^
    424 94770baf + PTR(Span) lastspan = _spans.back();
    ? ++++ ^ if ((y == lastspan->getY()) && (x0 == (lastspan->getX1() + 1))) { // contiguous. lastspan->_x1 = x1; _area += (1 + x1 - x0); _bbox.include(geom::Point2I(x1,y)); return *lastspan; } if (!((y > lastspan->getY()) || (x0 > (lastspan->getX1() + 1)))) {
    491 99dc4b86 - throw LSST_EXCEPT
    435 94770baf + throw LSST_EXCEPT(
    ? +
    492 99dc4b86 - (lsst::pex::exceptions::InvalidParameterException,
    ? - ^^^^^^ ^
    436 a4c91494 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^
    493 99dc4b86 - str(boost::format("addSpanInSeries: new span %i,[%i,%i] is NOT in series after last span %i,[%i,%i]") %
    ? - ---------- ---
    437 94770baf + str(boost::format("addSpanInSeries: new span %i,[%i,%i] is NOT in series after last span "
    438 94770baf + "%i,[%i,%i]") %
    494 99dc4b86 - y % x0 % x1 % lastspan->getY() % lastspan->getX0() % lastspan->getX1()));
    ? -
    439 94770baf + y % x0 % x1 % lastspan->getY() % lastspan->getX0() % lastspan->getX1()));
    }
    496 097386fc - const Span& s = this->addSpan(y, x0, x1);
    ? ------
    441 94770baf + const Span& s = addSpan(y, x0, x1);
    _normalized = true; return s; }
    501 f8edfe90 - /**
    502 2a10294e - * Shift a Footprint by (dx, dy)
    503 f8edfe90 - */
    void Footprint::shift(
    505 17d1d529 - int dx, //!< How much to move footprint in column direction
    506 17d1d529 - int dy //!< How much to move in row direction
    447 94770baf + int dx,
    448 94770baf + int dy
    ) { for (SpanList::iterator i = _spans.begin(); i != _spans.end(); ++i){
    509 17d1d529 - Span::Ptr span = *i;
    ? ^^^^^
    451 94770baf + PTR(Span) span = *i;
    ? ++++ ^ span->_y += dy; span->_x0 += dx; span->_x1 += dx; } _bbox.shift(geom::Extent2I(dx, dy)); }
    519 102a5edd - /**
    520 102a5edd - * Return the Footprint's centroid
    521 102a5edd - *
    522 102a5edd - * The centroid is calculated as the mean of the pixel centers
    523 102a5edd - */
    geom::Point2D Footprint::getCentroid() const { int n = 0; double xc = 0, yc = 0; for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) {
    530 102a5edd - Span::Ptr const span = *siter;
    467 94770baf + CONST_PTR(Span) span = *siter;
    int const y = span->getY(); int const x0 = span->getX0(); int const x1 = span->getX1(); int const npix = x1 - x0 + 1; n += npix; xc += npix*0.5*(x1 + x0); yc += npix*y; } assert(n == _area); return geom::Point2D(xc/_area, yc/_area); }
    545 102a5edd - /**
    546 102a5edd - * Return the Footprint's shape (interpreted as an ellipse)
    547 102a5edd - *
    548 102a5edd - * The shape is determined by measuring the moments of the pixel centers about its centroid (cf. getCentroid)
    549 102a5edd - */
    geom::ellipses::Quadrupole Footprint::getShape() const { geom::Point2D cen = getCentroid(); double const xc = cen.getX(); double const yc = cen.getY(); double sumxx = 0, sumxy = 0, sumyy = 0; for (Footprint::SpanList::const_iterator siter = _spans.begin(); siter != _spans.end(); ++siter) {
    559 102a5edd - Span::Ptr const span = *siter;
    491 94770baf + CONST_PTR(Span) span = *siter;
    int const y = span->getY(); int const x0 = span->getX0(); int const x1 = span->getX1(); int const npix = x1 - x0 + 1; for (int x = x0; x <= x1; ++x) { sumxx += (x - xc)*(x - xc); } sumxy += npix*(0.5*(x1 + x0) - xc)*(y - yc); sumyy += npix*(y - yc)*(y - yc); } return geom::ellipses::Quadrupole(sumxx/_area, sumyy/_area, sumxy/_area); } namespace { /*
    577 2410dfe5 - * Set the pixels in idImage which are in Footprint by adding or replacing the specified value to the Image
    ? -------------------------------------------
    509 94770baf + * Set the pixels in idImage which are in Footprint by adding or
    510 94770baf + * replacing the specified value to the Image
    * * The ids that are overwritten are returned for the callers deliction */ template void doInsertIntoImage(geom::Box2I const& _region, // unpacked from Footprint Footprint::SpanList const& _spans, // unpacked from Footprint image::Image& idImage, // Image to contain the footprint boost::uint64_t const id, // Add/replace id to idImage for pixels in Footprint geom::Box2I const& region, // Footprint's region (default: getRegion()) long const mask=0x0, // Don't overwrite bits in this mask std::set *oldIds=NULL // if non-NULL, set the IDs that were overwritten ) { int width, height, x0, y0; if(!region.isEmpty()) { height = region.getHeight(); width = region.getWidth(); x0 = region.getMinX(); y0 = region.getMinY(); } else { height = _region.getHeight(); width = _region.getWidth(); x0 = _region.getMinX(); y0 = _region.getMinY(); } if (width != idImage.getWidth() || height != idImage.getHeight()) {
    606 2410dfe5 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    539 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("Image of size (%dx%d) doesn't match " "Footprint's host Image of size (%dx%d)") % idImage.getWidth() % idImage.getHeight() % width % height)); } if (id & mask) {
    613 5ba4f880 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    546 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("Id 0x%x sets bits in the protected mask 0x%x") % id % mask)); } typename std::set::const_iterator pos; // hint on where to insert into oldIds if (oldIds) { pos = oldIds->begin(); } for (Footprint::SpanList::const_iterator spi = _spans.begin(); spi != _spans.end(); ++spi) {
    622 2410dfe5 - Span::Ptr const span = *spi;
    555 94770baf + CONST_PTR(Span) span = *spi;
    int const sy0 = span->getY() - y0; if (sy0 < 0 || sy0 >= height) { continue; } int sx0 = span->getX0() - x0; if (sx0 < 0) { sx0 = 0; } int sx1 = span->getX1() - x0; int const swidth = (sx1 >= width) ? width - sx0 : sx1 - sx0 + 1; for (typename image::Image::x_iterator ptr = idImage.x_at(sx0, sy0), end = ptr + swidth; ptr != end; ++ptr) { if (overwriteId) { long val = *ptr & ~mask; if (val != 0 and oldIds != NULL) { pos = oldIds->insert(pos, val); // update our hint, pos } *ptr = (*ptr & mask) + id; } else { *ptr += id; } } } } }
    652 f8edfe90 - /**
    653 097386fc - Clips the given *Footprint* to the region in the *Image* containing
    654 097386fc - non-zero values. The clipping drops spans that are totally zero,
    655 097386fc - and moves endpoints to non-zero; it does not split spans that have
    656 097386fc - internal zeros.
    657 097386fc - */
    template void Footprint::clipToNonzero(typename image::Image const& img) {
    661 097386fc - typedef typename lsst::afw::image::Image ImageT;
    ? ---------
    588 94770baf + typedef lsst::afw::image::Image ImageT;
    662 097386fc - int ix0 = img.getX0();
    589 94770baf + int const ix0 = img.getX0();
    ? ++++++
    663 097386fc - int iy0 = img.getY0();
    590 94770baf + int const iy0 = img.getY0();
    ? ++++++
    664 097386fc - PixelT zero = 0;
    591 94770baf + const PixelT zero = 0;
    ? ++++++
    666 99dc4b86 - for (SpanList::iterator s = _spans.begin(); s < _spans.end(); s++) {
    ? -
    593 94770baf + for (SpanList::iterator s = _spans.begin(); s < _spans.end(); ++s) {
    ? +
    667 097386fc - int y = (*s)->getY();
    594 94770baf + int const y = (*s)->getY();
    ? ++++++
    668 097386fc - int x0 = (*s)->getX0();
    595 94770baf + int const x0 = (*s)->getX0();
    ? ++++++
    669 097386fc - int x1 = (*s)->getX1();
    596 94770baf + int const x1 = (*s)->getX1();
    ? ++++++ typename ImageT::x_iterator img_it = img.row_begin(y - iy0) + (x0 - ix0); int leftx, rightx; // find zero pixels on the left... for (leftx = x0; leftx <= x1; ++leftx, ++img_it) { if (*img_it != zero) { break; } } if (leftx > x1) { // whole span is zero; drop it. _normalized = false; _spans.erase(s); s--; continue; } // find zero pixels on the right... img_it = img.row_begin(y - iy0) + (x1 - ix0); for (rightx = x1; rightx >= leftx; --rightx, --img_it) { if (*img_it != zero) { break; } } if (leftx != x0) { (*s)->_x0 = leftx; _normalized = false; } if (rightx != x1) { (*s)->_x1 = rightx; _normalized = false; } } if (_spans.empty()) { _bbox = geom::Box2I(); _area = 0; _normalized = true; } }
    709 097386fc - /**
    710 f8edfe90 - * Set the pixels in idImage which are in Footprint by adding the specified value to the Image
    711 f8edfe90 - */
    template void Footprint::insertIntoImage(
    715 f0e831df - typename image::Image& idImage, //!< Image to contain the footprint
    716 f0e831df - boost::uint64_t const id, //!< Add id to idImage for pixels in the Footprint
    717 8a634e0b - geom::Box2I const& region //!< Footprint's region (default: getRegion())
    639 94770baf + typename image::Image& idImage,
    640 94770baf + boost::uint64_t const id,
    641 94770baf + geom::Box2I const& region
    ) const { static_cast(doInsertIntoImage(_region, _spans, idImage, id, region)); }
    723 8a634e0b - /**
    724 8a634e0b - * Set the pixels in idImage which are in Footprint by adding the specified value to the Image
    725 2410dfe5 - *
    726 2410dfe5 - * The list of ids found under the new Footprint are returned
    727 8a634e0b - */
    template void Footprint::insertIntoImage(
    731 f0e831df - image::Image& idImage, //!< Image to contain the footprint
    732 f0e831df - boost::uint64_t const id, //!< Add id to idImage for pixels in the Footprint
    733 2410dfe5 - bool overwriteId, //!< should id replace any value already in idImage?
    734 2410dfe5 - long const mask, //!< Don't overwrite ID bits in this mask
    735 f0e831df - std::set *oldIds, //!< if non-NULL, set the IDs that were overwritten
    736 8a634e0b - geom::Box2I const& region //!< Footprint's region (default: getRegion())
    650 94770baf + image::Image& idImage,
    651 94770baf + boost::uint64_t const id,
    652 94770baf + bool overwriteId,
    653 94770baf + long const mask,
    654 94770baf + std::set *oldIds,
    655 94770baf + geom::Box2I const& region
    ) const { if (id > std::size_t(std::numeric_limits::max())) { throw LSST_EXCEPT(
    741 f0e831df - lsst::pex::exceptions::OutOfRangeException,
    ? ^^^^^^ ^
    660 21597d88 + lsst::pex::exceptions::OutOfRangeError,
    ? ^^ ^ "id out of range for image type" ); } if (overwriteId) { doInsertIntoImage(_region, _spans, idImage, id, region, mask, oldIds); } else { doInsertIntoImage(_region, _spans, idImage, id, region, mask, oldIds); } }
    752 ddb75eb2 - void Footprint::include(std::vector const & others, bool ignoreSelf) {
    ? -----------------
    671 0b2457bc + void Footprint::include(std::vector const & others) {
    if (others.empty()) return;
    754 ddb75eb2 - geom::Box2I bbox;
    673 0b2457bc + geom::Box2I bbox(getBBox());
    ? +++++++++++
    755 ddb75eb2 - if (!ignoreSelf) {
    756 ddb75eb2 - bbox.include(getBBox());
    757 ddb75eb2 - } else {
    758 ddb75eb2 - _spans.clear();
    759 ddb75eb2 - }
    for (std::vector::const_iterator i = others.begin(); i != others.end(); ++i) { bbox.include((**i).getBBox()); } boost::uint16_t bits = 0x1; image::Mask mask(bbox);
    765 ddb75eb2 - if (!ignoreSelf) {
    766 ddb75eb2 - setMaskFromFootprint(&mask, *this, bits);
    ? ----
    679 0b2457bc + setMaskFromFootprint(&mask, *this, bits);
    767 ddb75eb2 - }
    for (std::vector::const_iterator i = others.begin(); i != others.end(); ++i) { setMaskFromFootprint(&mask, **i, bits); } FootprintSet fpSet(mask, Threshold(bits, Threshold::BITMASK));
    772 0d1ab12d - if (fpSet.getFootprints()->empty()) {
    773 0d1ab12d - _spans.clear();
    774 0d1ab12d - } else if (fpSet.getFootprints()->size() == 1u) {
    ? ------- -
    684 0b2457bc + if (fpSet.getFootprints()->size() != 1u) {
    ? +
    685 0b2457bc + throw LSST_EXCEPT(
    686 d19772f0 + pex::exceptions::RuntimeError,
    687 0b2457bc + (boost::format("Footprint::include() result is disjoint; got %d distinct Footprints")
    688 0b2457bc + % fpSet.getFootprints()->size()).str()
    689 0b2457bc + );
    690 0b2457bc + }
    775 0d1ab12d - _spans.swap(fpSet.getFootprints()->front()->getSpans());
    ? ----
    691 0b2457bc + _spans.swap(fpSet.getFootprints()->front()->getSpans());
    776 0d1ab12d - } else {
    777 0d1ab12d - _spans.clear();
    778 0d1ab12d - for (std::vector::const_iterator i = fpSet.getFootprints()->begin();
    779 0d1ab12d - i != fpSet.getFootprints()->end(); ++i) {
    780 0d1ab12d - _spans.insert(_spans.end(), (**i).getSpans().begin(), (**i).getSpans().end());
    781 0d1ab12d - }
    782 5d1934cc - }
    _normalized = false; normalize(); } // Factory class used for table-based persistence; invoked via registry in afw::table::io class FootprintFactory : public table::io::PersistableFactory { public: virtual PTR(table::io::Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const { LSST_ARCHIVE_ASSERT(catalogs.size() == 2u); PTR(Footprint) result = boost::make_shared(); result->readSpans(catalogs.front()); result->readPeaks(catalogs.back()); return result; } explicit FootprintFactory(std::string const & name) : table::io::PersistableFactory(name) {} }; namespace { // Singleton helper class that manages the schema and keys for persisting a Footprint class FootprintPersistenceHelper : private boost::noncopyable { public: table::Schema spanSchema; table::Key spanY; table::Key spanX0; table::Key spanX1; static FootprintPersistenceHelper const & get() { static FootprintPersistenceHelper instance; return instance; } private: FootprintPersistenceHelper() : spanSchema(), spanY(spanSchema.addField("y", "row position of span", "pixels")), spanX0(spanSchema.addField("x0", "first column of span (inclusive)", "pixels")), spanX1(spanSchema.addField("x1", "first column of span (inclusive)", "pixels")) { spanSchema.getCitizen().markPersistent(); } }; std::string getFootprintPersistenceName() { return "Footprint"; } // Insert the factory into the registry (instantiating an instance is sufficient, because // the code that does the work is in the base class ctor) FootprintFactory registration(getFootprintPersistenceName()); } // anonymous std::string Footprint::getPersistenceName() const { return getFootprintPersistenceName(); } std::string Footprint::getPythonModule() const { return "lsst.afw.detection"; } void Footprint::write(OutputArchiveHandle & handle) const { FootprintPersistenceHelper const & keys = FootprintPersistenceHelper::get(); afw::table::BaseCatalog spanCat = handle.makeCatalog(keys.spanSchema); spanCat.reserve(_spans.size()); for (SpanList::const_iterator i = _spans.begin(); i != _spans.end(); ++i) { PTR(afw::table::BaseRecord) record = spanCat.addNew(); record->set(keys.spanY, (**i).getY()); record->set(keys.spanX0, (**i).getX0()); record->set(keys.spanX1, (**i).getX1()); } handle.saveCatalog(spanCat); afw::table::BaseCatalog peakCat = handle.makeCatalog(_peaks.getSchema()); peakCat.insert(peakCat.end(), _peaks.begin(), _peaks.end(), true); handle.saveCatalog(peakCat); } void Footprint::readSpans(afw::table::BaseCatalog const & spanCat) { FootprintPersistenceHelper const & keys = FootprintPersistenceHelper::get(); for (afw::table::BaseCatalog::const_iterator i = spanCat.begin(); i != spanCat.end(); ++i) { addSpan(i->get(keys.spanY), i->get(keys.spanX0), i->get(keys.spanX1)); } } void Footprint::readPeaks(afw::table::BaseCatalog const & peakCat) { if (!peakCat.getSchema().contains(PeakTable::makeMinimalSchema())) { // need to handle an older form of Peak persistence for backwards compatibility afw::table::SchemaMapper mapper(peakCat.getSchema()); mapper.addMinimalSchema(PeakTable::makeMinimalSchema()); afw::table::Key oldX = peakCat.getSchema()["x"]; afw::table::Key oldY = peakCat.getSchema()["y"]; afw::table::Key oldPeakValue = peakCat.getSchema()["value"]; mapper.addMapping(oldX, "f.x"); mapper.addMapping(oldY, "f.y"); mapper.addMapping(oldPeakValue, "peakValue"); _peaks = PeakCatalog(mapper.getOutputSchema()); _peaks.reserve(peakCat.size()); for (afw::table::BaseCatalog::const_iterator i = peakCat.begin(); i != peakCat.end(); ++i) { PTR(PeakRecord) newPeak = _peaks.addNew(); newPeak->assign(*i, mapper); newPeak->setIx(int(newPeak->getFx())); newPeak->setIy(int(newPeak->getFy())); } return; } _peaks = PeakCatalog(peakCat.getSchema()); _peaks.reserve(peakCat.size()); for (afw::table::BaseCatalog::const_iterator i = peakCat.begin(); i != peakCat.end(); ++i) { _peaks.addNew()->assign(*i); } } /** * Assignment operator. Will not change the id */ Footprint & Footprint::operator=(Footprint & other) { _region = other._region; //deep copy spans _spans = SpanList(); _spans.reserve(other._spans.size()); for(SpanList::const_iterator i(other._spans.begin()); i != other._spans.end(); ++i ) { addSpan(**i); } _area = other._area; _normalized = other._normalized; _bbox = other._bbox; //deep copy peaks _peaks = PeakCatalog(other.getPeaks().getTable(), other.getPeaks().begin(), other.getPeaks().end(), true); return *this; }
    916 f8edfe90 - /**
    917 5cdd6a3d - * \brief Intersect the Footprint with a Mask
    918 f8edfe90 - *
    919 5cdd6a3d - * The resulting Footprint contains only pixels for which (mask & bitMask) == 0;
    920 5cdd6a3d - * it may have disjoint pieces. Any part of the footprint that falls outside the
    921 5cdd6a3d - * bounds of the mask will be clipped.
    922 f8edfe90 - *
    923 f8edfe90 - */
    template void Footprint::intersectMask( lsst::afw::image::Mask const & mask, MaskT const bitmask ) {
    929 5cdd6a3d - geom::Box2I maskBBox = mask.getBBox(image::PARENT);
    ? -------------
    830 93994d54 + geom::Box2I maskBBox = mask.getBBox();
    //this operation makes no sense on non-normalized footprints. //make sure this is normalized normalize(); SpanList::iterator s(_spans.begin());
    936 f78ceebc - while(s != _spans.end() && (*s)->getY() < maskBBox.getMinY()){
    837 5cdd6a3d + while((*s)->getY() < maskBBox.getMinY() && s != _spans.end()){
    ++s; } int x0, x1, y; SpanList maskedSpans; int maskedArea=0; for( ; s != _spans.end(); ++s) { y = (*s)->getY(); if (y > maskBBox.getMaxY()) break; x0 = (*s)->getX0(); x1 = (*s)->getX1(); if(x1 < maskBBox.getMinX() || x0 > maskBBox.getMaxX()) { //span is entirely outside the image mask. cannot be used continue; } //clip the span to be within the mask if(x0 < maskBBox.getMinX()) x0 = maskBBox.getMinX(); if(x1 > maskBBox.getMaxX()) x1 = maskBBox.getMaxX(); //Image iterators are always specified with respect to (0,0) //regardless what the image::XY0 is set to. typename image::Mask::const_x_iterator mIter = mask.x_at( x0 - maskBBox.getMinX(), y - maskBBox.getMinY() ); //loop over all span locations, slicing the span at maskedPixels for(int x = x0; x <= x1; ++x, ++mIter) { if((*mIter & bitmask) != 0) { //masked pixel found within span if (x > x0) { //add beginning of span to the output //the fixed span contains all the unmasked pixels up to, //but not including this masked pixel
    976 5cdd6a3d - Span::Ptr maskedSpan(new Span(y, x0, x- 1));
    ? ^^^^^
    877 94770baf + PTR(Span) maskedSpan(new Span(y, x0, x- 1));
    ? ++++ ^ maskedSpans.push_back(maskedSpan); maskedArea += maskedSpan->getWidth(); } //set the next Span to start after this pixel x0 = x + 1; } } //add last section of span if(x0 <= x1) {
    987 5cdd6a3d - Span::Ptr maskedSpan(new Span(y, x0, x1));
    ? ^^^^^
    888 94770baf + PTR(Span) maskedSpan(new Span(y, x0, x1));
    ? ++++ ^ maskedSpans.push_back(maskedSpan); maskedArea += maskedSpan->getWidth(); } } _area = maskedArea; _spans = maskedSpans; _bbox.clip(maskBBox); } PTR(Footprint) Footprint::transform( image::Wcs const& source, image::Wcs const& target, geom::Box2I const& region, bool doClip ) const { // Transform the original bounding box geom::Box2I const& fpBox = getBBox(); // Original bounding box geom::Box2D tBoxD; // If slow, could consider linearising the WCSes and combining the // linear versions to a single transform, and then using that to // transform all the points. tBoxD.include(transformPoint(fpBox.getMinX(), fpBox.getMinY(), source, target)); tBoxD.include(transformPoint(fpBox.getMinX(), fpBox.getMaxY(), source, target)); tBoxD.include(transformPoint(fpBox.getMaxX(), fpBox.getMinY(), source, target)); tBoxD.include(transformPoint(fpBox.getMaxX(), fpBox.getMaxY(), source, target)); geom::Box2I tBoxI(tBoxD); // enumerate points in the new bbox that, when reverse-transformed, are within the given footprint. PTR(Footprint) fpNew = boost::make_shared(getPeaks().getSchema(), 0, region); for (int y = tBoxI.getBeginY(); y < tBoxI.getEndY(); ++y) { bool inSpan = false; // Are we in a span? int start = -1; // Start of span for (int x = tBoxI.getBeginX(); x < tBoxI.getEndX(); ++x) {
    1024 95043065 - geom::Point2D p = transformPoint(x, y, target, source);
    925 58d8c34f + lsst::afw::geom::Point2D const& p = transformPoint(x, y, target, source);
    ? +++++++++++ +++++++ int const xSource = std::floor(0.5 + p.getX()); int const ySource = std::floor(0.5 + p.getY());
    1028 95043065 - if (contains(geom::Point2I(xSource, ySource))) {
    929 5539a924 + if (contains(lsst::afw::geom::Point2I(xSource, ySource))) {
    ? +++++++++++ if (!inSpan) { inSpan = true; start = x; } } else if (inSpan) { inSpan = false; fpNew->addSpan(y, start, x - 1); } } if (inSpan) { fpNew->addSpan(y, start, tBoxI.getMaxX()); } }
    1042 95043065 -
    1043 95043065 - // Copy over peaks to new Footprint
    1044 95043065 - for (
    1045 95043065 - PeakCatalog::const_iterator iter = this->getPeaks().begin();
    1046 95043065 - iter != this->getPeaks().end();
    1047 95043065 - ++iter
    1048 95043065 - ) {
    1049 95043065 - geom::Point2D tp = transformPoint(iter->getFx(), iter->getFy(), source, target);
    1050 95043065 - fpNew->addPeak(tp.getX(), tp.getY(), iter->getPeakValue());
    1051 95043065 - }
    1052 95043065 -
    if (doClip) { fpNew->clipTo(region); } return fpNew; } /** Returns *true* iff this Footprint satisfies the "normalized" conditions. Useful as an "assert" during algorithm development. */ bool _checkNormalized(Footprint const& foot) {
    1065 7ac2306a - // Ugly!
    1066 7ac2306a - Footprint copy(foot);
    955 94770baf + Footprint copy(foot);
    ? ++
    1067 7ac2306a - copy.normalize();
    956 94770baf + copy.normalize();
    ? ++
    1068 7ac2306a - if (copy.getArea() != foot.getArea()) {
    957 94770baf + if (copy.getArea() != foot.getArea()) {
    ? ++
    1069 7ac2306a - return false;
    958 94770baf + return false;
    ? ++++
    1070 7ac2306a - }
    959 94770baf + }
    ? ++
    1071 7ac2306a - if (copy.getSpans().size() != foot.getSpans().size()) {
    960 94770baf + if (copy.getSpans().size() != foot.getSpans().size()) {
    ? ++
    1072 7ac2306a - return false;
    961 94770baf + return false;
    ? ++++
    1073 7ac2306a - }
    962 94770baf + }
    ? ++
    1074 d9ace53f - const Footprint::SpanList& spansa = foot.getSpans();
    ? ^^^^^
    963 94770baf + Footprint::SpanList const& spansa = foot.getSpans();
    ? ^ ++++++
    1075 d9ace53f - const Footprint::SpanList& spansb = copy.getSpans();
    ? ^^^^^
    964 94770baf + Footprint::SpanList const& spansb = copy.getSpans();
    ? ^ ++++++
    1076 7ac2306a - Footprint::SpanList::const_iterator spa = spansa.begin();
    965 94770baf + Footprint::SpanList::const_iterator spa = spansa.begin();
    ? ++
    1077 7ac2306a - Footprint::SpanList::const_iterator spb = spansb.begin();
    966 94770baf + Footprint::SpanList::const_iterator spb = spansb.begin();
    ? ++
    1078 7ac2306a - for (; spa != spansa.end(); spa++, spb++) {
    ? -- --
    967 94770baf + for (; spa != spansa.end(); ++spa, ++spb) {
    ? ++ ++ ++
    1079 7ac2306a - if ((*spa)->getY() != (*spb)->getY()) {
    968 94770baf + if ((*spa)->getY() != (*spb)->getY()) {
    ? ++++
    1080 7ac2306a - return false;
    969 94770baf + return false;
    ? ++++++
    1081 7ac2306a - }
    970 94770baf + }
    ? ++++
    1082 7ac2306a - if ((*spa)->getX0() != (*spb)->getX0()) {
    971 94770baf + if ((*spa)->getX0() != (*spb)->getX0()) {
    ? ++++
    1083 7ac2306a - return false;
    972 94770baf + return false;
    ? ++++++
    1084 7ac2306a - }
    973 94770baf + }
    ? ++++
    1085 7ac2306a - if ((*spa)->getX1() != (*spb)->getX1()) {
    974 94770baf + if ((*spa)->getX1() != (*spb)->getX1()) {
    ? ++++
    1086 7ac2306a - return false;
    975 94770baf + return false;
    ? ++++++
    1087 7ac2306a - }
    976 94770baf + }
    ? ++++
    1088 7ac2306a - }
    977 94770baf + }
    ? ++
    1089 7ac2306a - return true;
    978 94770baf + return true;
    ? ++ }
    1091 7ac2306a -
    1092 7ac2306a -
    /************************************************************************************************************/
    982 94770baf +
    1095 5cdd6a3d - /**
    1096 5cdd6a3d - * \brief Return a Footprint that's the intersection of a Footprint with a Mask
    1097 5cdd6a3d - *
    1098 5cdd6a3d - * The resulting Footprint contains only pixels for which (mask & bitMask) != 0;
    1099 5cdd6a3d - * it may have disjoint pieces
    1100 5cdd6a3d - *
    1101 5cdd6a3d - * \note This isn't a member of Footprint as Footprint isn't templated over MaskT
    1102 5cdd6a3d - *
    1103 5cdd6a3d - * \returns Returns the new Footprint
    1104 5cdd6a3d - */
    template
    1106 5cdd6a3d - Footprint::Ptr footprintAndMask(
    ? ^^^^^
    984 94770baf + PTR(Footprint) footprintAndMask(
    ? ++++ ^
    1107 5cdd6a3d - Footprint::Ptr const& fp, ///< The initial Footprint
    985 94770baf + PTR(Footprint) const& fp,
    1108 5cdd6a3d - typename lsst::afw::image::Mask::Ptr const& mask, ///< The mask to & with foot
    ? --------------------------------
    986 94770baf + typename lsst::afw::image::Mask::Ptr const& mask,
    1109 5cdd6a3d - MaskT const bitmask ///< Only consider these bits
    987 94770baf + MaskT const bitmask
    ) {
    1111 3d19aa2b - Footprint::Ptr newFp(new Footprint(fp->getPeaks().getSchema()));
    ? ^^^^^
    989 f0799ebb + PTR(Footprint) newFp(new Footprint(fp->getPeaks().getSchema()));
    ? ++++ ^ return newFp; }
    1115 5cdd6a3d - /******************************************************************************/
    1116 5cdd6a3d -
    1117 5cdd6a3d -
    /************************************************************************************************************/
    994 94770baf +
    1119 f8edfe90 - /**
    1120 d2f33c47 - * \brief OR bitmask into all the Mask's pixels that are in the Footprint
    1121 f8edfe90 - *
    1122 f8edfe90 - * \return bitmask
    1123 f8edfe90 - */
    template MaskT setMaskFromFootprint( image::Mask *mask, ///< Mask to set Footprint const& foot, ///< Footprint specifying desired pixels MaskT const bitmask ///< Bitmask to OR into mask ) { int const width = static_cast(mask->getWidth()); int const height = static_cast(mask->getHeight()); for (Footprint::SpanList::const_iterator siter = foot.getSpans().begin();
    1135 9a8e8725 - siter != foot.getSpans().end(); siter++) {
    ? --
    1006 94770baf + siter != foot.getSpans().end(); ++siter) {
    ? ++
    1136 17d1d529 - Span::Ptr const span = *siter;
    1007 94770baf + CONST_PTR(Span) span = *siter;
    int const y = span->getY() - mask->getY0(); if (y < 0 || y >= height) { continue; } int x0 = span->getX0() - mask->getX0(); int x1 = span->getX1() - mask->getX0(); x0 = (x0 < 0) ? 0 : (x0 >= width ? width - 1 : x0); x1 = (x1 < 0) ? 0 : (x1 >= width ? width - 1 : x1); for (typename image::Image::x_iterator ptr = mask->x_at(x0, y), end = mask->x_at(x1 + 1, y); ptr != end; ++ptr) { *ptr |= bitmask; } } return bitmask; } /************************************************************************************************************/
    1028 94770baf +
    1157 f8edfe90 - /**
    1158 d2f33c47 - * \brief (AND ~bitmask) all the Mask's pixels that are in the
    1159 d2f33c47 - * Footprint; that is, set to zero in the Mask-intersecting-Footprint
    1160 d2f33c47 - * all bits that are 1 in then bitmask.
    1161 d2f33c47 - *
    1162 d2f33c47 - * \return bitmask
    1163 d2f33c47 - */
    template MaskT clearMaskFromFootprint( image::Mask *mask, ///< Mask to set Footprint const& foot, ///< Footprint specifying desired pixels MaskT const bitmask ///< Bitmask ) { int const width = static_cast(mask->getWidth()); int const height = static_cast(mask->getHeight()); for (Footprint::SpanList::const_iterator siter = foot.getSpans().begin();
    1174 d2f33c47 - siter != foot.getSpans().end(); siter++) {
    ? --
    1039 94770baf + siter != foot.getSpans().end(); ++siter) {
    ? ++
    1175 d2f33c47 - Span::Ptr const span = *siter;
    1040 94770baf + CONST_PTR(Span) span = *siter;
    int const y = span->getY() - mask->getY0(); if (y < 0 || y >= height) { continue; } int x0 = span->getX0() - mask->getX0(); int x1 = span->getX1() - mask->getX0(); x0 = (x0 < 0) ? 0 : (x0 >= width ? width - 1 : x0); x1 = (x1 < 0) ? 0 : (x1 >= width ? width - 1 : x1); for (typename image::Image::x_iterator ptr = mask->x_at(x0, y), end = mask->x_at(x1 + 1, y); ptr != end; ++ptr) { *ptr &= ~bitmask; } } return bitmask; } /************************************************************************************************************/
    1061 94770baf +
    1196 d2f33c47 - /**
    1197 f8edfe90 - * \brief OR bitmask into all the Mask's pixels which are in the set of Footprint%s
    1198 f8edfe90 - *
    1199 f8edfe90 - * \return bitmask
    1200 f8edfe90 - */
    template MaskT setMaskFromFootprintList( image::Mask *mask, ///< Mask to set
    1204 2eb9dac3 - std::vector const& footprints, ///< Footprint list specifying desired pixels
    ? ^^^^^
    1065 94770baf + std::vector const& footprints, ///< Footprint list specifying desired pixels
    ? ++++ ^ MaskT const bitmask ///< Bitmask to OR into mask ) {
    1207 17d1d529 - for (std::vector::const_iterator fiter = footprints.begin();
    ? ^^^^^
    1068 94770baf + for (std::vector::const_iterator fiter = footprints.begin();
    ? ++++ ^ fiter != footprints.end(); ++fiter) { (void)setMaskFromFootprint(mask, **fiter, bitmask); } return bitmask; } /************************************************************************************************************/
    1077 94770baf +
    1216 f9d4c054 - /**
    1217 f9d4c054 - * \brief OR bitmask into all the Mask's pixels which are in the set of Footprint%s
    1218 f9d4c054 - *
    1219 f9d4c054 - * \return bitmask
    1220 f9d4c054 - */
    template MaskT setMaskFromFootprintList( image::Mask *mask, ///< Mask to set
    1224 a8f86353 - CONST_PTR(std::vector) const & footprints, ///< Footprint list specifying desired pixels
    ? ^^^^^
    1081 94770baf + CONST_PTR(std::vector) const & footprints, ///< Footprint list specifying desired pixels
    ? ++++ ^ MaskT const bitmask ///< Bitmask to OR into mask ) { return setMaskFromFootprintList(mask, *footprints, bitmask); } /************************************************************************************************************/ namespace { template class SetFootprint : public FootprintFunctor { public: SetFootprint(ImageT const& image, typename ImageT::Pixel value) : FootprintFunctor(image), _value(value) {} void operator()(typename ImageT::xy_locator loc, int, int) { *loc = _value; } private: typename ImageT::Pixel _value; }; }
    1248 c902c475 - /**
    1249 c902c475 - * \brief Set all image pixels in a Footprint to a given value
    1250 c902c475 - *
    1251 c902c475 - * \return value
    1252 c902c475 - */
    template typename ImageT::Pixel setImageFromFootprint( ImageT *image, ///< image to set Footprint const& foot, ///< Footprint defining desired pixels typename ImageT::Pixel const value ///< value to set Image to ) { SetFootprint setit(*image, value); setit.apply(foot); return value; }
    1265 c902c475 - /**
    1266 c902c475 - * \brief Set all image pixels in a set of Footprint%s to a given value
    1267 c902c475 - *
    1268 c902c475 - * \return value
    1269 c902c475 - */
    template typename ImageT::Pixel setImageFromFootprintList( ImageT *image, ///< image to set
    1273 f9d4c054 - CONST_PTR(std::vector) footprints, ///< Footprint list specifying desired pixels
    ? ^^^^^
    1120 94770baf + CONST_PTR(std::vector) footprints, ///< Footprint list specifying desired pixels
    ? ++++ ^ typename ImageT::Pixel const value ///< value to set Image to ) { return setImageFromFootprintList(image, *footprints, value); }
    1279 f9d4c054 - /**
    1280 f9d4c054 - * \brief Set all image pixels in a set of Footprint%s to a given value
    1281 f9d4c054 - *
    1282 f9d4c054 - * \return value
    1283 f9d4c054 - */
    template typename ImageT::Pixel setImageFromFootprintList( ImageT *image, ///< image to set
    1287 2eb9dac3 - std::vector const& footprints, ///< Footprint list specifying desired pixels
    ? ^^^^^
    1129 94770baf + std::vector const& footprints, ///< Footprint list specifying desired pixels
    ? ++++ ^ typename ImageT::Pixel const value ///< value to set Image to ) { SetFootprint setit(*image, value);
    1291 17d1d529 - for (std::vector::const_iterator fiter = footprints.begin(),
    ? ^^^^^
    1133 94770baf + for (std::vector::const_iterator fiter = footprints.begin(),
    ? ++++ ^ end = footprints.end(); fiter != end; ++fiter) { setit.apply(**fiter); } return value; } /************************************************************************************************************/ /* * Worker routine for the pmSetFootprintArrayIDs/pmSetFootprintID (and pmMergeFootprintArrays) */ template static void set_footprint_id( typename image::Image::Ptr idImage, // the image to set Footprint const& foot, // the footprint to insert int const id, // the desired ID int dx=0, int dy=0 // Add these to all x/y in the Footprint ) { for (Footprint::SpanList::const_iterator i = foot.getSpans().begin();
    1311 17d1d529 - i != foot.getSpans().end(); i++) {
    ? -
    1153 94770baf + i != foot.getSpans().end(); ++i) {
    ? +
    1312 17d1d529 - Span::Ptr const span = *i;
    1154 94770baf + CONST_PTR(Span) span = *i;
    for (typename image::Image::x_iterator ptr = idImage->x_at(span->getX0() + dx, span->getY() + dy), end = ptr + span->getWidth(); ptr != end; ++ptr) { *ptr = id; } } } template static void set_footprint_array_ids( typename image::Image::Ptr idImage, // the image to set
    1325 17d1d529 - std::vector const& footprints, // the footprints to insert
    ? ^^^^^
    1167 94770baf + std::vector const& footprints, // the footprints to insert
    ? ++++ ^ bool const relativeIDs // show IDs starting at 0, not Footprint->id ) { int id = 0; // first index will be 1
    1330 17d1d529 - for (std::vector::const_iterator fiter = footprints.begin();
    ? ^^^^^
    1172 94770baf + for (std::vector::const_iterator fiter = footprints.begin();
    ? ++++ ^ fiter != footprints.end(); ++fiter) {
    1332 17d1d529 - Footprint::Ptr const foot = *fiter;
    ? ^^^^^^^^^^^
    1174 94770baf + CONST_PTR(Footprint) foot = *fiter;
    ? ++++++++++ ^ if (relativeIDs) {
    1335 f8edfe90 - id++;
    ? --
    1177 94770baf + ++id;
    ? ++ } else { id = foot->getId(); } set_footprint_id(idImage, *foot, id); } } template void set_footprint_array_ids( image::Image::Ptr idImage,
    1346 17d1d529 - std::vector const& footprints,
    ? ^^^^^
    1188 94770baf + std::vector const& footprints,
    ? ++++ ^ bool const relativeIDs); /******************************************************************************/ /* * Set an image to the value of footprint's ID wherever they may fall * * @param footprints the footprints to insert * @param relativeIDs show the IDs starting at 1, not pmFootprint->id */ template typename boost::shared_ptr > setFootprintArrayIDs(
    1358 2e46fcbb - std::vector const& footprints,
    ? ^^^^^
    1200 94770baf + std::vector const& footprints,
    ? ++++ ^ bool const relativeIDs ) {
    1361 17d1d529 - std::vector::const_iterator fiter = footprints.begin();
    ? ^^^^^
    1203 94770baf + std::vector::const_iterator fiter = footprints.begin();
    ? ++++ ^ if (fiter == footprints.end()) { throw LSST_EXCEPT(
    1364 17d1d529 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    1206 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "You didn't provide any footprints" ); }
    1368 17d1d529 - Footprint::Ptr const foot = *fiter;
    1210 94770baf + CONST_PTR(Footprint) foot = *fiter;
    typename image::Image::Ptr idImage( new image::Image(foot->getRegion()) ); *idImage = 0; /* * do the work */ set_footprint_array_ids(idImage, footprints, relativeIDs); return idImage; } template image::Image::Ptr setFootprintArrayIDs(
    1383 17d1d529 - std::vector const& footprints,
    ? ^^^^^
    1225 94770baf + std::vector const& footprints,
    ? ++++ ^ bool const relativeIDs); /* * Set an image to the value of Footprint's ID wherever it may fall */ template typename boost::shared_ptr > setFootprintID(
    1390 17d1d529 - Footprint::Ptr const& foot, // the Footprint to insert
    ? ^^^^^^^^^^^
    1232 94770baf + CONST_PTR(Footprint)& foot, // the Footprint to insert
    ? ++++++++++ ^ int const id // the desired ID ) { typename image::Image::Ptr idImage(new image::Image(foot->getBBox())); *idImage = 0; /* * do the work */ set_footprint_id(idImage, *foot, id); return idImage; }
    1403 17d1d529 - template image::Image::Ptr setFootprintID(Footprint::Ptr const& foot, int const id);
    ? ^^^ ^ -----------------
    1245 94770baf + template image::Image::Ptr setFootprintID(CONST_PTR(Footprint)& foot, int const id);
    ? ++++++++++ ^^^^^^ ^^^^^
    1405 61b6195c - /***********************************************************************************************************/
    namespace {
    1248 fd3397a2 + /** Define a structuring element for use in RLE-based morphological operations
    1249 5b637e27 + *
    1250 dddc9b36 + * Provides pre-canned definition of circular & diamond shapes for use in
    1251 dddc9b36 + * isotropic and non-isotropic dilation respectively, as well as elements which
    1252 dddc9b36 + * can be used to grow in one or more of up/down/left/right.
    1253 f8edfe90 + */
    1254 dddc9b36 + class StructuringElement
    1407 61b6195c - //
    1408 61b6195c - // Utility routine to repack a list of Footprints into a single grown Footprint
    1409 61b6195c - //
    1410 61b6195c - PTR(Footprint)
    1411 61b6195c - convertGrownListToFootprint(FootprintSet::FootprintList const& grownList,
    1412 61b6195c - geom::Box2I const& bbox,
    1413 61b6195c - Footprint const& foot
    1414 61b6195c - )
    {
    1416 61b6195c - PTR(Footprint) grown = boost::make_shared();
    1417 61b6195c - grown->include(grownList, true);
    1256 dddc9b36 + public:
    1257 dddc9b36 + enum class Shape { CIRCLE, DIAMOND };
    1258 dddc9b36 + typedef std::vector::const_iterator const_iterator;
    1259 dddc9b36 + StructuringElement(Shape shape, int radius);
    1260 dddc9b36 + StructuringElement(int left, int right, int up, int down);
    1261 89e96d0e + const_iterator begin() const { return _widths.begin(); }
    1262 89e96d0e + const_iterator end() const { return _widths.end(); }
    1263 89e96d0e + int getYRange() const { return _yRange; }
    1264 dddc9b36 +
    1265 dddc9b36 + private:
    1266 89e96d0e + std::vector _widths;
    1267 89e96d0e + int _yRange;
    1268 dddc9b36 + };
    1269 dddc9b36 +
    1270 dddc9b36 + /** Create a shape-based StructuringElement
    1271 dddc9b36 + *
    1272 dddc9b36 + * Circles and diamonds are used in isotropic and non-isotropic grows,
    1273 dddc9b36 + * respetively.
    1274 dddc9b36 + */
    1275 dddc9b36 + StructuringElement::StructuringElement(Shape shape, int radius) {
    1276 89e96d0e + _yRange = 2*radius + 1;
    1277 89e96d0e + _widths.reserve(_yRange);
    1278 dddc9b36 + switch (shape) {
    1279 dddc9b36 + case Shape::CIRCLE:
    1280 dddc9b36 + for (auto dy = -radius; dy <= radius; dy++) {
    1281 89e96d0e + int dx = static_cast(sqrt(radius*radius - dy*dy));
    1282 89e96d0e + _widths.push_back(Span(dy, -dx, dx));
    1283 dddc9b36 + }
    1284 dddc9b36 + break;
    1285 dddc9b36 + case Shape::DIAMOND:
    1286 dddc9b36 + for (auto dy = -radius; dy <= radius; dy++) {
    1287 dddc9b36 + int dx = radius - abs(dy);
    1288 89e96d0e + _widths.push_back(Span(dy, -dx, dx));
    1289 dddc9b36 + }
    1290 dddc9b36 + break;
    1291 dddc9b36 + }
    1292 dddc9b36 + }
    1293 dddc9b36 +
    1294 dddc9b36 + /** Create a direction-based StructuringElement
    1295 dddc9b36 + *
    1296 dddc9b36 + * Used to grow in one or more of the left/right/up/down directions.
    1297 dddc9b36 + */
    1298 dddc9b36 + StructuringElement::StructuringElement(int left, int right, int up, int down) {
    1299 89e96d0e + _yRange = up + down + 1;
    1300 89e96d0e + _widths.reserve(_yRange);
    1301 dddc9b36 + for (auto dy = 1; dy <= up; dy++) {
    1302 89e96d0e + _widths.push_back(Span(dy, 0, 0));
    1303 dddc9b36 + }
    1304 dddc9b36 + for (auto dy = -1; dy >= -down; dy--) {
    1305 89e96d0e + _widths.push_back(Span(dy, 0, 0));
    1306 dddc9b36 + }
    1307 89e96d0e + _widths.push_back(Span(0, -left, right));
    1308 dddc9b36 + }
    1309 dddc9b36 +
    1310 dddc9b36 + /** RLE based implementation of Footprint dilation.
    1311 dddc9b36 + *
    1312 dddc9b36 + * See Kim et al., ETRI Journal 27, Dec 2005.
    1313 dddc9b36 + */
    1314 7cc5e55a + PTR(Footprint) growFootprintImpl(
    1315 dddc9b36 + Footprint const& foot, //!< The Footprint to grow
    1316 dddc9b36 + StructuringElement const& element //!< The structuring element
    1317 7cc5e55a + ) {
    1318 dddc9b36 + // Create an empty footprint covering foot's region.
    1319 dddc9b36 + PTR(Footprint) grown(new Footprint(0, foot.getRegion()));
    1320 f8edfe90 +
    1321 ca6bfc5f + // We use a map of (y coordinate) to set of (xmin, xmax) pairs to describe
    1322 ca6bfc5f + // the spans being constructed. In this way, we ensure that the spans are
    1323 ca6bfc5f + // always sorted by increasing y, xmin.
    1324 ca6bfc5f + std::map>> spans;
    1325 ca6bfc5f +
    1326 ca6bfc5f + // Iterate over foot & structuring element building up a collection of
    1327 ca6bfc5f + // spans which should be added to the footprint.
    1328 ca6bfc5f + for (auto spanIter = foot.getSpans().cbegin(); spanIter != foot.getSpans().cend(); ++spanIter) {
    1329 ca6bfc5f + for (auto elementIter = element.begin(); elementIter != element.end(); ++elementIter) {
    1330 ca6bfc5f + int const xmin = (*spanIter)->getX0() + elementIter->getX0();
    1331 ca6bfc5f + int const xmax = (*spanIter)->getX1() + elementIter->getX1();
    1332 ca6bfc5f + int const yval = (*spanIter)->getY() + elementIter->getY();
    1333 ca6bfc5f + spans[yval].insert(std::make_pair(xmin, xmax));
    1334 ca6bfc5f +
    1335 ca6bfc5f + // Merge overlapping spans at this y coordinate, thereby ensuring
    1336 ca6bfc5f + // that the proto-footprint remains normalized.
    1337 ca6bfc5f + std::set> newSpans;
    1338 ca6bfc5f + for (auto span = spans[yval].cbegin(); span != spans[yval].cend(); ++span) {
    1339 ca6bfc5f + int const start = span->first;
    1340 ca6bfc5f + int end = span->second;
    1341 ca6bfc5f + // Check for end+1 because end value is inclusive. That is, if
    1342 ca6bfc5f + // one span terminates at x=N and another begins at x=N+1,
    1343 ca6bfc5f + // those spans are contiguous.
    1344 ca6bfc5f + while (span != spans[yval].cend() && span->first <= (end+1)) {
    1345 ca6bfc5f + end = std::max(end, span++->second);
    1346 ca6bfc5f + }
    1347 ca6bfc5f + newSpans.insert(std::make_pair(start, end));
    1348 ca6bfc5f + --span; // "rewind" to the last span included
    1349 ca6bfc5f + }
    1350 ca6bfc5f + std::swap(spans[yval], newSpans);
    1351 2eb9dac3 + }
    1352 f8edfe90 + }
    1353 f8edfe90 +
    1354 ca6bfc5f + // Now append the spans to the output footprint, making use of the fact
    1355 ca6bfc5f + // that they are already normalized.
    1356 ca6bfc5f + for (auto y = spans.cbegin(); y != spans.cend(); ++y) {
    1357 ca6bfc5f + for (auto x = y->second.cbegin(); x != y->second.cend(); ++x) {
    1358 ca6bfc5f + grown->addSpanInSeries(y->first, x->first, x->second);
    1359 ca6bfc5f + }
    1360 ca6bfc5f + }
    // Copy over peaks from the original footprint
    1363 ecb01ab8 + grown->getPeaks() = PeakCatalog(foot.getPeaks().getTable(), foot.getPeaks().begin(),
    1364 ecb01ab8 + foot.getPeaks().end(), true);
    1365 ecb01ab8 +
    1420 3d19aa2b - grown->getPeaks() = PeakCatalog(
    1421 3d19aa2b - foot.getPeaks().getTable(),
    1422 3d19aa2b - foot.getPeaks().begin(), foot.getPeaks().end(),
    1423 3d19aa2b - true
    1424 3d19aa2b - );
    1425 61b6195c - //
    1426 61b6195c - // Fix the coordinate system to be that of foot
    1427 61b6195c - //
    1428 61b6195c - grown->shift(bbox.getMinX(), bbox.getMinY());
    1429 61b6195c - grown->setRegion(foot.getRegion());
    1430 61b6195c -
    return grown; }
    1434 61b6195c - /*
    1369 89e96d0e + /**
    ? +
    1435 61b6195c - * Grow a Footprint isotropically by r pixels, returning a new Footprint
    1370 89e96d0e + * Represents a "primary run", as defined by Kim et al. A primary run is an
    1371 89e96d0e + * intermediate result from the erosion operation; they represent potential
    1372 89e96d0e + * spans in the output footprint, but are not normalized.
    *
    1437 61b6195c - * N.b. this is slow, as it uses a convolution with a disk
    1374 89e96d0e + * The 'm' value tracks the row in the structuring element which was
    1375 89e96d0e + * responsible for a particular primary run; it is required to implement the
    1376 89e96d0e + * algorithm.
    */
    1378 89e96d0e + struct PrimaryRun {
    1379 89e96d0e + int m, y, xmin, xmax;
    1380 89e96d0e + };
    1440 61b6195c - Footprint::Ptr growFootprintSlow(
    1382 89e96d0e + /**
    1383 89e96d0e + * Compare primary runs such that they are sorted primarily by y, then by m,
    1384 89e96d0e + * then by xmin.
    1385 89e96d0e + */
    1386 89e96d0e + bool comparePrimaryRun(PrimaryRun const& first, PrimaryRun const& second) {
    1387 89e96d0e + if (first.y != second.y) {
    1388 89e96d0e + return first.y < second.y;
    1389 89e96d0e + } else if (first.m != second.m) {
    1390 89e96d0e + return first.m < second.m;
    1391 89e96d0e + } else {
    1392 89e96d0e + return first.xmin < second.xmin;
    1393 89e96d0e + }
    1394 89e96d0e + }
    1395 89e96d0e +
    1396 89e96d0e + class ComparePrimaryRunY{
    1397 89e96d0e + public:
    1398 89e96d0e + bool operator()(PrimaryRun const& pr, int yval) {
    1399 89e96d0e + return pr.y < yval;
    1400 89e96d0e + }
    1401 89e96d0e + bool operator()(int yval, PrimaryRun const& pr) {
    1402 89e96d0e + return yval < pr.y;
    1403 89e96d0e + }
    1404 89e96d0e + };
    1405 89e96d0e +
    1406 89e96d0e + class ComparePrimaryRunM{
    1407 89e96d0e + public:
    1408 89e96d0e + bool operator()(PrimaryRun const& pr, int mval) {
    1409 89e96d0e + return pr.m < mval;
    1410 89e96d0e + }
    1411 89e96d0e + bool operator()(int mval, PrimaryRun const& pr) {
    1412 89e96d0e + return mval < pr.m;
    1413 89e96d0e + }
    1414 89e96d0e + };
    1415 89e96d0e +
    1416 89e96d0e + /** RLE based implementation of Footprint erosion.
    1417 89e96d0e + *
    1418 89e96d0e + * See Kim et al., ETRI Journal 27, Dec 2005.
    1419 89e96d0e + */
    1420 89e96d0e + PTR(Footprint) shrinkFootprintImpl(
    1441 61b6195c - Footprint const& foot, //!< The Footprint to grow
    ? ---- ^ ^^
    1421 89e96d0e + Footprint const& foot, //!< The Footprint to shrink
    ? +++++++++++ ^^ ^^^
    1442 61b6195c - int ngrow //!< how much to grow foot
    1443 61b6195c - ) {
    1444 61b6195c - if (ngrow < 0) {
    1445 61b6195c - ngrow = 0; // ngrow == 0 => no grow
    1422 89e96d0e + StructuringElement const& element //!< The structuring element
    1423 89e96d0e + ) {
    1424 89e96d0e + // Create an empty FootprintSet covering the input region
    1425 89e96d0e + PTR(Footprint) shrunk(new Footprint(0, foot.getRegion()));
    1426 89e96d0e +
    1427 89e96d0e + // Calculate all possible primary runs.
    1428 89e96d0e + std::vector primaryRuns;
    1429 89e96d0e + for (auto spanIter = foot.getSpans().begin(); spanIter != foot.getSpans().end(); ++spanIter) {
    1430 89e96d0e + int m = 0;
    1431 89e96d0e + for (auto it = element.begin(); it != element.end(); ++it, ++m) {
    1432 89e96d0e + if ((it->getX1() - it->getX0()) <= ((*spanIter)->getX1() - (*spanIter)->getX0())) {
    1433 89e96d0e + int xmin = (*spanIter)->getX0() - it->getX0();
    1434 89e96d0e + int xmax = (*spanIter)->getX1() - it->getX1();
    1435 89e96d0e + int y = (*spanIter)->getY() - it->getY();
    1436 89e96d0e + primaryRuns.push_back(PrimaryRun({m, y, xmin, xmax}));
    1437 89e96d0e + }
    1446 d588836a - }
    1438 89e96d0e + }
    ? ++++
    1447 d588836a -
    1448 61b6195c - if (foot.getNpix() == 0) { // an empty Footprint
    1449 61b6195c - return Footprint::Ptr(new Footprint(foot));
    1450 d588836a - }
    1451 d588836a -
    1452 61b6195c - /*
    ? ^^
    1439 89e96d0e + }
    ? ^
    1453 61b6195c - * We'll insert the footprints into an image, then convolve with a disk,
    1454 61b6195c - * then extract a footprint from the result --- this is magically what we want.
    1455 61b6195c - */
    1456 61b6195c - geom::Box2I bbox = foot.getBBox();
    1457 61b6195c - bbox.grow(2*ngrow);
    1458 61b6195c - image::Image::Ptr idImage(new image::Image(bbox));
    1459 61b6195c - *idImage = 0;
    1460 61b6195c - idImage->setXY0(0, 0);
    1462 61b6195c - set_footprint_id(idImage, foot, 1, -bbox.getMinX(), -bbox.getMinY());
    1441 89e96d0e + // Iterate over the primary runs in such a way that we consider all values
    1442 89e96d0e + // of m for given y, then all m for y+1, etc.
    1443 89e96d0e + std::sort(primaryRuns.begin(), primaryRuns.end(), comparePrimaryRun);
    1445 89e96d0e + for (int y = primaryRuns.front().y; y <= primaryRuns.back().y; ++y) {
    1446 89e96d0e + auto yRange = std::equal_range(primaryRuns.begin(), primaryRuns.end(), y, ComparePrimaryRunY());
    1465 61b6195c - image::Image::Ptr circle_im(
    1466 61b6195c - new image::Image(geom::Extent2I(2*ngrow + 1, 2*ngrow + 1))
    1467 61b6195c - );
    1468 61b6195c - *circle_im = 0;
    1469 61b6195c - for (int r = -ngrow; r <= ngrow; ++r) {
    1470 61b6195c - image::Image::x_iterator row = circle_im->x_at(0, r + ngrow);
    1471 61b6195c - for (int c = -ngrow; c <= ngrow; ++c, ++row) {
    1472 61b6195c - if (r*r + c*c <= ngrow*ngrow) {
    1473 61b6195c - *row = 8;
    1448 89e96d0e + // Discard runs for any value of y for which we find fewer groups than
    1449 89e96d0e + // M, the total Y range of the structuring element. This is step 3.1
    1450 89e96d0e + // of the Kim et al. algorithm.
    1451 89e96d0e + if (std::distance(yRange.first, yRange.second) < element.getYRange()) {
    1452 89e96d0e + continue;
    1453 89e96d0e + }
    1454 89e96d0e +
    1455 89e96d0e + // "good" runs are those which are covered by each value of m, ie by
    1456 89e96d0e + // each row in the structuring element. Our algorithm will consider
    1457 89e96d0e + // each value of m in turn, gradually whittling down the list of good
    1458 89e96d0e + // runs, then finally convert the remainder into Spans and add them to
    1459 89e96d0e + // the shrunken Footprint.
    1460 89e96d0e + std::list goodRuns;
    1461 89e96d0e +
    1462 89e96d0e + for (int m = 0; m < element.getYRange(); ++m) {
    1463 89e96d0e + auto mRange = std::equal_range(yRange.first, yRange.second, m, ComparePrimaryRunM());
    1464 89e96d0e + if (mRange.first == mRange.second) {
    1465 89e96d0e + // If a particular m is missing, we know that this y contains
    1466 89e96d0e + // no good runs; this is equivalent to Kim et al. step 3.2.
    1467 89e96d0e + goodRuns.clear();
    1468 89e96d0e + } else {
    1469 89e96d0e + // Consolidate all primary runs at this m so that they
    1470 89e96d0e + // don't overlap.
    1471 89e96d0e + std::list candidateRuns;
    1472 89e96d0e + int start_x = mRange.first->xmin;
    1473 89e96d0e + int end_x = mRange.first->xmax;
    1474 89e96d0e + for (auto run = mRange.first+1; run != mRange.second; ++run) {
    1475 89e96d0e + if (run->xmin > end_x) {
    1476 89e96d0e + // Start of a new run
    1477 89e96d0e + candidateRuns.push_back(PrimaryRun{m, y, start_x, end_x});
    1478 89e96d0e + start_x = run->xmin;
    1479 89e96d0e + end_x = run->xmax;
    1480 89e96d0e + } else {
    1481 89e96d0e + // Continuation of an existing run
    1482 89e96d0e + end_x = run->xmax;
    1483 89e96d0e + }
    1474 d588836a - }
    1484 89e96d0e + }
    ? ++++
    1485 89e96d0e + candidateRuns.push_back(PrimaryRun{m, y, start_x, end_x});
    1486 89e96d0e +
    1487 89e96d0e + // Otherwise, calculate the intersection of candidate runs at
    1488 89e96d0e + // this m with good runs from all previous m.
    1489 89e96d0e + if (m == 0) {
    1490 89e96d0e + // For m = 0 we have nothing to compare to; all runs are
    1491 89e96d0e + // accepted.
    1492 89e96d0e + std::swap(goodRuns, candidateRuns);
    1493 89e96d0e + } else {
    1494 89e96d0e + std::list newlist;
    1495 89e96d0e + for (auto good = goodRuns.begin(); good != goodRuns.end(); ++good) {
    1496 89e96d0e + for (auto cand = candidateRuns.begin(); cand != candidateRuns.end(); ++cand) {
    1497 89e96d0e + int start = std::max(good->xmin, cand->xmin);
    1498 89e96d0e + int end = std::min(good->xmax, cand->xmax);
    1499 89e96d0e + if (end >= start) {
    1500 89e96d0e + newlist.push_back(PrimaryRun({m, y, start, end}));
    1501 89e96d0e + }
    1502 89e96d0e + }
    1503 89e96d0e + }
    1504 89e96d0e + std::swap(newlist, goodRuns);
    1505 89e96d0e + }
    1475 d588836a - }
    1506 89e96d0e + }
    ? ++++
    1476 d588836a - }
    1507 89e96d0e + }
    ? ++++
    1508 89e96d0e + for (auto run = goodRuns.begin(); run != goodRuns.end(); ++run) {
    1509 89e96d0e + shrunk->addSpan(run->y, run->xmin, run->xmax);
    1510 89e96d0e + }
    1511 89e96d0e + }
    1513 89e96d0e + shrunk->normalize();
    1478 61b6195c - math::FixedKernel::Ptr circle(new math::FixedKernel(*circle_im));
    1479 61b6195c - // Here's the actual grow step
    1480 61b6195c - image::MaskedImage::Ptr convolvedImage(new image::MaskedImage(idImage->getDimensions()));
    1481 61b6195c - math::convolve(*convolvedImage->getImage(), *idImage, *circle, false);
    1483 61b6195c - PTR(FootprintSet) grownList(new FootprintSet(*convolvedImage, 0.5, "", 1, false));
    1484 d588836a -
    1485 61b6195c - return convertGrownListToFootprint(*grownList->getFootprints(), bbox, foot);
    1515 ecb01ab8 + // Peaks from the original footprint have not yet been added to the shrunken footprint.
    1516 ecb01ab8 + // Iterate over peaks from the original footprint and add them IF they are contained
    1517 ecb01ab8 + // within the shrunken footprint.
    1518 ecb01ab8 + for (auto peakIter = foot.getPeaks().begin(); peakIter != foot.getPeaks().end(); peakIter++) {
    1519 ecb01ab8 + if (shrunk->contains(peakIter->getI())) {
    1520 ecb01ab8 + shrunk->getPeaks().addNew()->assign(*peakIter);
    1521 ecb01ab8 + }
    1522 ecb01ab8 + }
    1523 89e96d0e + return shrunk;
    } } /************************************************************************************************************/ namespace {
    1492 d9ace53f - Footprint::Ptr _mergeFootprints(Footprint const& foota, Footprint const& footb) {
    ? ^^^^^ ^ - ^ -
    1530 94770baf + PTR(Footprint) _mergeFootprints(Footprint const& aFoot, Footprint const& bFoot) {
    ? ++++ ^ ^^ ^^ PTR(Footprint) foot(new Footprint());
    1495 6ac35e07 - const PeakCatalog & pka = foota.getPeaks();
    1496 6ac35e07 - const PeakCatalog& pkb = footb.getPeaks();
    ? ^ - ^ -
    1533 1d5e7de8 + const PeakCatalog& aPeak = aFoot.getPeaks();
    ? ^^^^ ^^
    1534 1d5e7de8 + const PeakCatalog& bPeak = bFoot.getPeaks();
    1497 6ac35e07 - PeakCatalog& pk = foot->getPeaks();
    1535 1d5e7de8 + PeakCatalog& peaks = foot->getPeaks();
    ? ++ +
    1498 6ac35e07 - if (pka.empty()) {
    ? ^ -
    1536 1d5e7de8 + if (aPeak.empty()) {
    ? ^^^^
    1499 6ac35e07 - if (!pkb.empty()) {
    ? ^ -
    1537 1d5e7de8 + if (!bPeak.empty()) {
    ? ^^^^
    1500 6ac35e07 - pk = PeakCatalog(pkb.getTable(), pkb.begin(), pkb.end(), true);
    ? ^ - ^ - ^ -
    1538 1d5e7de8 + peaks = PeakCatalog(bPeak.getTable(), bPeak.begin(), bPeak.end(), true);
    ? ++ + ^^^^ ^^^^ ^^^^ } } else {
    1503 6ac35e07 - if (pkb.empty()) {
    ? ^ -
    1541 1d5e7de8 + if (bPeak.empty()) {
    ? ^^^^
    1504 6ac35e07 - pk = PeakCatalog(pka.getTable(), pka.begin(), pka.end(), true);
    ? ^ - ^ - ^ -
    1542 1d5e7de8 + peaks = PeakCatalog(aPeak.getTable(), aPeak.begin(), aPeak.end(), true);
    ? ++ + ^^^^ ^^^^ ^^^^ } else {
    1506 6ac35e07 - if (pka.getSchema() == pkb.getSchema()) {
    ? ^ - ^ -
    1544 1d5e7de8 + if (aPeak.getSchema() == bPeak.getSchema()) {
    ? ^^^^ ^^^^ // use schema A, as it's the same as schema B
    1508 6ac35e07 - pk = PeakCatalog(pka.getTable());
    ? ^ -
    1546 1d5e7de8 + peaks = PeakCatalog(aPeak.getTable());
    ? ++ + ^^^^
    1509 6ac35e07 - pk.reserve(pka.size() + pkb.size());
    ? ^ - ^ -
    1547 1d5e7de8 + peaks.reserve(aPeak.size() + bPeak.size());
    ? ++ + ^^^^ ^^^^
    1510 6ac35e07 - pk.insert(pk.end(), pka.begin(), pka.end(), true);
    ? ^ - ^ -
    1548 1d5e7de8 + peaks.insert(peaks.end(), aPeak.begin(), aPeak.end(), true);
    ? ++ + ++ + ^^^^ ^^^^
    1511 6ac35e07 - pk.insert(pk.end(), pkb.begin(), pkb.end(), true);
    ? ^ - ^ -
    1549 1d5e7de8 + peaks.insert(peaks.end(), bPeak.begin(), bPeak.end(), true);
    ? ++ + ++ + ^^^^ ^^^^ } else { throw LSST_EXCEPT(
    1514 6ac35e07 - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    1552 1d5e7de8 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Cannot merge Footprints when Peaks have different Schemas" ); } } }
    1521 d9ace53f - const Footprint::SpanList& spansa = foota.getSpans();
    1522 d9ace53f - const Footprint::SpanList& spansb = footb.getSpans();
    ? ------ ^ - ^ -
    1559 94770baf + Footprint::SpanList const& aSpans = aFoot.getSpans();
    ? ++++++ ^^ ^^
    1560 94770baf + Footprint::SpanList const& bSpans = bFoot.getSpans();
    1523 d9ace53f - Footprint::SpanList::const_iterator spa = spansa.begin();
    ? ^ ^ -
    1561 94770baf + Footprint::SpanList::const_iterator aSpan = aSpans.begin();
    ? ^^ + ^^
    1524 d9ace53f - Footprint::SpanList::const_iterator spb = spansb.begin();
    ? ^ ^^^^ -
    1562 94770baf + Footprint::SpanList::const_iterator bSpan = bSpans.begin();
    ? ^^ +++++ ^
    1525 d9ace53f - Footprint::SpanList::const_iterator enda = spansa.end();
    1526 d9ace53f - Footprint::SpanList::const_iterator endb = spansb.end();
    ? ^ - ^ -
    1563 94770baf + Footprint::SpanList::const_iterator aEnd = aSpans.end();
    ? ^^ ^^
    1564 94770baf + Footprint::SpanList::const_iterator bEnd = bSpans.end();
    1528 d9ace53f - foot->getSpans().reserve(std::max(spansa.size(), spansb.size()));
    ? ^ - ^ -
    1566 94770baf + foot->getSpans().reserve(std::max(aSpans.size(), bSpans.size()));
    ? ^^ ^^
    1530 d9ace53f - while ((spa != enda) && (spb != endb)) {
    ? ^ ^ - ^ ^ ^ -
    1568 94770baf + while ((aSpan != aEnd) && (bSpan != bEnd)) {
    ? ^^ + ^^ ^^ ^^ ^^
    1531 d9ace53f - int y = (*spa)->getY();
    ? ^
    1569 94770baf + int y = (*aSpan)->getY();
    ? ^^ +
    1532 d9ace53f - int x0 = (*spa)->getX0();
    ? ^
    1570 94770baf + int x0 = (*aSpan)->getX0();
    ? ^^ +
    1533 d9ace53f - int x1 = (*spa)->getX1();
    ? ^
    1571 94770baf + int x1 = (*aSpan)->getX1();
    ? ^^ +
    1534 d9ace53f - int yb = (*spb)->getY();
    ? ^ ^
    1572 94770baf + int yb = (*bSpan)->getY();
    ? ^^ ^^
    1535 d9ace53f - int xb0 = (*spb)->getX0();
    ? ^ ^
    1573 94770baf + int xb0 = (*bSpan)->getX0();
    ? ^^ ^^
    1536 d9ace53f - int xb1 = (*spb)->getX1();
    ? ^ ^
    1574 94770baf + int xb1 = (*bSpan)->getX1();
    ? ^^ ^^ if ((y < yb) || (y == yb && (x1 < (xb0-1)))) { // A is earlier -- add A foot->addSpanInSeries(y, x0, x1);
    1541 d9ace53f - spa++;
    ? ^ ^^
    1579 94770baf + ++aSpan;
    ? ^^^^ ^ continue; } if ((yb < y) || (y == yb && (xb1 < (x0-1)))) { // B is earlier -- add B foot->addSpanInSeries(yb, xb0, xb1);
    1547 d9ace53f - spb++;
    ? ---
    1585 94770baf + ++bSpan;
    ? +++++ continue; } assert(yb == y); // Overlap -- find connected spans from both iterators. x0 = std::min(x0, xb0); x1 = std::max(x1, xb1); // Union all connected spans
    1556 d9ace53f - spa++;
    ? ^ ^^
    1594 94770baf + ++aSpan;
    ? ^^^^ ^
    1557 d9ace53f - spb++;
    ? ---
    1595 94770baf + ++bSpan;
    ? +++++
    1558 d9ace53f - while (1) {
    ? ^
    1596 94770baf + while (true) {
    ? ^^^^
    1559 d9ace53f - if ((spa != enda) &&
    ? ^ ^ -
    1597 94770baf + if ((aSpan != aEnd) &&
    ? ^^ + ^^
    1560 d9ace53f - ((*spa)->getY() == y) &&
    ? ^
    1598 94770baf + ((*aSpan)->getY() == y) &&
    ? ^^ +
    1561 d9ace53f - ((*spa)->getX0() <= (x1+1))) {
    ? ^
    1599 94770baf + ((*aSpan)->getX0() <= (x1+1))) {
    ? ^^ +
    1562 d9ace53f - // *spa continues this span.
    ? ^
    1600 94770baf + // *aSpan continues this span.
    ? ^^ +
    1563 d9ace53f - x1 = std::max(x1, (*spa)->getX1());
    ? ^
    1601 94770baf + x1 = std::max(x1, (*aSpan)->getX1());
    ? ^^ +
    1564 d9ace53f - spa++;
    ? ^ ^^
    1602 94770baf + ++aSpan;
    ? ^^^^ ^ continue; }
    1567 d9ace53f - if ((spb != endb) &&
    ? ^ ^ ^ -
    1605 94770baf + if ((bSpan != bEnd) &&
    ? ^^ ^^ ^^
    1568 d9ace53f - ((*spb)->getY() == y) &&
    ? ^ ^
    1606 94770baf + ((*bSpan)->getY() == y) &&
    ? ^^ ^^
    1569 d9ace53f - ((*spb)->getX0() <= (x1+1))) {
    ? ^ ^
    1607 94770baf + ((*bSpan)->getX0() <= (x1+1))) {
    ? ^^ ^^
    1570 d9ace53f - // *spb continues this span.
    ? ^ ^
    1608 94770baf + // *bSpan continues this span.
    ? ^^ ^^
    1571 d9ace53f - x1 = std::max(x1, (*spb)->getX1());
    ? ^ ^
    1609 94770baf + x1 = std::max(x1, (*bSpan)->getX1());
    ? ^^ ^^
    1572 d9ace53f - spb++;
    ? ---
    1610 94770baf + ++bSpan;
    ? +++++ continue; } break; } foot->addSpanInSeries(y, x0, x1); }
    1579 d9ace53f - // At this point either "spa" or "spb" is at the end.
    ? ^ ^ ^
    1617 94770baf + // At this point either "aSpan" or "bSpan" is at the end.
    ? ^^ + ^^ ^^ // Add any remaining spans from "A".
    1582 d9ace53f - for (; spa != enda; spa++) {
    ? ^ ^ ^^^ ^^
    1620 94770baf + for (; aSpan != aEnd; ++aSpan) {
    ? ^^ + ^^ ++++ ^ ^
    1583 d9ace53f - foot->addSpanInSeries((*spa)->getY(), (*spa)->getX0(), (*spa)->getX1());
    ? ^ ^ ^
    1621 94770baf + foot->addSpanInSeries((*aSpan)->getY(), (*aSpan)->getX0(), (*aSpan)->getX1());
    ? ^^ + ^^ + ^^ + } // Add any remaining spans from "B".
    1586 d9ace53f - for (; spb != endb; spb++) {
    ? ^ ^ ^ - ---
    1624 94770baf + for (; bSpan != bEnd; ++bSpan) {
    ? ^^ ^^ ^^ +++++
    1587 d9ace53f - foot->addSpanInSeries((*spb)->getY(), (*spb)->getX0(), (*spb)->getX1());
    ? ^ ^ ^ ^ ^ ^
    1625 94770baf + foot->addSpanInSeries((*bSpan)->getY(), (*bSpan)->getX0(), (*bSpan)->getX1());
    ? ^^ ^^ ^^ ^^ ^^ ^^ } return foot; } }
    1593 e880cec9 - /**
    1594 e880cec9 - Merges two Footprints -- appends their peaks, and unions their
    1595 e880cec9 - spans, returning a new Footprint.
    1596 e880cec9 - */
    1597 7ac2306a - Footprint::Ptr mergeFootprints(Footprint& foot1, Footprint& foot2) {
    ? ^^^^^
    1631 94770baf + PTR(Footprint) mergeFootprints(Footprint& foot1, Footprint& foot2) {
    ? ++++ ^ foot1.normalize(); foot2.normalize(); return _mergeFootprints(foot1, foot2); }
    1602 e880cec9 - /**
    1603 e880cec9 - Merges two Footprints -- appends their peaks, and unions their
    1604 e880cec9 - spans, returning a new Footprint.
    1606 e880cec9 - This const version requires that both input footprints are
    1607 e880cec9 - normalized (and will raise an exception if not).
    1608 e880cec9 - */
    1609 d9ace53f - Footprint::Ptr mergeFootprints(Footprint const& foot1, Footprint const& foot2) {
    ? ^^^^^
    1637 94770baf + PTR(Footprint) mergeFootprints(Footprint const& foot1, Footprint const& foot2) {
    ? ++++ ^ if (!foot1.isNormalized() || !foot2.isNormalized()) {
    1611 d9ace53f - throw LSST_EXCEPT
    1639 94770baf + throw LSST_EXCEPT(
    ? +
    1612 d9ace53f - (lsst::pex::exceptions::InvalidParameterException,
    ? - ^^^^^^ ^
    1640 a4c91494 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^
    1613 d9ace53f - "mergeFootprints(const Footprints) requires normalize()d Footprints.");
    ? -
    1641 94770baf + "mergeFootprints(const Footprints) requires normalize()d Footprints.");
    } return _mergeFootprints(foot1, foot2); } /************************************************************************************************************/
    1620 9337578a - void nearestFootprint(std::vector const& foots,
    ? ^^^^^
    1648 94770baf + void nearestFootprint(std::vector const& foots,
    ? ++++ ^ image::Image::Ptr argmin, image::Image::Ptr dist) { /*
    1625 9337578a - * insert the footprints into an image, set all the pixels to the Manhatten distance from the
    ? ----------------------------
    1653 94770baf + * insert the footprints into an image, set all the pixels to the
    1626 9337578a - * nearest set pixel.
    1654 94770baf + * Manhattan distance from the nearest set pixel.
    */ typedef boost::uint16_t dtype; typedef boost::uint16_t itype;
    1631 9337578a - itype nil = 0xffff;
    1659 94770baf + const itype nil = 0xffff;
    ? ++++++
    1633 9337578a - geom::Box2I bbox = argmin->getBBox(image::PARENT);
    ? -------------
    1661 93994d54 + const geom::Box2I bbox = argmin->getBBox();
    ? ++++++ *argmin = 0;
    1635 9337578a - //image::Image::Ptr dist(new image::Image(bbox));
    *dist = 0;
    1638 9337578a - int x0 = bbox.getMinX();
    1665 94770baf + int const x0 = bbox.getMinX();
    ? ++++++
    1639 9337578a - int y0 = bbox.getMinY();
    1666 94770baf + int const y0 = bbox.getMinY();
    ? ++++++
    1641 9337578a - for (size_t i=0; i ? -
    1668 94770baf + for (size_t i=0; i ? + // Set all the pixels in the footprint to 1 set_footprint_id(argmin, *foots[i], i, -x0, -y0); set_footprint_id(dist, *foots[i], 1, -x0, -y0); } int const height = dist->getHeight(); int const width = dist->getWidth(); // traverse from bottom left to top right for (int y = 0; y != height; ++y) { image::Image::xy_locator dim = dist->xy_at(0, y); image::Image::xy_locator aim = argmin->xy_at(0, y); for (int x = 0; x != width; ++x, ++dim.x(), ++aim.x()) { if (dim(0, 0) == 1) { // first pass and pixel was on, it gets a zero dim(0, 0) = 0; // its argmin is already set } else {
    1660 9337578a - // pixel was off. It is at most the sum of lengths of the array away from a pixel that is on
    ? ---------------------------------------
    1687 94770baf + // pixel was off. It is at most the sum of lengths of
    1688 94770baf + // the array away from a pixel that is on
    dim(0, 0) = width + height; aim(0, 0) = nil; // or one more than the pixel to the north if (y > 0) { dtype ndist = dim(0,-1) + 1; if (ndist < dim(0,0)) { dim(0,0) = ndist; aim(0,0) = aim(0,-1); } } // or one more than the pixel to the west if (x > 0) { dtype ndist = dim(-1,0) + 1; if (ndist < dim(0,0)) { dim(0,0) = ndist; aim(0,0) = aim(-1,0); } } } } } // traverse from top right to bottom left for (int y = height - 1; y >= 0; --y) { image::Image::xy_locator dim = dist->xy_at(width-1, y); image::Image::xy_locator aim = argmin->xy_at(width-1, y); for (int x = width - 1; x >= 0; --x, --dim.x(), --aim.x()) {
    1687 9337578a - // either what we had on the first pass or one more than the pixel to the south
    ? -----------------------
    1715 94770baf + // either what we had on the first pass or one more than
    1716 94770baf + // the pixel to the south
    if (y + 1 < height) { dtype ndist = dim(0,1) + 1; if (ndist < dim(0,0)) { dim(0,0) = ndist; aim(0,0) = aim(0,1); } } // or one more than the pixel to the east if (x + 1 < width) { dtype ndist = dim(1,0) + 1; if (ndist < dim(0,0)) { dim(0,0) = ndist; aim(0,0) = aim(1,0); } } } } }
    1707 61b6195c -
    1708 61b6195c - /**
    1709 61b6195c - * Grow a Footprint by ngrow pixels, returning a new Footprint
    1710 61b6195c - */
    1711 61b6195c - Footprint::Ptr growFootprint(
    ? ^^^^^
    1736 94770baf + PTR(Footprint) growFootprint(
    ? ++++ ^ Footprint const& foot, //!< The Footprint to grow
    1713 61b6195c - int ngrow, //!< how much to grow foot
    1738 dddc9b36 + int nGrow, //!< how much to grow foot
    bool isotropic //!< Grow isotropically (as opposed to a Manhattan metric)
    1715 61b6195c - //!< @note Isotropic grows are significantly slower
    1740 b0e170fa + ) {
    1741 dddc9b36 + if (nGrow <= 0 || foot.getNpix() == 0 ) {
    1742 b0e170fa + // Return a new footprint equal to the input.
    1743 b0e170fa + return PTR(Footprint)(new Footprint(foot));
    1744 5b637e27 + }
    1745 5b637e27 +
    1746 dddc9b36 + // An isotropic grow is equivalent to growing with a circular structuring
    1747 dddc9b36 + // element, while a Manhattan grow is equivalent to growing with a
    1748 dddc9b36 + // diamond-shaped element.
    1749 dddc9b36 + typedef StructuringElement::Shape Shape;
    1750 dddc9b36 + Shape shape = isotropic ? Shape::CIRCLE : Shape::DIAMOND;
    1751 dddc9b36 + return growFootprintImpl(foot, StructuringElement(shape, nGrow));
    1752 f8edfe90 + }
    1753 f8edfe90 +
    1754 dddc9b36 + PTR(Footprint) growFootprint(PTR(Footprint) const& foot, int nGrow, bool isotropic) {
    1755 dddc9b36 + return growFootprint(*foot, nGrow, isotropic);
    1756 4b1be60a + }
    1757 4b1be60a +
    1758 dddc9b36 + PTR(Footprint) growFootprint(Footprint const& foot, ///< Footprint to grow
    1759 dddc9b36 + int nGrow, ///< How many pixels to grow it
    1760 dddc9b36 + bool left, ///< grow to the left
    1761 dddc9b36 + bool right, ///< grow to the right
    1762 dddc9b36 + bool up, ///< grow up
    1763 dddc9b36 + bool down ///< grow down
    ) {
    1766 dddc9b36 + if (nGrow <= 0 || foot.getNpix() == 0 ) {
    1767 dddc9b36 + // Return a new footprint equal to the input.
    1768 dddc9b36 + return PTR(Footprint)(new Footprint(foot));
    1718 61b6195c - if (isotropic) {
    1719 61b6195c - return growFootprintSlow(foot, ngrow);
    1720 61b6195c - }
    1721 61b6195c -
    1722 61b6195c - if (ngrow < 0) {
    1723 61b6195c - ngrow = 0; // ngrow == 0 => no grow
    1724 61b6195c - }
    1725 61b6195c - /*
    ? ^^
    1769 868f131e + }
    ? ^
    1770 dddc9b36 + return growFootprintImpl(foot, StructuringElement(left ? nGrow: 0, right ? nGrow : 0,
    1771 dddc9b36 + up ? nGrow : 0, down ? nGrow : 0));
    1726 61b6195c - * We'll insert the footprints into an image, set all the pixels to the Manhatten distance from the
    1727 61b6195c - * nearest set pixel, then extract a footprint from the result
    1728 61b6195c - *
    1729 61b6195c - * Cf. http://ostermiller.org/dilate_and_erode.html
    1730 61b6195c - */
    1731 61b6195c - geom::Box2I bbox = foot.getBBox();
    1732 61b6195c - bbox.grow(ngrow);
    1733 61b6195c - image::Image::Ptr idImage(new image::Image(bbox));
    1734 61b6195c - *idImage = 0;
    1735 61b6195c - idImage->setXY0(0, 0);
    1736 61b6195c -
    1737 61b6195c - // Set all the pixels in the footprint to 1
    1738 61b6195c - set_footprint_id(idImage, foot, 1, -bbox.getMinX(), -bbox.getMinY());
    1739 61b6195c - //
    1740 61b6195c - // Set the idImage to the Manhattan distance from the nearest set pixel
    1741 61b6195c - //
    1742 61b6195c - int const height = idImage->getHeight();
    1743 61b6195c - int const width = idImage->getWidth();
    1744 61b6195c -
    1745 61b6195c - // traverse from bottom left to top right
    1746 61b6195c - for (int y = 0; y != height; ++y) {
    1747 61b6195c - image::Image::xy_locator im = idImage->xy_at(0, y);
    1748 61b6195c -
    1749 61b6195c - for (int x = 0; x != width; ++x, ++im.x()) {
    1750 61b6195c - if (im(0, 0) == 1) {
    1751 61b6195c - // first pass and pixel was on, it gets a zero
    1752 61b6195c - im(0, 0) = 0;
    1753 61b6195c - } else {
    1754 61b6195c - // pixel was off. It is at most the sum of lengths of the array away from a pixel that is on
    1755 61b6195c - im(0, 0) = width + height;
    1756 61b6195c - // or one more than the pixel to the north
    1757 61b6195c - if (y > 0) {
    1758 61b6195c - // im(0, 0)[0] == static_cast(im(0, 0))
    1759 61b6195c - im(0, 0) = std::min(im(0, 0)[0], im(0, -1) + 1);
    1760 61b6195c - }
    1761 61b6195c - // or one more than the pixel to the west
    1762 61b6195c - if (x > 0) {
    1763 61b6195c - im(0, 0) = std::min(im(0, 0)[0], im(-1, 0) + 1);
    1764 61b6195c - }
    1765 61b6195c - }
    1766 61b6195c - }
    1767 5b637e27 - }
    1768 61b6195c - // traverse from top right to bottom left
    1769 61b6195c - for (int y = height - 1; y >= 0; --y) {
    1770 61b6195c - image::Image::xy_locator im = idImage->xy_at(width - 1, y);
    1771 61b6195c - for (int x = width - 1; x >= 0; --x, --im.x()) {
    1772 61b6195c - // either what we had on the first pass or one more than the pixel to the south
    1773 61b6195c - if (y + 1 < height) {
    1774 61b6195c - im(0, 0) = std::min(im(0, 0)[0], im(0, 1) + 1);
    1775 61b6195c - }
    1776 61b6195c - // or one more than the pixel to the east
    1777 61b6195c - if (x + 1 < width) {
    1778 61b6195c - im(0, 0) = std::min(im(0, 0)[0], im(1, 0) + 1);
    1779 61b6195c - }
    1780 61b6195c - }
    1781 61b6195c - }
    1782 61b6195c -
    1783 61b6195c - image::MaskedImage::Ptr midImage(new image::MaskedImage(idImage));
    1784 61b6195c - // XXX Why do I need a -ve threshold when parity == false? I'm looking for pixels below ngrow
    1785 61b6195c - PTR(FootprintSet) grownList(new FootprintSet(*midImage, Threshold(-ngrow, Threshold::VALUE, false)));
    1786 2e46fcbb -
    1787 61b6195c - return convertGrownListToFootprint(*grownList->getFootprints(), bbox, foot);
    }
    1790 61b6195c - /**
    1791 61b6195c - * \note Deprecated interface; use the Footprint const& version
    1792 61b6195c - */
    1793 61b6195c - Footprint::Ptr growFootprint(Footprint::Ptr const& foot, int ngrow, bool isotropic) {
    1794 61b6195c - return growFootprint(*foot, ngrow, isotropic);
    1795 4b1be60a - }
    1775 89e96d0e + PTR(Footprint) shrinkFootprint(
    1776 89e96d0e + Footprint const& foot, //!< The Footprint to shrink
    1777 ae20e2b5 + int nShrink, //!< How much to grow foot
    1778 ae20e2b5 + bool isotropic //!< Shrink isotropically (as opposed to a Manhattan metric)
    1779 89e96d0e + ) {
    1780 ae20e2b5 + typedef StructuringElement::Shape Shape;
    1781 ae20e2b5 + Shape shape = isotropic ? Shape::CIRCLE : Shape::DIAMOND;
    1782 ae20e2b5 + return shrinkFootprintImpl(foot, StructuringElement(shape, nShrink));
    1797 61b6195c - /**
    1798 61b6195c - * \brief Grow a Foorprint in at least one of the cardinal directions, returning a new Footprint
    1799 61b6195c - *
    1800 61b6195c - * Note that any left/right grow is done prior to the up/down grow, so any left/right grown pixels
    1801 61b6195c - * \em are subject to a further up/down grow (i.e. an initial single pixel Footprint will end up
    1802 61b6195c - * as a square, not a cross.
    1803 61b6195c - */
    1804 61b6195c - PTR(Footprint) growFootprint(Footprint const& old, ///< Footprint to grow
    1805 61b6195c - int nGrow, ///< How many pixels to grow it
    1806 61b6195c - bool left, ///< grow to the left
    1807 61b6195c - bool right, ///< grow to the right
    1808 61b6195c - bool up, ///< grow up
    1809 61b6195c - bool down ///< grow down
    1810 8687de82 - )
    1811 8687de82 - {
    1812 61b6195c - Footprint::Ptr grown(new Footprint(old.getPeaks().getSchema(), 0, old.getRegion()));
    1813 61b6195c -
    1814 61b6195c - for (Footprint::SpanList::const_iterator siter = old.getSpans().begin();
    1815 61b6195c - siter != old.getSpans().end(); ++siter) {
    1816 61b6195c - CONST_PTR(Span) span = *siter;
    1817 61b6195c - int y=span->getY();
    1818 61b6195c - int x0 = (left) ? span->getX0() - nGrow : span->getX0();
    1819 61b6195c - int x1 = (right) ? span->getX1() + nGrow : span->getX1();
    1820 61b6195c - grown->addSpan(y, x0, x1);
    1821 61b6195c - if (up) {
    1822 61b6195c - for(int i=1; i <=nGrow; i++) {
    1823 61b6195c - grown->addSpan(y+i,span->getX0(), span->getX1());
    1824 61b6195c - }
    1825 61b6195c - }
    1826 61b6195c - if (down) {
    1827 61b6195c - for(int i=1; i <=nGrow; i++) {
    1828 61b6195c - grown->addSpan(y-i, span->getX0(), span->getX1());
    1829 61b6195c - }
    1830 61b6195c - }
    1831 868f131e - }
    1832 22fe6abd -
    1833 61b6195c - //normalize to remove overlapped spans and correct bbox
    1834 61b6195c - grown->normalize();
    1835 61b6195c - return grown;
    } /************************************************************************************************************/
    1786 94770baf +
    1839 a716b827 - /**
    1840 a716b827 - * Return a list of BBox%s, whose union contains exactly the pixels in foot, neither more nor less
    1841 a716b827 - *
    1842 a716b827 - * Useful in generating sets of meas::algorithms::Defects for the ISR
    1843 a716b827 - */
    std::vector footprintToBBoxList(Footprint const& foot) { typedef boost::uint16_t ImageT; geom::Box2I fpBBox = foot.getBBox(); image::Image::Ptr idImage( new image::Image(fpBBox.getDimensions()) ); *idImage = 0; int const height = fpBBox.getHeight(); geom::Extent2I shift(fpBBox.getMinX(), fpBBox.getMinY()); foot.insertIntoImage(*idImage, 1, fpBBox); std::vector bboxes; /* * Our strategy is to find a row of pixels in the Footprint and interpret it as the first * row of a rectangular set of pixels. We then extend this rectangle upwards as far as it * will go, and define that as a BBox. We clear all those pixels, and repeat until there * are none left. I.e. a Footprint will get cut up like this: * * .555... * 22.3314 * 22.331. * .000.1. * (as shown in Footprint_1.py) */ int y0 = 0; // the first row with non-zero pixels in it while (y0 < height) { geom::Box2I bbox; // our next BBox for (int y = y0; y != height; ++y) { // Look for a set pixel in this row image::Image::x_iterator begin = idImage->row_begin(y), end = idImage->row_end(y); image::Image::x_iterator first = std::find(begin, end, 1); if (first != end) { // A pixel is set in this row image::Image::x_iterator last = std::find(first, end, 0) - 1; int const x0 = first - begin; int const x1 = last - begin; std::fill(first, last + 1, 0); // clear pixels; we don't want to see them again bbox.include(geom::Point2I(x0, y)); // the LLC bbox.include(geom::Point2I(x1, y)); // the LRC; initial guess for URC // we found at least one pixel so extend the BBox upwards for (++y; y != height; ++y) { if (std::find(idImage->at(x0, y), idImage->at(x1 + 1, y), 0) != idImage->at(x1 + 1, y)) { break; // some pixels weren't set, so the BBox stops here, (actually in previous row) } std::fill(idImage->at(x0, y), idImage->at(x1 + 1, y), 0); bbox.include(geom::Point2I(x1, y)); // the new URC } bbox.shift(shift); bboxes.push_back(bbox); } else { y0 = y + 1; } break; } } return bboxes; } template void copyWithinFootprint(Footprint const& foot, PTR(ImageOrMaskedImageT) const input, PTR(ImageOrMaskedImageT) output) { Footprint::SpanList spans = foot.getSpans();
    1916 76f3706f -
    1917 6201600d - int const inX0 = input->getX0(), inY0 = input->getY0();
    1918 6201600d - int const outX0 = output->getX0(), outY0 = output->getY0();
    1919 6201600d -
    1920 6201600d - int const xMin = std::max(inX0, outX0);
    1921 6201600d - int const xMax = std::min(input->getWidth() + inX0, output->getWidth() + outX0) - 1;
    for (Footprint::SpanList::iterator sp = spans.begin(); sp != spans.end(); ++sp) {
    1924 bd5612b0 - int const y = (*sp)->getY();
    ? ------
    1861 36cfb16b + int y = (*sp)->getY();
    1925 bd5612b0 - int const x0 = (*sp)->getX0();
    ? ------
    1862 36cfb16b + int x0 = (*sp)->getX0();
    1926 bd5612b0 - int const x1 = (*sp)->getX1();
    ? ------
    1863 36cfb16b + int x1 = (*sp)->getX1();
    1927 76f3706f -
    1928 6201600d - int const yInput = y - inY0, yOutput = y - outY0;
    1929 76f3706f - if (yInput < 0 || yInput >= input->getHeight() || yOutput < 0 || yOutput >= output->getHeight()) {
    1930 76f3706f - continue;
    1931 76f3706f - }
    1932 76f3706f -
    1933 6201600d - int const xStart = std::max(x0, xMin); // Starting position in x, parent frame
    1934 6201600d - int const xStop = std::min(x1, xMax); // Stopping position (inclusive) in x, parent frame
    1935 6201600d -
    1936 6201600d - typename ImageOrMaskedImageT::const_x_iterator initer = input->x_at(xStart - inX0, yInput);
    ? -----------------------
    1864 36cfb16b + typename ImageOrMaskedImageT::const_x_iterator initer = input->x_at(
    1865 36cfb16b + x0 - input->getX0(), y - input->getY0());
    1937 6201600d - typename ImageOrMaskedImageT::x_iterator outiter = output->x_at(xStart - outX0, yOutput);
    ? -------------------------
    1866 36cfb16b + typename ImageOrMaskedImageT::x_iterator outiter = output->x_at(
    1867 36cfb16b + x0 - output->getX0(), y - output->getY0());
    1938 6201600d - for (int x = xStart; x <= xStop; ++x, ++initer, ++outiter) {
    ? - - ^^^^^ ^^^^
    1868 36cfb16b + for (int x=x0; x <= x1; ++x, ++initer, ++outiter) {
    ? ^ ^ *outiter = *initer; } } } #if 0 /************************************************************************************************************/ /* * Grow a psArray of pmFootprints isotropically by r pixels, returning a new psArray of new pmFootprints */ psArray *pmGrowFootprintArray(psArray const *footprints, // footprints to grow int r) { // how much to grow each footprint assert (footprints->n == 0 || pmIsFootprint(footprints->data[0])); if (footprints->n == 0) { // we don't know the size of the footprint's region return psArrayAlloc(0); } /* * We'll insert the footprints into an image, then convolve with a disk, * then extract a footprint from the result --- this is magically what we want. */ psImage *idImage = pmSetFootprintArrayIDs(footprints, true); if (r <= 0) { r = 1; // r == 1 => no grow } psKernel *circle = psKernelAlloc(-r, r, -r, r); assert (circle->image->numRows == 2*r + 1 && circle->image->numCols == circle->image->numRows);
    1970 f8edfe90 - for (int i = 0; i <= r; i++) {
    ? -
    1900 94770baf + for (int i = 0; i <= r; ++i) {
    ? +
    1971 2eb9dac3 - for (int j = 0; j <= r; j++) {
    ? -
    1901 94770baf + for (int j = 0; j <= r; ++j) {
    ? + if (i*i + j*j <= r*r) { circle->kernel[i][j] = circle->kernel[i][-j] = circle->kernel[-i][j] = circle->kernel[-i][-j] = 1; } } } psImage *grownIdImage = psImageConvolveDirect(idImage, circle); // Here's the actual grow step psFree(circle); psArray *grown = pmFindFootprints(grownIdImage, 0.5, 1); // and here we rebuild the grown footprints assert (grown != NULL); psFree(idImage); psFree(grownIdImage); /* * Now assign the peaks appropriately. We could do this more efficiently * using grownIdImage (which we just freed), but this is easy and probably fast enough */ psArray const *peaks = pmFootprintArrayToPeaks(footprints); pmPeaksAssignToFootprints(grown, peaks); psFree((psArray *)peaks); return grown; } /************************************************************************************************************/ /* * Merge together two psArrays of pmFootprints neither of which is damaged. * * The returned psArray may contain elements of the inital psArrays (with * their reference counters suitable incremented) */ psArray *pmMergeFootprintArrays(psArray const *footprints1, // one set of footprints psArray const *footprints2, // the other set int const includePeaks) { // which peaks to set? 0x1 => footprints1, 0x2 => 2 assert (footprints1->n == 0 || pmIsFootprint(footprints1->data[0])); assert (footprints2->n == 0 || pmIsFootprint(footprints2->data[0])); if (footprints1->n == 0 || footprints2->n == 0) { // nothing to do but put copies on merged psArray const *old = (footprints1->n == 0) ? footprints2 : footprints1; psArray *merged = psArrayAllocEmpty(old->n);
    2016 2eb9dac3 - for (int i = 0; i < old->n; i++) {
    ? -
    1946 94770baf + for (int i = 0; i < old->n; ++i) {
    ? + psArrayAdd(merged, 1, old->data[i]); } return merged; } /* * We have real work to do as some pmFootprints in footprints2 may overlap * with footprints1 */ { pmFootprint *fp1 = footprints1->data[0]; pmFootprint *fp2 = footprints2->data[0]; if (fp1->region.x0 != fp2->region.x0 || fp1->region.x1 != fp2->region.x1 || fp1->region.y0 != fp2->region.y0 || fp1->region.y1 != fp2->region.y1) { psError(PS_ERR_BAD_PARAMETER_SIZE, true, "The two pmFootprint arrays correspnond to different-sized regions"); return NULL; } } /* * We'll insert first one set of footprints then the other into an image, then * extract a footprint from the result --- this is magically what we want. */ psImage *idImage = pmSetFootprintArrayIDs(footprints1, true); set_footprint_array_ids(idImage, footprints2, true); psArray *merged = pmFindFootprints(idImage, 0.5, 1); assert (merged != NULL); psFree(idImage); /* * Now assign the peaks appropriately. We could do this more efficiently * using idImage (which we just freed), but this is easy and probably fast enough */ if (includePeaks & 0x1) { psArray const *peaks = pmFootprintArrayToPeaks(footprints1); pmPeaksAssignToFootprints(merged, peaks); psFree((psArray *)peaks); } if (includePeaks & 0x2) { psArray const *peaks = pmFootprintArrayToPeaks(footprints2); pmPeaksAssignToFootprints(merged, peaks); psFree((psArray *)peaks); } return merged; } /************************************************************************************************************/ /* * Given a psArray of pmFootprints and another of pmPeaks, assign the peaks to the * footprints in which that fall; if they _don't_ fall in a footprint, add a suitable * one to the list. */ psErrorCode pmPeaksAssignToFootprints(psArray *footprints, // the pmFootprints psArray const *peaks) { // the pmPeaks assert (footprints != NULL); assert (footprints->n == 0 || pmIsFootprint(footprints->data[0])); assert (peaks != NULL); assert (peaks->n == 0 || pmIsPeak(peaks->data[0])); if (footprints->n == 0) { if (peaks->n > 0) { return psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Your list of footprints is empty"); } return PS_ERR_NONE; } /* * Create an image filled with the object IDs, and use it to assign pmPeaks to the * objects */ psImage *ids = pmSetFootprintArrayIDs(footprints, true); assert (ids != NULL); assert (ids->type.type == PS_TYPE_S32); int const y0 = ids->y0; int const x0 = ids->x0; int const numRows = ids->numRows; int const numCols = ids->numCols;
    2099 f8edfe90 - for (int i = 0; i < peaks->n; i++) {
    ? -
    2029 94770baf + for (int i = 0; i < peaks->n; ++i) {
    ? + pmPeak *peak = peaks->data[i]; int const x = peak->x - x0; int const y = peak->y - y0; assert (x >= 0 && x < numCols && y >= 0 && y < numRows); int id = ids->data.S32[y][x - x0]; if (id == 0) { // peak isn't in a footprint, so make one for it pmFootprint *nfp = pmFootprintAlloc(1, ids); pmFootprintAddSpan(nfp, y, x, x); psArrayAdd(footprints, 1, nfp); psFree(nfp); id = footprints->n; } assert (id >= 1 && id <= footprints->n); pmFootprint *fp = footprints->data[id - 1]; psArrayAdd(fp->peaks, 5, peak); } psFree(ids); // // Make sure that peaks within each footprint are sorted and unique //
    2124 f8edfe90 - for (int i = 0; i < footprints->n; i++) {
    ? -
    2054 94770baf + for (int i = 0; i < footprints->n; ++i) {
    ? + pmFootprint *fp = footprints->data[i]; fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN);
    2128 2eb9dac3 - for (int j = 1; j < fp->peaks->n; j++) { // check for duplicates
    ? -
    2058 94770baf + for (int j = 1; j < fp->peaks->n; ++j) { // check for duplicates
    ? + if (fp->peaks->data[j] == fp->peaks->data[j-1]) { (void)psArrayRemoveIndex(fp->peaks, j); j--; // we moved everything down one } } } return PS_ERR_NONE; } /************************************************************************************************************/ /* * Examine the peaks in a pmFootprint, and throw away the ones that are not sufficiently * isolated. More precisely, for each peak find the highest coll that you'd have to traverse * to reach a still higher peak --- and if that coll's more than nsigma DN below your * starting point, discard the peak. */ psErrorCode pmFootprintCullPeaks(psImage const *img, // the image wherein lives the footprint psImage const *weight, // corresponding variance image pmFootprint *fp, // Footprint containing mortal peaks float const nsigma_delta, // how many sigma above local background a peak // needs to be to survive float const min_threshold) { // minimum permitted coll height assert (img != NULL); assert (img->type.type == PS_TYPE_F32); assert (weight != NULL); assert (weight->type.type == PS_TYPE_F32); assert (img->y0 == weight->y0 && img->x0 == weight->x0); assert (fp != NULL); if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do return PS_ERR_NONE; } psRegion subRegion; // desired subregion; 1 larger than bounding box (grr) subRegion.x0 = fp->bbox.x0; subRegion.x1 = fp->bbox.x1 + 1; subRegion.y0 = fp->bbox.y0; subRegion.y1 = fp->bbox.y1 + 1; psImage const *subImg = psImageSubset((psImage *)img, subRegion); psImage const *subWt = psImageSubset((psImage *)weight, subRegion); assert (subImg != NULL && subWt != NULL); // // We need a psArray of peaks brighter than the current peak. We'll fake this // by reusing the fp->peaks but lying about n. // // We do this for efficiency (otherwise I'd need two peaks lists), and we are // rather too chummy with psArray in consequence. But it works. // psArray *brightPeaks = psArrayAlloc(0); psFree(brightPeaks->data); brightPeaks->data = psMemIncrRefCounter(fp->peaks->data);// use the data from fp->peaks // // The brightest peak is always safe; go through other peaks trying to cull them //
    2184 f8edfe90 - for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop
    ? -
    2114 94770baf + for (int i = 1; i < fp->peaks->n; ++i) { // n.b. fp->peaks->n can change within the loop
    ? + pmPeak const *peak = fp->peaks->data[i]; int x = peak->x - subImg->x0; int y = peak->y - subImg->y0; // // Find the level nsigma below the peak that must separate the peak // from any of its friends // assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows); float const stdev = std::sqrt(subWt->data.F32[y][x]); float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev; if (lsst::utils::isnan(threshold) || threshold < min_threshold) { #if 1 // min_threshold is assumed to be below the detection threshold, // so all the peaks are pmFootprint, and this isn't the brightest (void)psArrayRemoveIndex(fp->peaks, i); i--; // we moved everything down one continue; #else #error n.b. We will be running LOTS of checks at this threshold, so only find the footprint once threshold = min_threshold; #endif } if (threshold > subImg->data.F32[y][x]) { threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON; } int const peak_id = 1; // the ID for the peak of interest brightPeaks->n = i; // only stop at a peak brighter than we are pmFootprint *peakFootprint = pmFindFootprintAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x); brightPeaks->n = 0; // don't double free psImage *idImg = pmSetFootprintID(peakFootprint, peak_id); psFree(peakFootprint); int j;
    2218 2eb9dac3 - for (j = 0; j < i; j++) {
    ? -
    2148 94770baf + for (j = 0; j < i; ++j) {
    ? + pmPeak const *peak2 = fp->peaks->data[j]; int x2 = peak2->x - subImg->x0; int y2 = peak2->y - subImg->y0; int const peak2_id = idImg->data.S32[y2][x2]; // the ID for some other peak if (peak2_id == peak_id) { // There's a brighter peak within the footprint above ; // threshold; so cull our initial peak (void)psArrayRemoveIndex(fp->peaks, i); i--; // we moved everything down one break; } } if (j == i) {
    2232 2eb9dac3 - j++;
    ? -
    2162 94770baf + ++j;
    ? + } psFree(idImg); } brightPeaks->n = 0; psFree(brightPeaks); psFree((psImage *)subImg); psFree((psImage *)subWt); return PS_ERR_NONE; } /* * Cull an entire psArray of pmFootprints */ psErrorCode pmFootprintArrayCullPeaks(psImage const *img, // the image wherein lives the footprint psImage const *weight, // corresponding variance image psArray *footprints, // array of pmFootprints float const nsigma_delta, // how many sigma above local background a peak // needs to be to survive float const min_threshold) { // minimum permitted coll height
    2256 f8edfe90 - for (int i = 0; i < footprints->n; i++) {
    ? -
    2186 94770baf + for (int i = 0; i < footprints->n; ++i) {
    ? + pmFootprint *fp = footprints->data[i]; if (pmFootprintCullPeaks(img, weight, fp, nsigma_delta, min_threshold) != PS_ERR_NONE) { return psError(PS_ERR_UNKNOWN, false, "Culling pmFootprint %d", fp->id); } } return PS_ERR_NONE; } /************************************************************************************************************/ /* * Extract the peaks in a psArray of pmFootprints, returning a psArray of pmPeaks */ psArray *pmFootprintArrayToPeaks(psArray const *footprints) { assert(footprints != NULL); assert(footprints->n == 0 || pmIsFootprint(footprints->data[0])); int npeak = 0;
    2275 7a6ea5ce - for (int i = 0; i < footprints->n; i++) {
    ? -
    2205 94770baf + for (int i = 0; i < footprints->n; ++i) {
    ? + pmFootprint const *fp = footprints->data[i]; npeak += fp->peaks->n; } psArray *peaks = psArrayAllocEmpty(npeak);
    2282 7a6ea5ce - for (int i = 0; i < footprints->n; i++) {
    ? -
    2212 94770baf + for (int i = 0; i < footprints->n; ++i) {
    ? + pmFootprint const *fp = footprints->data[i];
    2284 7a6ea5ce - for (int j = 0; j < fp->peaks->n; j++) {
    ? -
    2214 94770baf + for (int j = 0; j < fp->peaks->n; ++j) {
    ? + psArrayAdd(peaks, 1, fp->peaks->data[j]); } } return peaks; } #endif /************************************************************************************************************/ // // Explicit instantiations // \cond // // template void Footprint::intersectMask( image::Mask const& mask, image::MaskPixel bitMask); template
    2305 17d1d529 - Footprint::Ptr footprintAndMask(
    ? ^^^^^
    2235 94770baf + PTR(Footprint) footprintAndMask(
    ? ++++ ^
    2306 17d1d529 - Footprint::Ptr const& foot,
    ? ^^^^^
    2236 94770baf + PTR(Footprint) const& foot,
    ? ++++ ^ image::Mask::Ptr const& mask, image::MaskPixel bitMask); template image::MaskPixel setMaskFromFootprintList( image::Mask *mask,
    2313 a8f86353 - CONST_PTR(std::vector) const& footprints,
    ? ^^^^^
    2243 94770baf + CONST_PTR(std::vector) const& footprints,
    ? ++++ ^ image::MaskPixel const bitmask); template image::MaskPixel setMaskFromFootprintList( image::Mask *mask,
    2318 17d1d529 - std::vector const& footprints,
    ? ^^^^^
    2248 94770baf + std::vector const& footprints,
    ? ++++ ^ image::MaskPixel const bitmask); template image::MaskPixel setMaskFromFootprint( image::Mask *mask, Footprint const& foot, image::MaskPixel const bitmask); template image::MaskPixel clearMaskFromFootprint( image::Mask *mask, Footprint const& foot, image::MaskPixel const bitmask);
    2327 f0e831df - #define INSTANTIATE_FLOAT(TYPE) \
    ? ^^^^^
    2257 94770baf + #define INSTANTIATE_NUMERIC(TYPE) \
    ? ^^^^^^^ template \ TYPE setImageFromFootprint(image::Image *image, \ Footprint const& footprint, \ TYPE const value); \ template \ TYPE setImageFromFootprintList(image::Image *image, \
    2334 17d1d529 - std::vector const& footprints, \
    ? ^^^^^
    2264 94770baf + std::vector const& footprints, \
    ? ++++ ^ TYPE const value); \ template \ TYPE setImageFromFootprintList(image::Image *image, \
    2338 a8f86353 - CONST_PTR(std::vector) footprints, \
    ? ^^^^^
    2268 94770baf + CONST_PTR(std::vector) footprints, \
    ? ++++ ^ TYPE const value); \ template \ void copyWithinFootprint(Footprint const&, \ PTR(lsst::afw::image::Image) const, \ PTR(lsst::afw::image::Image)); \ template \ void copyWithinFootprint(Footprint const&, \ PTR(lsst::afw::image::MaskedImage) const, \ PTR(lsst::afw::image::MaskedImage)); \ template \ void Footprint::clipToNonzero(lsst::afw::image::Image const&); \
    2352 f0e831df - INSTANTIATE_FLOAT(float);
    ? ^^^^^
    2282 94770baf + INSTANTIATE_NUMERIC(float);
    ? ^^^^^^^
    2353 f0e831df - INSTANTIATE_FLOAT(double);
    ? ^^^^^
    2283 94770baf + INSTANTIATE_NUMERIC(double);
    ? ^^^^^^^ // There's no reason these shouldn't have setImageFromFootprint(), etc, instantiated
    2355 9337578a - INSTANTIATE_FLOAT(boost::uint16_t);
    ? ^^^^^
    2285 94770baf + INSTANTIATE_NUMERIC(boost::uint16_t);
    ? ^^^^^^^
    2356 9337578a - INSTANTIATE_FLOAT(int);
    ? ^^^^^
    2286 94770baf + INSTANTIATE_NUMERIC(int);
    ? ^^^^^^^
    2357 9337578a - INSTANTIATE_FLOAT(boost::uint64_t);
    ? ^^^^^
    2287 94770baf + INSTANTIATE_NUMERIC(boost::uint64_t);
    ? ^^^^^^^ #define INSTANTIATE_MASK(PIXEL) \ template \ void Footprint::insertIntoImage( \ lsst::afw::image::Image& idImage, \ boost::uint64_t const id, \ geom::Box2I const& region=geom::Box2I() \ ) const; \ template \ void Footprint::insertIntoImage( \ lsst::afw::image::Image& idImage, \ boost::uint64_t const id, \ bool const overwriteId, long const idMask, \ std::set *oldIds, \ geom::Box2I const& region=geom::Box2I() \ ) const; \ INSTANTIATE_MASK(boost::uint16_t); INSTANTIATE_MASK(int); INSTANTIATE_MASK(boost::uint64_t); }}} // \endcond
    2313 94770baf +
    2314 94770baf + // LocalWords: SpanList

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    90219c90

    commit 90219c902f2d7e3c89b3b4964d379ff3b65f65c9
    Author: rhl 
    Date:   Mon Dec 1 14:37:03 2008 +0000
    
        Allow us to offset Spans #505; Fix some problems with subimages #507; Fix bug in setting Footprint's BBox
    

    95043065

    commit 95043065b5f06e090c1bbfaa4d2b76faf17f9ffc
    Author: Bob Armstrong 
    Date:   Tue Dec 23 13:09:17 2014 -0500
    
        Footprint: fix bug that did not copy peaks in transform
    

    76f3706f

    commit 76f3706f6688b23d5b0c71e66af3e94095a9f821
    Author: Paul Price 
    Date:   Wed Sep 17 12:30:21 2014 -0400
    
        copyWithinFootprint: respect image size
        
        copyWithinFootprint could produce a segfault (or at least corrupt
        memory) when copying a Footprint that is larger than either of the
        images.  Changed so that pixels outside either image are ignored
        (i.e., it copies every pixel it is able to).  Added test of this
        behaviour and documented the function's behaviour.
    

    f0e831df

    commit f0e831df133cdf9a2fc2f9d6ea1cbb6094ceebd5
    Author: price 
    Date:   Mon Nov 7 19:13:59 2011 +0000
    
        Changing footprint id type required adding support for uint64_t throughout afw.
    

    102a5edd

    commit 102a5eddfb6779ab597b1d94e115822822830a50
    Author: Robert Lupton the Good 
    Date:   Mon Jan 21 14:56:52 2013 -0500
    
        Implement Footprint.get{Centroid,Shape}; #2578
    

    bd5612b0

    commit bd5612b043d3db8afcdbe048d6ea86377662b3a2
    Author: Paul Price 
    Date:   Wed Sep 17 12:36:40 2014 -0400
    
        copyWithinFootprint: add consts in implementation
    

    9337578a

    commit 9337578a740b1b809c3e65eb8e52fa91254cfffd
    Author: Dustin Lang 
    Date:   Fri Apr 11 13:54:58 2014 -0400
    
        add nearesteFootprint() function; instantiate a broader range of Footprint functions for int images
    

    22fe6abd

    commit 22fe6abd8d3cf5e17078c690817c757e4347508d
    Author: Robert Lupton the Good 
    Date:   Fri Jun 1 13:41:08 2012 -0500
    
        Add dummy implementation for L/R/U/D grows
    

    7a6ea5ce

    commit 7a6ea5ce178494cb61090089847aacd809082e36
    Author: bick 
    Date:   Wed Jan 6 20:50:58 2010 +0000
    
        #1113 sundry style corrections on afw.
    

    097386fc

    commit 097386fc2cd385521370ffa031a621074dd4a6b9
    Author: Dustin Lang 
    Date:   Mon Mar 10 15:36:24 2014 -0400
    
        add Footprint.addSpanInSeries(), and Footprint.clipToNonzero()
    

    2eb9dac3

    commit 2eb9dac33eec6f13a73c03cc2827aa9884ff06cc
    Author: rowen 
    Date:   Mon Sep 28 22:55:55 2009 +0000
    
        Removed all tabs.
    

    8a634e0b

    commit 8a634e0b92ae0b48bb29bca331ebfe4d8288ae0e
    Author: rhl 
    Date:   Thu Oct 6 20:26:24 2011 +0000
    
        Updated version of Paul's disabling of the Footprint/Peak merge code that can crash afw; no failed tests
    

    c902c475

    commit c902c47592d44ba8aeeb3d329e340f1f32c0e5d9
    Author: rhl 
    Date:   Wed Mar 25 12:46:19 2009 +0000
    
        Added setImageFromFootprint(List)?; #0
    

    2a10294e

    commit 2a10294e8c36d905159c58f92de4b1e1a340265c
    Author: rhl 
    Date:   Fri Nov 28 20:53:18 2008 +0000
    
        Merged revisions 6505,6507-6508,6575-6577 via svnmerge (#490) from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/490
        N.b. svnmerge.py merge failed to complete after generating this
        file.  It appears to be OK.
    

    6ac35e07

    commit 6ac35e07a70a600e59ed290a1b8fb3173bdbf21d
    Author: Jim Bosch 
    Date:   Thu Nov 13 16:22:23 2014 -0500
    
        Replace Peak with PeakRecord
        
        By using afw::table objects to store Peaks, we allow additional
        information to be added to Peaks without requiring further changes
        to persistence.
    

    a716b827

    commit a716b8278e46b783bd31b9781f12a51761041a1e
    Author: rhl 
    Date:   Wed Mar 4 17:58:23 2009 +0000
    
        Add footprintToBBoxList (#681).  As part of writing its test, make Statistics understand unsigned short images, and allow getValue() to return single requested statistic
    

    b635df09

    commit b635df0908f570c1c3c371b687a581da61f0be1f
    Author: dubcovsky 
    Date:   Wed Apr 27 21:32:08 2011 +0000
    
        Added swap functions for Point, Extent, and Box. Added Copy constructors to Peak and Footprint
    

    2e46fcbb

    commit 2e46fcbb85dc1b140e9d4e8789ecd35a7e309d97
    Author: Dustin Lang 
    Date:   Wed Jan 22 13:06:30 2014 -0600
    
        whitespace
    

    99dc4b86

    commit 99dc4b86974566e73f34c9eaa0347969c46831a1
    Author: Dustin Lang 
    Date:   Tue Mar 11 11:13:43 2014 -0400
    
        add test case for Footprint.clipToNonzero and find the bug (was making a copy of spanlist -- ugh!)
    

    79337bb6

    commit 79337bb6d1ee3a0b73bcd2b2d0ca506a44d3fa56
    Author: Robert Lupton the Good 
    Date:   Sat May 9 16:56:34 2015 -0400
    
        Handle empty Footprints when normalising
        
        see discussion in HSC HipChat room, 2:10am, 2015-05-09
    

    2af73d7d

    commit 2af73d7da3b0100e1ab80c68854b5a9cdcfa4f78
    Author: dubcovsky 
    Date:   Wed Apr 13 22:12:08 2011 +0000
    
        #1556 added a footprint constructor to provide the functionality of the removed BCircle
    

    a8f86353

    commit a8f86353b4d794d8e2accd0ce6950e72a06c3f66
    Merge: a128aac 246b6dd
    Author: dubcovsky 
    Date:   Thu Mar 31 20:50:37 2011 +0000
    
        #1556 trunk merged to ticket branch
    

    868f131e

    commit 868f131edf514c22c8eb9172a5bda322f7f27b66
    Author: Robert Lupton the Good 
    Date:   Fri Jun 1 16:14:51 2012 -0500
    
        Implemented left/right grows
    

    35570270

    commit 355702709fadee7ac3db15237924fa3283ec298b
    Author: rhl 
    Date:   Thu Aug 19 21:02:50 2010 +0000
    
        Implement Footprint.contains()
    

    3d19aa2b

    commit 3d19aa2bc09a25310a20ab0313b0d76942d6a99f
    Author: Jim Bosch 
    Date:   Fri Dec 19 15:01:30 2014 -0500
    
        Functions and methods that create Footprints must preserve Peak schemas
        
        Many of the operations that created new Footprints from old ones
        internally used the Footprint default constructor, not the copy
        constructor, and that meant they weren't transferring the new
        peaks properly.
    

    fac13aff

    commit fac13affb6d89067ed58ff03a1ebd394d6306f86
    Author: rowen 
    Date:   Tue Apr 12 21:03:17 2011 +0000
    
        Fix a typo
    

    0d1ab12d

    commit 0d1ab12db604d5e42a5d72f028411a64294283ce
    Author: Jim Bosch 
    Date:   Sun Apr 20 21:44:20 2014 -0400
    
        When merging footprints, support noncontiguous inputs
    

    7ac2306a

    commit 7ac2306a4fc62d868a798aea1ba27830981c46b4
    Author: Dustin Lang 
    Date:   Fri Mar 7 17:10:31 2014 -0500
    
        add checkNormalized(); don't call normalize() and instead set _normalized=true in mergeFootprints().
    

    4dface89

    commit 4dface89496957978717e5a72752ca15609287a6
    Author: Jim Bosch 
    Date:   Thu Apr 16 11:48:49 2015 -0400
    
        Add method to sort Peaks within a Footprint.
        
        Peaks should almost always be sorted from most positive to most negative.
        While Footprint doesn't enforce that condition, we need to make it easier
        for external code to do so.
    

    5cdd6a3d

    commit 5cdd6a3d782a7a8c37764d4494e3408312cdcb3a
    Author: dubcovsky 
    Date:   Fri Apr 29 23:26:39 2011 +0000
    
        #1659 correcting the behavor of footprintAndMask. closing ticket
    

    ddb75eb2

    commit ddb75eb2dc0ce9b2871dc265597db934b75531e5
    Author: Bob Armstrong 
    Date:   Fri May 1 14:03:26 2015 -0400
    
        Footprint: modify include method to ignore itself.
        
        This modification allows you to modify a footprint in-place to be the union
        of a list of footprints that are not necessarily contiguous.
    

    f9d4c054

    commit f9d4c0544640f89e818122e41c8d262c8369d540
    Author: rhl 
    Date:   Mon Feb 28 10:56:53 2011 +0000
    
        getFootprints was returning a potentially dangling reference... (blame a younger RHL).  Swig doesn't like mixing shared pointers to const with shared pointers to Foo
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    f78ceebc

    commit f78ceebc17e24ab89963dd248cd073c8390645d5
    Author: Steven Bickerton 
    Date:   Mon Oct 27 13:15:47 2014 +0900
    
        Check valid shared_ptr before dereferencing
    

    e880cec9

    commit e880cec9eb7431ac8d1ecf5d8a2e581ddc0fc39f
    Author: Dustin Lang 
    Date:   Fri Mar 7 15:52:33 2014 -0500
    
        merge connected spans; also require normalized footprints
    

    5ba4f880

    commit 5ba4f880058b4c6103dc292fa248cd4ab6dc6558
    Author: rhl 
    Date:   Sat Oct 22 22:03:52 2011 +0000
    
        Reverted r24389 (Paul) and r24632 (Steve).  Fixed #1783, although the implementation is poor [sorting twice to get unique Peak lists as Footprints can overlap more than one other Footprint) I want to get it in before more sturm and drang
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    d588836a

    commit d588836aaf6563afe2e8bf452cfc72532a9ce268
    Author: John Swinbank 
    Date:   Fri Nov 28 17:31:26 2014 -0600
    
        RLE-based Footprint erosion
    

    4b1be60a

    commit 4b1be60a1d27c771b92829b02a37d9db164482f8
    Author: rhl 
    Date:   Sun Mar 1 16:00:32 2009 +0000
    
        Implement DetectionSet copy constructor that grows the Footprints; adjust growFootprint signature to make this possible; #0
    

    2410dfe5

    commit 2410dfe554fa914054f2be0bb974009ff6e804d2
    Author: rhl 
    Date:   Sat Oct 8 18:53:15 2011 +0000
    
        Fixed peak-merging within Footprints.  Peaks within Footprints that are entirely subsumed by other Footprints are lost, but the hooks to fix this are in
    

    a64e361f

    commit a64e361f0310e27a7afbf6dbd99ca88d8ac19e84
    Author: Jim Bosch 
    Date:   Fri Dec 19 15:00:08 2014 -0500
    
        Make it easier to control Peak schemas in Footprint
        
        For backwards compatibility, we're keeping around
        all the old Footprint constructors, which use the
        default Peak minimal schema.  But we now have a
        ctor that accepts a custom schema, and a Python
        accessible way to change the schema.
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    d9ace53f

    commit d9ace53f1da7e47ed729d80ad0ec6e710e19118d
    Author: Dustin Lang 
    Date:   Tue Mar 11 11:37:39 2014 -0400
    
        make mergeFootprints non-member functions
    

    d2f33c47

    commit d2f33c477729042d4ab5f7dcacbd24158f754973
    Author: Dustin Lang 
    Date:   Fri Apr 27 11:23:27 2012 -0500
    
        add clearMaskFromFootprint, paralleling setMaskFromFootprint.
    

    9a8e8725

    commit 9a8e8725023274b895fecd1e9375a4e718da63ad
    Author: rhl 
    Date:   Fri Jan 16 02:43:37 2009 +0000
    
        Modify setMaskFromFootprint (keeping old version but deprecating it); #0
    

    5d1934cc

    commit 5d1934cc9fe7d8c43aa8f9318a1ac9a3ce85e94e
    Author: Jim Bosch 
    Date:   Wed Apr 16 17:20:02 2014 -0400
    
        Add Footprint method to merge with neighbors
    

    17d1d529

    commit 17d1d529ed63e98f98e5d1a7a7da4811e95fc26c
    Author: dubcovsky 
    Date:   Tue Feb 15 00:00:43 2011 +0000
    
        #1556 Split Footprint.h into Threshold.h, FootprintSet.h, and FootprintFunctor.h, to correspond with class names. Added a constructors to Footprint which use geom objects (BoxI and Ellipse) to construct footprints. Footprints now exclusively use geom::PointI and geom::BoxI internally. (but still accept image::PointI and image::BBox for backwards compatibility wherever possible). FootprintArray.h contains a static functions to flatten and expand ndarrays using a Footprint to map between 2-d and 1-d indices.
    

    6201600d

    commit 6201600ddb8237a23549502e14c56c4022ebb2d9
    Author: Paul Price 
    Date:   Thu Sep 25 14:46:26 2014 -0400
    
        copyWithinFootprint: more complete fix for respect image size
        
        Had fixed the iteration range previously, but not the iterators, so that
        it was still possible for the iterators to start off the image.  Made
        things more consistent and clearer with more temporary variables.
    

    8687de82

    commit 8687de8284c66b68b1f180fc6aebffd02d7cfad6
    Author: Robert Lupton the Good 
    Date:   Fri Jun 1 20:57:48 2012 -0400
    
        Implemented up/down grows
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    5b637e27

    commit 5b637e2745f46bf04e106bfeffc807b4b8716ec4
    Author: rhl 
    Date:   Fri Feb 27 02:59:00 2009 +0000
    
        Add option to growFootprint to speed up operation by using a Manhattan metric to define the distance to grow; #0
    

    61b6195c

    commit 61b6195c87e9320e84ffff47c38353a6d945d173
    Author: Robert Lupton the Good 
    Date:   Sat May 9 16:53:20 2015 -0400
    
        Overwrote master with files checked out from HSC-1246
    

    Commits in /Users/nate/repos_lsst/afw/

    1d5e7de8

    commit 1d5e7de822d6bd618f9ec7f8ec87a5571830c3e0
    Author: Lauren MacArthur 
    Date:   Thu Apr 2 17:11:17 2015 -0400
    
        Change variable names for consistency
    

    89e96d0e

    commit 89e96d0e1b2e80141039a3d51b153af8d5fc7f22
    Author: John Swinbank 
    Date:   Fri Nov 28 17:31:26 2014 -0600
    
        RLE-based Footprint erosion
    

    fd3397a2

    commit fd3397a2d970652feb1f352abde5af316506f50b
    Author: John Swinbank 
    Date:   Fri Nov 28 17:30:48 2014 -0600
    
        Better semantics for Span trailing edge
        
        Assuming that the structuring element is centred at the origin, then its range
        in X is from -x0 to x1. This makes semantically more sense than
        representing it as x0 to x1 and remembering to put in a - when required.
    

    b0e170fa

    commit b0e170fa68c056a82b75b8076652e5caed4c9b9c
    Author: John Swinbank 
    Date:   Wed Nov 19 13:52:26 2014 -0600
    
        Use RLE for Manhattan Footprint dilation
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    7cc5e55a

    commit 7cc5e55a8ec76e927c9e7feb767bc65d712a28ab
    Author: John Swinbank 
    Date:   Wed Nov 19 13:11:43 2014 -0600
    
        Grow Footprints isotropically using RLE operations
        
        This gives a roughly order of magnitude performance improvement over the
        convolution with a circle used previously.
    

    d19772f0

    commit d19772f08869b4990e56eed3825d4550a1830b98
    Author: Lauren MacArthur 
    Date:   Wed Mar 4 18:25:31 2015 -0500
    
        Update Exception in Footprint and tests/footprint1.py to new name
    

    dddc9b36

    commit dddc9b36d166bc85774ff34c38c134fcf6206508
    Author: John Swinbank 
    Date:   Thu Nov 20 15:43:44 2014 -0600
    
        Use a class for the structuring element in Footprint grows.
        
        This replaces the previous definition, based on std::map, and makes it
        possible to have asymmetric structuring elements. We can therefore use the
        RLE-based technique to grow in any (or all) of the up/down/left/right
        directions.
    

    58d8c34f

    commit 58d8c34fec4fd4e9616d3be8d3eec04bc5f53acd
    Author: Paul Price 
    Date:   Mon May 20 14:27:20 2013 -0400
    
        Footprint: optimize Footprint::transform (#2884)
        
        There was a general lack of use of 'const' and 'const&' which may impact
        the speed.
    

    ae20e2b5

    commit ae20e2b580e6d2a9e785dc0d4f471b7ebed2fb45
    Author: John Swinbank 
    Date:   Fri Nov 28 17:10:45 2014 -0600
    
        Support shrinks with a Manhattan metric
    

    ca6bfc5f

    commit ca6bfc5f93a0fa247ac9dad1a5997f3dc97e6edb
    Author: John Swinbank 
    Date:   Mon May 11 21:26:56 2015 -0400
    
        Fix performance regression in Footprint dilation.
        
        The earlier RLE-based Footprint dilation routine relied on
        Footprint::normalize() to weed out duplicate and overlapping Spans. Although
        good performance was obtained for small Footprints and structuring elements,
        this could result in a significant performance regression when a large number
        of Spans were created during dilation.
        
        Here, the algorithm is adjusted so that the list of (proto-)Spans is
        maintained in a normalized state as the Footprint is grown, thereby avoiding
        the bottleneck.
    

    f0799ebb

    commit f0799ebbbf327d21565f9746ab3ac358b0124426
    Author: Jim Bosch 
    Date:   Fri Dec 19 15:01:30 2014 -0500
    
        Functions and methods that create Footprints must preserve Peak schemas
        
        Many of the operations that created new Footprints from old ones
        internally used the Footprint default constructor, not the copy
        constructor, and that meant they weren't transferring the new
        peaks properly.
        
        Conflicts:
            src/detection/Footprint.cc
        
        Note that recent improvements on the Footprint grow and shrink
        algorithms require a separate commit to ensure the peaks are
        being transferred and updated properly.
    

    5539a924

    commit 5539a92479bcb4cb81be6be6b2f6b5bc503f0cd7
    Merge: 6d5596b 1873501
    Author: price 
    Date:   Mon Nov 7 19:57:26 2011 +0000
    
        Merging trunk to get #1804 (footprints need too many bits)
    

    5cdd6a3d

    commit 5cdd6a3d782a7a8c37764d4494e3408312cdcb3a
    Author: dubcovsky 
    Date:   Fri Apr 29 23:26:39 2011 +0000
    
        #1659 correcting the behavor of footprintAndMask. closing ticket
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    0b2457bc

    commit 0b2457bc72484e8cfb78f471f6d6d7e7fc1f6437
    Author: Jim Bosch 
    Date:   Wed Apr 16 17:20:02 2014 -0400
    
        Add Footprint method to merge with neighbors
        
        Conflicts:
            tests/footprint1.py
    

    36cfb16b

    commit 36cfb16be779ed99d60e5b287db72b6821d470d4
    Author: Dustin Lang 
    Date:   Wed Jan 15 16:11:28 2014 -0600
    
        add some Footprint functions used in meas_deblender: copyWithinFootprint, and mergeHeavyFootprints, including tests
    

    ecb01ab8

    commit ecb01ab81744139491981fb406fcc634181cbf5b
    Author: Lauren MacArthur 
    Date:   Thu Apr 23 16:58:48 2015 -0400
    
        Copy Peaks into grown and shrunken Footprints
        
        Peaks from the original Footprint need to be copied into the new
        Footprints returned by the growFootprint and shrinkFootprint
        functions.  For the latter, only those Peaks lying within the
        shrunken Footprint get added.
        
        The unittest code was updated to test these changes.
    

    4b1be60a

    commit 4b1be60a1d27c771b92829b02a37d9db164482f8
    Author: rhl 
    Date:   Sun Mar 1 16:00:32 2009 +0000
    
        Implement DetectionSet copy constructor that grows the Footprints; adjust growFootprint signature to make this possible; #0
    

    868f131e

    commit 868f131edf514c22c8eb9172a5bda322f7f27b66
    Author: Robert Lupton the Good 
    Date:   Fri Jun 1 16:14:51 2012 -0500
    
        Implemented left/right grows
    

    c12d3b48

    commit c12d3b4824bcbb203135218e908325e47e99698f
    Author: Jim Bosch 
    Date:   Fri Dec 19 15:00:08 2014 -0500
    
        Make it easier to control Peak schemas in Footprint
        
        For backwards compatibility, we're keeping around
        all the old Footprint constructors, which use the
        default Peak minimal schema.  But we now have a
        ctor that accepts a custom schema, and a Python
        accessible way to change the schema.
        
        Conflicts:
            include/lsst/afw/detection/Footprint.h
            src/detection/Footprint.cc
    

    a4c91494

    commit a4c914944a3dd543ae2be2d112fca76e66dce807
    Merge: 94770ba ae3ebc3
    Author: Russell Owen 
    Date:   Thu Jun 26 10:13:53 2014 -0700
    
        Merge branch 'tickets/DM-764'
        
        Conflicts:
            src/detection/Footprint.cc
    

    007ca4a2

    commit 007ca4a24b6bb73d9d63d427ae579cc433dc616a
    Author: Jim Bosch 
    Date:   Thu Nov 13 16:22:23 2014 -0500
    
        Replace Peak with PeakRecord
        
        By using afw::table objects to store Peaks, we allow additional
        information to be added to Peaks without requiring further changes
        to persistence.
        
        Conflicts:
            include/lsst/afw/detection/Footprint.h
            include/lsst/afw/detection/FootprintSet.h
            src/detection/Footprint.cc
            src/detection/FootprintSet.cc
            tests/footprint1.py
    

    c839d0f2

    commit c839d0f28287875df3e43b674f1da3f140a33250
    Author: Lauren MacArthur 
    Date:   Mon Mar 16 16:34:35 2015 -0400
    
        Update copyright and remove whitespace
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    2eb9dac3

    commit 2eb9dac33eec6f13a73c03cc2827aa9884ff06cc
    Author: rowen 
    Date:   Mon Sep 28 22:55:55 2009 +0000
    
        Removed all tabs.
    

    2e46fcbb

    commit 2e46fcbb85dc1b140e9d4e8789ecd35a7e309d97
    Author: Dustin Lang 
    Date:   Wed Jan 22 13:06:30 2014 -0600
    
        whitespace
    

    94770baf

    commit 94770bafec04976204f56cf3aed80fa02bece412
    Author: Dustin Lang 
    Date:   Mon Jun 23 17:17:08 2014 -0500
    
        Address various issues from Paul Price's in-depth review.
        
        Footprint.h:
            No documentation for new methods and functions.
        
        Footprint.cc:
            Move documentation to header file.
            Indentation is inconsistent. Should always be 4.
            Don't use this-> when there is no need for it, e.g., this->addSpan should be addSpan.
            Paren following LSST_EXCEPT *must* cuddle --- it certainly may not be on the next line.
            Breaks 110 column limit.
            PixelT zero = 0; should be PixelT const zero = 0; Add const also for ix0 and iy0 --- *anywhere* the value will never change, as it helps the compiler write faster code.
            You're iterating with the postfix operator (s++) instead of prefix (++s); this can adversely affect performance in C++.
            What does the comment Ugly! refer to?
            Names foota and footb don't follow naming rules, and are a bit hard to read. Suggest aFoot and bFoot. Similarly with pka, etc.
            const Footprint::PeakList& --> Footprint::PeakList const& (throughout).
            while (1) --> while (true)
            nearestFootprint isn't documented.
            Why do you call INSTANTIATE_FLOAT on integer types???  [I renamed it -- it instantiated functions that were appropriate for *numeric*, not necessarily floating-point, types!]
            remove gratuitous 'typename'
            prefer PTR(Foo) to Foo::Ptr and CONST_PTR(Foo) to Foo:ConstPtr.
        
        HeavyFootprint?.cc:
            Some lines exceed 110 columns.
            Commented out code should be removed
        
        footprint1.py:
            Instead of self.assertTrue(a > b) use self.assertGreater(a, b). This provides a more useful message when it fails.
            Why is the trailing F required on clipToNonzeroF? It should be able to tell from the type of the image.  [fixed]
        
        Also removed stray Footprint.mergeWith() function that got messed up during rebase
    

    5b637e27

    commit 5b637e2745f46bf04e106bfeffc807b4b8716ec4
    Author: rhl 
    Date:   Fri Feb 27 02:59:00 2009 +0000
    
        Add option to growFootprint to speed up operation by using a Manhattan metric to define the distance to grow; #0
    

    Return to list

    include/lsst/afw/geom/ellipses/radii.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    #ifndef LSST_AFW_GEOM_ELLIPSES_radii_h_INCLUDED
                    #define LSST_AFW_GEOM_ELLIPSES_radii_h_INCLUDED
                    
                    /**
                     *  \file
                     *  @brief Helper classes defining radii for Separable core.
                     *
                     *  \note Do not include directly; use the main ellipse header file.
                     */
                    
                    #include "lsst/afw/geom/ellipses/BaseCore.h"
                    #include "lsst/afw/geom/ellipses/Distortion.h"
                    #include 
                    
                    namespace lsst { namespace afw { namespace geom {
                    namespace ellipses {
                    
                    #ifndef SWIG
                    template  class Separable;
                    #endif
                    
                    class DeterminantRadius;
                    class TraceRadius;
                    class LogDeterminantRadius;
                    class LogTraceRadius;
                    
                    /**
                     * \brief The radius defined as the 4th root of the determinant of the quadrupole matrix.
                     *
                     * The determinant radius is equal to the standard radius for a circle, and
                     * \f$\pi R_{det}^2\f$ is the area of the ellipse.
                     */
                    class DeterminantRadius {
                    public:
                    
                        void normalize() {
                            if (_value < 0)
    
    62 ce01a540 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    62 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Ellipse radius cannot be negative."); } static std::string getName() { return "DeterminantRadius"; } explicit DeterminantRadius(double value=1.0) : _value(value) {} explicit DeterminantRadius(LogDeterminantRadius const & other); operator double const & () const { return _value; } operator double & () { return _value; } DeterminantRadius & operator=(double value) { _value = value; return *this; } DeterminantRadius & operator=(LogDeterminantRadius const & other); private: template friend class Separable; /// Undefined and disabled; conversion between trace and determinant radii requires ellipticity. void operator=(TraceRadius const &); /// Undefined and disabled; conversion between trace and determinant radii requires ellipticity. void operator=(LogTraceRadius const &); void assignFromQuadrupole( double ixx, double iyy, double ixy, Distortion & distortion ); BaseCore::Jacobian dAssignFromQuadrupole( double ixx, double iyy, double ixy, Distortion & distortion ); void assignToQuadrupole( Distortion const & distortion, double & ixx, double & iyy, double & ixy ) const; BaseCore::Jacobian dAssignToQuadrupole( Distortion const & distortion, double & ixx, double & iyy, double & ixy ) const; double _value; }; /** * \brief The radius defined as \f$\sqrt{0.5(I_{xx} + I_{yy})}\f$ * * The trace radius is equal to the standard radius for a circle */ class TraceRadius { public: void normalize() { if (_value < 0)
    122 ce01a540 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    122 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Ellipse radius cannot be negative."); } static std::string getName() { return "TraceRadius"; } explicit TraceRadius(double value=1.0) : _value(value) {} explicit TraceRadius(LogTraceRadius const & other); operator double const & () const { return _value; } operator double & () { return _value; } TraceRadius & operator=(double value) { _value = value; return *this; } TraceRadius & operator=(LogTraceRadius const & other); private: template friend class Separable; /// Undefined and disabled; conversion between trace and determinant radii requires ellipticity. void operator=(DeterminantRadius const &); /// Undefined and disabled; conversion between trace and determinant radii requires ellipticity. void operator=(LogDeterminantRadius const &); void assignFromQuadrupole( double ixx, double iyy, double ixy, Distortion & distortion ); BaseCore::Jacobian dAssignFromQuadrupole( double ixx, double iyy, double ixy, Distortion & distortion ); void assignToQuadrupole( Distortion const & distortion, double & ixx, double & iyy, double & ixy ) const; BaseCore::Jacobian dAssignToQuadrupole( Distortion const & distortion, double & ixx, double & iyy, double & ixy ) const; double _value; }; /** * \brief The natural logarithm of the DeterminantRadius */ class LogDeterminantRadius { public: void normalize() {} static std::string getName() { return "LogDeterminantRadius"; } explicit LogDeterminantRadius(double value=0.0) : _value(value) {} explicit LogDeterminantRadius(DeterminantRadius const & other); operator double const & () const { return _value; } operator double & () { return _value; } LogDeterminantRadius & operator=(double value) { _value = value; return *this; } LogDeterminantRadius & operator=(DeterminantRadius const & other); private: template friend class Separable; /// Undefined and disabled; conversion between trace and determinant radii requires ellipticity. void operator=(TraceRadius const &); /// Undefined and disabled; conversion between trace and determinant radii requires ellipticity. void operator=(LogTraceRadius const &); void assignFromQuadrupole( double ixx, double iyy, double ixy, Distortion & distortion ); BaseCore::Jacobian dAssignFromQuadrupole( double ixx, double iyy, double ixy, Distortion & distortion ); void assignToQuadrupole( Distortion const & distortion, double & ixx, double & iyy, double & ixy ) const; BaseCore::Jacobian dAssignToQuadrupole( Distortion const & distortion, double & ixx, double & iyy, double & ixy ) const; double _value; }; /** * \brief The natural logarithm of the TraceRadius */ class LogTraceRadius { public: void normalize() {} static std::string getName() { return "LogTraceRadius"; } explicit LogTraceRadius(double value=0.0) : _value(value) {} explicit LogTraceRadius(TraceRadius const & other); operator double const & () const { return _value; } operator double & () { return _value; } LogTraceRadius & operator=(double value) { _value = value; return *this; } LogTraceRadius & operator=(TraceRadius const & value); private: template friend class Separable; /// Undefined and disabled; conversion between trace and determinant radii requires ellipticity. void operator=(DeterminantRadius const &); /// Undefined and disabled; conversion between trace and determinant radii requires ellipticity. void operator=(LogDeterminantRadius const &); void assignFromQuadrupole( double ixx, double iyy, double ixy, Distortion & distortion ); BaseCore::Jacobian dAssignFromQuadrupole( double ixx, double iyy, double ixy, Distortion & distortion ); void assignToQuadrupole( Distortion const & distortion, double & ixx, double & iyy, double & ixy ) const; BaseCore::Jacobian dAssignToQuadrupole( Distortion const & distortion, double & ixx, double & iyy, double & ixy ) const; double _value; }; inline DeterminantRadius::DeterminantRadius(LogDeterminantRadius const & other) : _value(std::exp(other)) {} inline TraceRadius::TraceRadius(LogTraceRadius const & other) : _value(std::exp(other)) {} inline LogDeterminantRadius::LogDeterminantRadius(DeterminantRadius const & other) : _value(std::log(other)) {} inline LogTraceRadius::LogTraceRadius(TraceRadius const & other) : _value(std::log(other)) {} inline DeterminantRadius & DeterminantRadius::operator=(LogDeterminantRadius const & other) { _value = std::exp(other); return *this; } inline TraceRadius & TraceRadius::operator=(LogTraceRadius const & other) { _value = std::exp(other); return *this; } inline LogDeterminantRadius & LogDeterminantRadius::operator=(DeterminantRadius const & other) { _value = std::log(other); return *this; } inline LogTraceRadius & LogTraceRadius::operator=(TraceRadius const & other) { _value = std::log(other); return *this; } }}}} // namespace lsst::afw::geom::ellipses #endif // !LSST_AFW_GEOM_ELLIPSES_radii_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ce01a540

    commit ce01a5406f327071e1701d534e563f0e75b870c4
    Author: jbosch 
    Date:   Wed Feb 2 01:27:08 2011 +0000
    
        afw #1556 - ellipses updated (#1551), but swig wrappers for ellipses now broken
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/geom/AffineTransform.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    %{
                    #include "lsst/afw/geom/AffineTransform.h"
                    %}
                    
                    %declareNumPyConverters(lsst::afw::geom::AffineTransform::ParameterVector);
                    %declareNumPyConverters(lsst::afw::geom::AffineTransform::Matrix);
                    
                    %shared_ptr(lsst::afw::geom::AffineTransform);
                    
                    %rename(__mul__) lsst::afw::geom::AffineTransform::operator*;
                    %ignore lsst::afw::geom::AffineTransform::operator[];
                    %ignore lsst::afw::geom::AffineTransform::dTransform;
                    %ignore lsst::afw::geom::AffineTransform::operator=;
                    
                    %copyctor lsst::afw::geom::AffineTransform;
                    %newobject lsst::afw::geom::AffineTransform::makeRotation;
                    %newobject lsst::afw::geom::AffineTransform::makeScaling;
                    %newobject lsst::afw::geom::AffineTransform::makeTranslation;
                    %newobject lsst::afw::geom::AffineTransform::invert;
                    
                    %include "lsst/afw/geom/Angle.i"
                    %include "lsst/afw/geom/AffineTransform.h"
                    
                    %extend lsst::afw::geom::AffineTransform {    
                        void set(double xx, double yx, double xy, double yy, double x, double y) {
                            (*self)[lsst::afw::geom::AffineTransform::XX] = xx;
                            (*self)[lsst::afw::geom::AffineTransform::XY] = xy;
                            (*self)[lsst::afw::geom::AffineTransform::X] = x;
                            (*self)[lsst::afw::geom::AffineTransform::YX] = yx; 
                            (*self)[lsst::afw::geom::AffineTransform::YY] = yy;
                            (*self)[lsst::afw::geom::AffineTransform::Y] = y;
                        }
                        
                        %feature("shadow") _setitem_nochecking %{
                            def __setitem__(self, k, v):
                                if k < 0 or k > 5: raise IndexError
                                $action(self, k, v)
                        %}
                        void _setitem_nochecking(int i, double value) {
                            self->operator[](i) = value;
                        }
                        
                        %feature("shadow") _getitem_nochecking %{
                            def __getitem__(self, k):
                                try:
                                    i,j = k
                                    if i < 0 or i > 2: raise IndexError
                                    if j < 0 or j > 2: raise IndexError
                                    return $action(self, i,j)
                                except TypeError:
                                    if k < 0 or k > 5: raise IndexError
                                    return $action(self, k)
                    
                        %}
                        double _getitem_nochecking(int row, int col) {
                            return (self->getMatrix())(row, col);
                        }
                        double _getitem_nochecking(int i) {
                            return self->operator[](i);
                        }   
                             
    
    85 ae06b2a8 - %pythoncode {
    85 81c3bd10 + %pythoncode %{
    ? + def __str__(self): return str(self.getMatrix()) def __reduce__(self): return (AffineTransform, (self.getMatrix(),)) def __repr__(self): return "AffineTransform(\n%r\n)" % (self.getMatrix(),)
    92 ae06b2a8 - }
    92 81c3bd10 + %}
    ? + }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ae06b2a8

    commit ae06b2a82f540d4475ab1df257cd211bc5b670c9
    Author: dubcovsky 
    Date:   Sat Oct 24 00:38:07 2009 +0000
    
        #892 swig wrappers for ellipse classes
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    include/lsst/afw/math.h

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief An include file to include the public header files for lsst::afw::math
                     *
                     * Note: this header file intentionally excludes math/detail header files because they define
                     * classes and functions which are not part of the public API.
                     */
                    #ifndef LSST_AFW_MATH_H
                    #define LSST_AFW_MATH_H
                    
                    #include "lsst/afw/math/GaussianProcess.h"
                    #include "lsst/afw/math/Background.h"
                    #include "lsst/afw/math/Function.h"
                    #include "lsst/afw/math/FunctionLibrary.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/KernelFunctions.h"
                    #include "lsst/afw/math/minimize.h"
                    #include "lsst/afw/math/warpExposure.h"
                    #include "lsst/afw/math/SpatialCell.h"
                    #include "lsst/afw/math/offsetImage.h"
                    #include "lsst/afw/math/MaskedVector.h"
                    #include "lsst/afw/math/Statistics.h"
                    #include "lsst/afw/math/Integrate.h"
                    #include "lsst/afw/math/Interpolate.h"
                    #include "lsst/afw/math/Random.h"
                    #include "lsst/afw/math/LeastSquares.h"
    
    49 561d9af1 - #include "lsst/afw/math/BoundedField.h"
    50 3f99dca1 - #include "lsst/afw/math/ChebyshevBoundedField.h"
    #endif // LSST_AFW_MATH_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3f99dca1

    commit 3f99dca17c50d3a38e5c5b0a487a347521286dd4
    Author: Jim Bosch 
    Date:   Fri May 23 18:50:20 2014 -0400
    
        Added 2-d Chebyshev class with new API
    

    561d9af1

    commit 561d9af1a98006c5026631538c2a0b3ff9b00844
    Author: Jim Bosch 
    Date:   Fri May 23 14:26:48 2014 -0400
    
        New base class for image-associated 2-d functions.
    

    Commits in /Users/nate/repos_lsst/afw/

    Return to list

    include/lsst/afw/image.h

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief An include file to include the header files for lsst::afw::image
                     */
                    #ifndef LSST_IMAGE_H
                    #define LSST_IMAGE_H
                    
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/image/LsstImageTypes.h"
                    #include "lsst/afw/image/Calib.h"
    
    33 d0950ae6 - #include "lsst/afw/image/ApCorrMap.h"
    #include "lsst/afw/image/Filter.h" #include "lsst/afw/image/Wcs.h" #include "lsst/afw/cameraGeom/Detector.h" #include "lsst/afw/image/TanWcs.h"
    37 a0b9d98c + #include "lsst/afw/image/DistortedTanWcs.h"
    #include "lsst/afw/image/Exposure.h" // Exposure.h brings in almost everything #include "lsst/afw/image/ImageAlgorithm.h" #include "lsst/afw/image/ImagePca.h" #include "lsst/afw/image/ImageUtils.h" #include "lsst/afw/image/ImageSlice.h" #include "lsst/afw/fits.h" // stuff here is forward-declared in headers in afw::image, but // since we need it in SWIG (and that's the only place anyone // should really be including image.h) we include it here. #endif // LSST_IMAGE_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d0950ae6

    commit d0950ae605e9f616b9ce46becebe81807151ed03
    Author: Jim Bosch 
    Date:   Mon Jun 2 15:51:03 2014 -0400
    
        Python wrappers, unit tests for ApCorrMap
    

    Commits in /Users/nate/repos_lsst/afw/

    a0b9d98c

    commit a0b9d98c33134ce69b177a9b6b6260de9f2bccfd
    Author: Russell Owen 
    Date:   Thu Jan 22 17:41:16 2015 -0800
    
        Added DistortedTanWcs and a unit test.
        
        fixup! Added DistortedTanWcs and a preliminary unit test.
        
        Fixed some incorrect names in DistortedTanWcs and improved argument names accordingly.
        
        Ignore _build files
    

    Return to list

    src/math/Approximate.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @brief Approximate values for a set of x,y vector<>s
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    #include 
                    #include "Eigen/Core"
                    #include "Eigen/LU"
                    #include "boost/format.hpp"
                    #include "boost/shared_ptr.hpp"
                    #include "lsst/utils/ieee.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/FunctionLibrary.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/Approximate.h"
                    
                    namespace lsst {
                    namespace ex = pex::exceptions;
                    namespace afw {
                    namespace math {
                    
                    /// \brief ctor
                    ApproximateControl::ApproximateControl(Style style, ///< Type of approximation
                                                           int orderX,  ///< Order of approximation to use in x-direction
    
    50 8a46673b - int orderY ///< Order of approximation to use in y-direction
    ? ^
    50 83a9a5f5 + int orderY, ///< Order of approximation to use in y-direction
    ? ^
    51 83a9a5f5 + bool weighting ///< Use inverse variance weighting?
    ) :
    52 22807ea1 - _style(style), _orderX(orderX), _orderY(orderY < 0 ? orderX : orderY) {
    53 83a9a5f5 + _style(style), _orderX(orderX), _orderY(orderY < 0 ? orderX : orderY), _weighting(weighting) {
    ? +++++++++++++++++++++++ if (_orderX != _orderY) {
    54 ce54f373 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    55 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("X- and Y-orders must be equal (%d != %d) " "due to a limitation in math::Chebyshev1Function2") % _orderX % _orderY)); } } /************************************************************************************************************/ namespace { /** * \brief Specialisation of Approximate in Chebyshev polynomials */ template class ApproximateChebyshev : public Approximate { template friend PTR(Approximate) math::makeApproximate(std::vector const &xVec, std::vector const &yVec, image::MaskedImage const& im, geom::Box2I const& bbox, ApproximateControl const& ctrl); public: virtual ~ApproximateChebyshev(); private: math::Chebyshev1Function2 _poly; ApproximateChebyshev(std::vector const &xVec, std::vector const &yVec, image::MaskedImage const& im, geom::Box2I const& bbox, ApproximateControl const& ctrl); virtual PTR(image::Image::OutPixelT>) doGetImage(int orderX, int orderY) const; virtual PTR(image::MaskedImage::OutPixelT>) doGetMaskedImage(int orderX, int orderY) const; }; /************************************************************************************************************/ namespace { // N.b. physically inlining these routines into ApproximateChebyshev // causes clang++ 3.1 problems; I suspect a clang bug (see http://llvm.org/bugs/show_bug.cgi?id=14162) inline void solveMatrix_Eigen(Eigen::MatrixXd &a, Eigen::VectorXd &b, Eigen::Map &c ) { Eigen::PartialPivLU lu(a); c = lu.solve(b); } } /** * \brief Fit a grid of points to a afw::math::Chebyshev1Function2D */ template ApproximateChebyshev::ApproximateChebyshev( std::vector const &xVec, ///< the x-values of points std::vector const &yVec, ///< the y-values of points image::MaskedImage const& im, ///< The values at (xVec, yVec) geom::Box2I const& bbox, ///< Range where approximation should be valid ApproximateControl const& ctrl ///< desired approximation algorithm ) : Approximate(xVec, yVec, bbox, ctrl), _poly(math::Chebyshev1Function2(ctrl.getOrderX(), geom::Box2D(bbox))) { #if !defined(NDEBUG) { std::vector const& coeffs = _poly.getParameters(); assert(std::accumulate(coeffs.begin(), coeffs.end(), 0.0) == 0.0); // i.e. coeffs is initialised to 0.0 } #endif int const nTerm = _poly.getNParameters(); // number of terms in polynomial int const nData = im.getWidth()*im.getHeight(); // number of data points /* * N.b. in the comments, * i runs over the 0..nTerm-1 coefficients * alpha runs over the 0..nData-1 data points */ /* * We need the value of the polynomials evaluated at every data point, so it's more * efficient to pre-calculate the values: termCoeffs[i][alpha] */ std::vector > termCoeffs(nTerm); for (int i = 0; i != nTerm; ++i) { termCoeffs[i].reserve(nData); } for (int iy = 0; iy != im.getHeight(); ++iy) { double const y = yVec[iy]; for (int ix = 0; ix != im.getWidth(); ++ix) { double const x = xVec[ix]; for (int i = 0; i != nTerm; ++i) { _poly.setParameter(i, 1.0); termCoeffs[i].push_back(_poly(x, y)); _poly.setParameter(i, 0.0); } } } // We'll solve A*c = b Eigen::MatrixXd A; A.setZero(nTerm, nTerm); // We'll solve A*c = b Eigen::VectorXd b; b.setZero(nTerm); /* * Go through the data accumulating the values of the A and b matrix/vector */ int alpha = 0; for (int iy = 0; iy != im.getHeight(); ++iy) { for (typename image::MaskedImage::const_x_iterator ptr = im.row_begin(iy), end = im.row_end(iy); ptr != end; ++ptr, ++alpha) { double const val = ptr.image();
    165 ce54f373 - double const ivar = 1/ptr.variance();
    166 83a9a5f5 + double const ivar = ctrl.getWeighting() ? 1/ptr.variance() : 1.0;
    ? ++++++++++++++++++++++ ++++++ if (!lsst::utils::isfinite(val + ivar)) { continue; } for (int i = 0; i != nTerm; ++i) { double const c_i = termCoeffs[i][alpha]; double const tmp = c_i*ivar; b(i) += val*tmp; A(i, i) += c_i*tmp; for (int j = 0; j < i; ++j) { double const c_j = termCoeffs[j][alpha]; A(i, j) += c_j*tmp; } } }
    183 ce54f373 + }
    184 50d76fd4 + if (A.isZero()) {
    185 50d76fd4 + throw LSST_EXCEPT(pex::exceptions::RuntimeError,
    186 50d76fd4 + "No valid points to fit. Variance is likely zero. Try weighting=False");
    } // We only filled out the lower triangular part of A for (int j = 0; j != nTerm; ++j) { for (int i = j + 1; i != nTerm; ++i) { A(j, i) = A(i, j); } } /* * OK, now all we ned do is solve that... */ std::vector cvec(nTerm); Eigen::Map c(&cvec[0], nTerm); // N.b. c shares memory with cvec solveMatrix_Eigen(A, b, c); _poly.setParameters(cvec); } /// \brief dtor template ApproximateChebyshev::~ApproximateChebyshev() { } /** * \brief worker function for getImage * * If orderX/orderY are specified the expansion will be truncated to that order * * \note As in the ApproximateControl ctor, the x- and y-orders must be equal */ template PTR(image::Image::OutPixelT>) ApproximateChebyshev::doGetImage(int orderX, ///< Order of approximation to use in x-direction int orderY ///< Order of approximation to use in y-direction ) const { if (orderX < 0) orderX = Approximate::_ctrl.getOrderX(); if (orderY < 0) orderY = Approximate::_ctrl.getOrderY(); math::Chebyshev1Function2 poly = (orderX == Approximate::_ctrl.getOrderX() && orderY == Approximate::_ctrl.getOrderY()) ? _poly : _poly.truncate(orderX); typedef typename image::Image::OutPixelT> ImageT; PTR(ImageT) im(new ImageT(Approximate::_bbox)); for (int iy = 0; iy != im->getHeight(); ++iy) { double const y = iy; int ix = 0; for (typename ImageT::x_iterator ptr = im->row_begin(iy), end = im->row_end(iy); ptr != end; ++ptr, ++ix) { double const x = ix; *ptr = poly(x, y); } } return im; } /** * \brief Return a MaskedImage * * * If orderX/orderY are specified the expansion will be truncated to that order * * \note As in the ApproximateControl ctor, the x- and y-orders must be equal */ template PTR(image::MaskedImage::OutPixelT>) ApproximateChebyshev::doGetMaskedImage( int orderX, ///< Order of approximation to use in x-direction int orderY ///< Order of approximation to use in y-direction ) const { typedef typename image::MaskedImage::OutPixelT> MImageT; PTR(MImageT) mi(new MImageT(Approximate::_bbox)); PTR(typename MImageT::Image) im = mi->getImage(); for (int iy = 0; iy != im->getHeight(); ++iy) { double const y = iy; int ix = 0; for (typename MImageT::Image::x_iterator ptr = im->row_begin(iy), end = im->row_end(iy); ptr != end; ++ptr, ++ix) { double const x = ix; *ptr = _poly(x, y); } } return mi; } } /************************************************************************************************************/ /** * \brief A factory function to make Approximate objects */ template PTR(Approximate) makeApproximate(std::vector const &x, ///< the x-values of points std::vector const &y, ///< the y-values of points image::MaskedImage const& im, ///< The values at (x, y) geom::Box2I const& bbox, ///< Range where approximation should be valid ApproximateControl const& ctrl ///< desired approximation algorithm ) { switch (ctrl.getStyle()) { case ApproximateControl::CHEBYSHEV: return PTR(Approximate)(new ApproximateChebyshev(x, y, im, bbox, ctrl)); default:
    295 3d2fc88e - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    300 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("Unknown ApproximationStyle: %d") % ctrl.getStyle())); } }
    304 b4f73cbf + /// \cond
    /* * Explicit instantiations *
    302 3d2fc88e - * \cond
    */ #define INSTANTIATE(PIXEL_T) \ template \ PTR(Approximate) makeApproximate( \ std::vector const &x, std::vector const &y, \ image::MaskedImage const& im, \ geom::Box2I const& bbox, \ ApproximateControl const& ctrl) INSTANTIATE(float); //INSTANTIATE(int); /// \endcond }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ce54f373

    commit ce54f373a160b8a69ca1f446780505ba649df8be
    Author: Robert Lupton the Good 
    Date:   Sat Oct 20 21:17:52 2012 -0400
    
        Compiles and runs (using temporary C++ test case)
    

    8a46673b

    commit 8a46673bdda9ca32eade33dac5bc1a53f9c6c180
    Author: Robert Lupton the Good 
    Date:   Sun Oct 21 20:16:18 2012 -0400
    
        Worked on documentation
    

    22807ea1

    commit 22807ea1c556edece81168730e99a93466db5222
    Author: Robert Lupton the Good 
    Date:   Sun Oct 21 18:42:00 2012 -0400
    
        Split Approximate.getImage, adding Approximate.getMaskedImage
        
        Restructured test case
    

    3d2fc88e

    commit 3d2fc88eb1a1cc9e11f09d0dfe6f1874d059f7a0
    Author: Robert Lupton the Good 
    Date:   Sat Oct 20 11:48:29 2012 -0400
    
        Initial version.
    

    Commits in /Users/nate/repos_lsst/afw/

    83a9a5f5

    commit 83a9a5f539b538b0cf4d5b67d8844a057d2401bc
    Author: Paul Price 
    Date:   Tue Jul 29 17:56:38 2014 -0500
    
        Approximate: make inverse-variance weighting configurable (#2411)
        
        If the input MaskedImage has identically zero variance (which
        occurs when approximating a BackgroundMI._statsImage constructed
        from a constant image; this occurs during testing with artificial
        images) then inverse variance weighting produces NANs.  Added an
        additional element in ApproximateControl to disable this behaviour.
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    b4f73cbf

    commit b4f73cbf3097165062c02aa04905ab10b06c6bec
    Author: Russell Owen 
    Date:   Mon Sep 8 16:05:52 2014 -0700
    
        First pass at DM-840
        Added UNDEFINED ImageOrigin enum value
        Made UNDEFINED the default for image constructors (which have lots of defaults,
        so I can't just delete the origin default).
        Eliminated the default value for ImageBase.getBBox.
        Modified all code that calls functions that accept an ImageOrigin argument to specify it explicitly.
    

    50d76fd4

    commit 50d76fd449d0438f9521f6d1257a1a23f7cebcf1
    Author: Yusra AlSayyad 
    Date:   Wed Jul 30 02:53:46 2014 -0500
    
        Throw a RuntimeError if no points (or their inverse variances) are finite in ApproximateChebyshev
        (Revision to inital solution for #2411)
    

    ce54f373

    commit ce54f373a160b8a69ca1f446780505ba649df8be
    Author: Robert Lupton the Good 
    Date:   Sat Oct 20 21:17:52 2012 -0400
    
        Compiles and runs (using temporary C++ test case)
    

    Return to list

    tests/imagePersistence1.py

    Diff:

    1 b10ab54c - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import os
    27 73e69aa0 + import unittest
    27 73e69aa0 - import unittest
    29 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests import lsst.afw.image as afwImage import lsst.daf.base as dafBase import lsst.daf.persistence as dafPers import lsst.pex.policy as pexPolicy
    33 73e69aa0 - import eups
    36 7cbb2bb9 + dataDir = lsst.utils.getPackageDir("afwdata")
    35 73e69aa0 - dataDir = eups.productDir("afwdata")
    36 73e69aa0 - if not dataDir:
    37 73e69aa0 - raise RuntimeError("You must set up afwdata to run these tests")
    class ImagePersistenceTestCase(unittest.TestCase): """A test case for Image Persistence""" def checkImages(self, image, image2): # Check that two images are identical (well, actually check only every 4th pixel) assert image.getHeight() == image2.getHeight() assert image.getWidth() == image2.getWidth() assert image.getY0() == image2.getY0() assert image.getX0() == image2.getX0() for x in xrange(0, image.getWidth(), 2): for y in xrange(0, image.getHeight(), 2): pixel1 = image.get(x, y) pixel2 = image2.get(x, y) # Persisting through Boost text archives causes conversion error! # assert abs(pixel1 - pixel2) / pixel1 < 1e-7, \ assert pixel1 == pixel2, \ "Differing pixel2 at %d, %d: %f, %f" % (x, y, pixel1, pixel2) def setUp(self): # Create the additionalData PropertySet self.additionalData = dafBase.PropertySet() self.additionalData.addInt("sliceId", 0) self.additionalData.addString("visitId", "fov391") self.additionalData.addInt("universeSize", 100) self.additionalData.addString("itemName", "foo") # Create an empty Policy policy = pexPolicy.Policy() # Get a Persistence object self.persistence = dafPers.Persistence.getPersistence(policy) # Choose a file to manipulate self.infile = os.path.join(dataDir, "CFHT", "D4", "cal-53535-i-797722_1.fits") self.image = afwImage.ImageF(self.infile) def tearDown(self): del self.additionalData del self.persistence del self.infile del self.image def testFitsPersistence(self): """Test persisting to FITS""" # Set up the LogicalLocation. logicalLocation = dafPers.LogicalLocation(self.infile) # Create a FitsStorage and put it in a StorageList. storage = self.persistence.getRetrieveStorage("FitsStorage", logicalLocation) storageList = dafPers.StorageList([storage]) # Let's do the retrieval! persPtr = self.persistence.unsafeRetrieve("ImageF", storageList, self.additionalData) image2 = afwImage.ImageF.swigConvert(persPtr) # Check the resulting Image self.checkImages(self.image, image2) def testBoostPersistence(self): """Persist the image using boost"""
    101 8bd58865 - boostFilePath = "image.boost"
    100 c605dfcd + with utilsTests.getTempFilePath(".boost") as boostFilePath:
    102 8bd58865 - logicalLocation = dafPers.LogicalLocation(boostFilePath)
    101 c605dfcd + logicalLocation = dafPers.LogicalLocation(boostFilePath)
    ? ++++
    103 73e69aa0 - storage = self.persistence.getPersistStorage("BoostStorage", logicalLocation)
    102 c605dfcd + storage = self.persistence.getPersistStorage("BoostStorage", logicalLocation)
    ? ++++
    104 73e69aa0 - storageList = dafPers.StorageList([storage])
    103 c605dfcd + storageList = dafPers.StorageList([storage])
    ? ++++
    105 73e69aa0 - self.persistence.persist(self.image, storageList, self.additionalData)
    104 c605dfcd + self.persistence.persist(self.image, storageList, self.additionalData)
    ? ++++
    107 73e69aa0 - # Retrieve it again
    106 c605dfcd + # Retrieve it again
    ? ++++
    108 73e69aa0 - storage = self.persistence.getRetrieveStorage("BoostStorage", logicalLocation)
    107 c605dfcd + storage = self.persistence.getRetrieveStorage("BoostStorage", logicalLocation)
    ? ++++
    109 73e69aa0 - storageList = dafPers.StorageList([storage])
    108 c605dfcd + storageList = dafPers.StorageList([storage])
    ? ++++
    110 73e69aa0 - pers2Ptr = self.persistence.unsafeRetrieve("ImageF", storageList, self.additionalData)
    109 c605dfcd + pers2Ptr = self.persistence.unsafeRetrieve("ImageF", storageList, self.additionalData)
    ? ++++
    111 73e69aa0 - image2 = afwImage.ImageF.swigConvert(pers2Ptr)
    110 c605dfcd + image2 = afwImage.ImageF.swigConvert(pers2Ptr)
    ? ++++
    112 73e69aa0 -
    111 c605dfcd +
    ? ++++
    113 73e69aa0 - # Check the resulting Image
    112 c605dfcd + # Check the resulting Image
    ? ++++
    114 73e69aa0 - self.checkImages(self.image, image2)
    113 c605dfcd + self.checkImages(self.image, image2)
    ? ++++
    116 8bd58865 - # Delete the boost-persisted image
    117 8bd58865 - os.remove(boostFilePath)
    118 8bd58865 -
    119 73e69aa0 - if False: # Crashes on RHL's os/x box -- #336
    120 73e69aa0 - def testBoostPersistenceU16(self):
    ? ----
    115 c605dfcd + def testBoostPersistenceU16(self):
    121 73e69aa0 - """Persist a U16 image using boost"""
    ? ----
    116 c605dfcd + """Persist a U16 image using boost"""
    122 8bd58865 - boostFilePath = "image.boost"
    117 c605dfcd + with utilsTests.getTempFilePath(".boost") as boostFilePath:
    logicalLocation = dafPers.LogicalLocation(boostFilePath) storage = self.persistence.getPersistStorage("BoostStorage", logicalLocation) storageList = dafPers.StorageList([storage]) # # Read a U16 image #
    129 f8edfe90 - self.image = self.im.Factory(os.path.join(dataDir, "small_MI_img.fits"))
    ? ----
    124 c605dfcd + self.image = self.image.Factory(os.path.join(dataDir, "data", "small_MI.fits"))
    ? +++ ++++++++ self.persistence.persist(self.image, storageList, self.additionalData) # Retrieve it again storage = self.persistence.getRetrieveStorage("BoostStorage", logicalLocation) storageList = dafPers.StorageList([storage]) pers2Ptr = self.persistence.unsafeRetrieve("ImageF", storageList, self.additionalData) image2 = afwImage.ImageF.swigConvert(pers2Ptr) # Check the resulting Image self.checkImages(self.image, image2)
    140 8bd58865 -
    141 8bd58865 - # Delete the boost-persisted image
    142 8bd58865 - os.remove(boostFilePath)
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ImagePersistenceTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    8bd58865

    commit 8bd58865340d9d8a6a4236f83779655321babcab
    Author: rowen 
    Date:   Mon Feb 7 23:29:52 2011 +0000
    
        Stopped two unit tests from leaving large files around on success
        (the files are still left on failure).
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    b10ab54c

    commit b10ab54c802578e3cc4158bc33aa212a5cba5bc4
    Author: rallsman 
    Date:   Sun Apr 6 01:43:41 2008 +0000
    
        Mostly replacing the files which were inexplicably zero length on last commit.
    

    73e69aa0

    commit 73e69aa077f5e218b81b3bb144174c698d9a06f1
    Author: rhl 
    Date:   Tue Apr 8 13:53:44 2008 +0000
    
        Use unittest and add #336 test case
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    73e69aa0

    commit 73e69aa077f5e218b81b3bb144174c698d9a06f1
    Author: rhl 
    Date:   Tue Apr 8 13:53:44 2008 +0000
    
        Use unittest and add #336 test case
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    tests/coordptr.py

    Diff:

    1 e04dd43d - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # # -*- python -*- """ Check that coord and coordPtr are properly passed through swig Run with: python coordptr.py """ import os import unittest
    36 e04dd43d - import eups
    37 7cbb2bb9 + import lsst.utils
    import lsst.afw.image as image
    38 e04dd43d - import lsst.afw.geom as geom
    import lsst.afw.geom as afwGeom import lsst.afw.coord.coordLib as coord import lsst.utils.tests as utilsTests
    42 e04dd43d - import lsst.daf.base as dafBase
    class CoordPtrTestCase(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def testMakeCoord(self): c = coord.Coord(1 * afwGeom.degrees,2 * afwGeom.degrees) print type(c) c = coord.makeCoord(coord.FK5, 1 * afwGeom.degrees, 2 * afwGeom.degrees) print type(c) def testMakeWcs(self):
    60 e04dd43d - path= eups.productDir("afw")
    59 7cbb2bb9 + afwdataDir = lsst.utils.getPackageDir("afw")
    61 e04dd43d - path = os.path.join(path, "tests", "data", "parent.fits")
    ? ^ ^
    60 7cbb2bb9 + path = os.path.join(afwdataDir, "tests", "data", "parent.fits")
    ? ^^^^ ^^^^ fitsHdr = image.readMetadata(path) wcs = image.makeWcs(fitsHdr) c = wcs.pixelToSky(0,0) print type(c) c.getPosition() def testCoordCast(self): for CoordClass in (coord.IcrsCoord, coord.Fk5Coord, coord.GalacticCoord, coord.EclipticCoord): derived1 = CoordClass(1 * afwGeom.degrees, 2 * afwGeom.degrees) self.assertEqual(type(derived1), CoordClass) base = derived1.clone() self.assertEqual(type(base), coord.Coord) derived2 = CoordClass.cast(base) self.assertEqual(type(derived2), CoordClass) ################################################################# # Test suite boiler plate ################################################################# def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(CoordPtrTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(exit = False): """Run the tests""" utilsTests.run(suite(), exit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    e04dd43d

    commit e04dd43d4b250f92e781595be7b063260f1ad7b7
    Author: fergal 
    Date:   Fri Mar 26 20:23:52 2010 +0000
    
        Make sure that Wcs is returning a Coord::Ptr correctly.
        Test was written to track down a bug in the image.i swig file.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    include/lsst/afw/table/FieldBase.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_FieldBase_h_INCLUDED
                    #define AFW_TABLE_FieldBase_h_INCLUDED
                    
                    #include 
                    #include 
                    
                    #include "boost/mpl/vector.hpp"
                    #include "boost/preprocessor/punctuation/paren.hpp"
                    #include "Eigen/Core"
                    
                    #include "lsst/base.h"
                    #include "lsst/pex/exceptions.h"
                    #include "ndarray.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/geom/ellipses.h"
                    #include "lsst/afw/coord.h"
                    #include "lsst/afw/table/misc.h"
                    #include "lsst/afw/table/KeyBase.h"
                    #include "lsst/afw/table/types.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    namespace detail {
                    
                    class TableImpl;
                    
                    /**
                     *  @brief Defines the ordering of packed covariance matrices.
                     *
                     *  This storage is equivalent to LAPACK 'UPLO=U'.
                     */
                    inline int indexCovariance(int i, int j) {
                        return (i < j) ? (i + j*(j+1)/2) : (j + i*(i+1)/2);
                    }
                    
                    /// Defines the packed size of a covariance matrices.
                    inline int computeCovariancePackedSize(int size) {
                        return size * (size + 1) / 2;
                    }
                    
                    } // namespace detail
                    
                    /**
                     *  @brief Field base class default implementation (used for numeric scalars and Angle).
                     *
                     *  FieldBase is where all the implementation
                     */
                    template 
                    struct FieldBase {
                    
                        typedef T Value;        ///< @brief the type returned by BaseRecord::get
                        typedef T & Reference;  ///< @brief the type returned by BaseRecord::operator[] (non-const)
                        typedef T const & ConstReference;  ///< @brief the type returned by BaseRecord::operator[] (const)
                        typedef T Element;      ///< @brief the type of subfields (the same as the type itself for scalars)
                    
                        /// @brief Return the number of subfield elements (always one for scalars).
                        int getElementCount() const { return 1; }
                    
                        /// @brief Return a string description of the field type.
                        static std::string getTypeString();
                    
                    #ifndef SWIG_BUG_3465431_FIXED
                        // SWIG uses this template to define the interface for the other specializations.
                        // We can add other methods to full specializations using %extend, but we can't add
                        // constructors that way.
                        FieldBase() {}
                        FieldBase(int) {
                            throw LSST_EXCEPT(
    
    70 9ccc92c4 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    70 21597d88 + lsst::pex::exceptions::LogicError,
    "Constructor disabled (it only appears to exist as a workaround for a SWIG bug)." ); } #endif protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(); } /// Defines how Fields are printed. void stream(std::ostream & os) const {} /// Used to implement RecordBase::operator[] (non-const). Reference getReference(Element * p, ndarray::Manager::Ptr const &) const { return *p; } /// Used to implement RecordBase::operator[] (const). ConstReference getConstReference(Element const * p, ndarray::Manager::Ptr const &) const { return *p; } /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const &) const { return *p; } /// Used to implement RecordBase::set. void setValue(Element * p, ndarray::Manager::Ptr const &, Value v) const { *p = v; } }; /** * @brief Field base class specialization for Coord. * * Coord fields are always stored in the ICRS system. You can assign Coords in other * systems to a record, but this will result in a conversion to ICRS, and returned * values will always be IcrsCoords. * * Coord fields do not support reference or const reference (operator[]) access. */ template <> struct FieldBase< Coord > { /// @brief the type returned by BaseRecord::get (coord::IcrsCoord, in this case). typedef IcrsCoord Value; /// @brief the type of subfields typedef Angle Element; /// @brief Return the number of subfield elements (always two for points). int getElementCount() const { return 2; } /// @brief Return a string description of the field type. static std::string getTypeString(); #ifndef SWIG_BUG_3465431_FIXED // SWIG uses this template to define the interface for the other specializations. // We can add other methods to full specializations using %extend, but we can't add // constructors that way. FieldBase() {} FieldBase(int) { throw LSST_EXCEPT(
    129 2cf33503 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    129 21597d88 + lsst::pex::exceptions::LogicError,
    "Constructor disabled (it only appears to exist as a workaround for a SWIG bug)." ); } #endif protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(); } /// Defines how Fields are printed. void stream(std::ostream & os) const {} /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const &) const { return Value(p[0], p[1]); } /// Used to implement RecordBase::set. void setValue(Element * p, ndarray::Manager::Ptr const &, Value const & v) const { p[0] = v.getRa(); p[1] = v.getDec(); } /// Used to implement RecordBase::set. void setValue(Element * p, ndarray::Manager::Ptr const & m, Coord const & v) const { setValue(p, m, v.toIcrs()); } }; /** * @brief Field base class specialization for points. * * Point fields do not support reference or const reference (operator[]) access. */ template struct FieldBase< Point > { /** * @brief the type returned by BaseRecord::get * * This will be geom::Point2I when U is an integer, and geom::Point2D when U is float or double. */ typedef typename boost::mpl::if_,geom::Point2I,geom::Point2D>::type Value; /// @brief the type of subfields typedef U Element; /// @brief Return the number of subfield elements (always two for points). int getElementCount() const { return 2; } /// @brief Return a string description of the field type. static std::string getTypeString(); #ifndef SWIG_BUG_3465431_FIXED // SWIG uses this template to define the interface for the other specializations. // We can add other methods to full specializations using %extend, but we can't add // constructors that way. FieldBase() {} FieldBase(int) { throw LSST_EXCEPT(
    191 9ccc92c4 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    191 21597d88 + lsst::pex::exceptions::LogicError,
    "Constructor disabled (it only appears to exist as a workaround for a SWIG bug)." ); } #endif protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(); } /// Defines how Fields are printed. void stream(std::ostream & os) const {} /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const &) const { return Value(p[0], p[1]); } /// Used to implement RecordBase::set. void setValue(Element * p, ndarray::Manager::Ptr const &, Value const & v) const { p[0] = v.getX(); p[1] = v.getY(); } }; /** * @brief Field base class specialization for second moments. * * Moments are ordered (xx, yy, xy), matching the order in geom::ellipses::Quadrupole. * * Moments fields do not support reference or const reference (operator[]) access. */ template struct FieldBase< Moments > { typedef afw::geom::ellipses::Quadrupole Value; ///< @brief the type returned by BaseRecord::get typedef U Element; /// @brief the type of subfields /// @brief Return the number of subfield elements (always three for shapes). int getElementCount() const { return 3; } /// @brief Return a string description of the field type. static std::string getTypeString(); #ifndef SWIG_BUG_3465431_FIXED // SWIG uses this template to define the interface for the other specializations. // We can add other methods to full specializations using %extend, but we can't add // constructors that way. FieldBase() {} FieldBase(int) { throw LSST_EXCEPT(
    241 9ccc92c4 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    241 21597d88 + lsst::pex::exceptions::LogicError,
    "Constructor disabled (it only appears to exist as a workaround for a SWIG bug)." ); } #endif protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(); } /// Defines how Fields are printed. void stream(std::ostream & os) const {} /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const &) const { return Value(p[0], p[1], p[2]); } /// Used to implement RecordBase::set. void setValue(Element * p, ndarray::Manager::Ptr const &, Value const & v) const { p[0] = v.getIxx(); p[1] = v.getIyy(); p[2] = v.getIxy(); } }; /** * @brief Field base class specialization for arrays. * * The Array tag is used for both fixed-length (same size in every record, accessible via ColumnView)
    272 0b745ec6 - * and variable-length arrays; variable-length arrays are initialized with zero size. Ideally,
    ? ^ ^^
    272 8389ad13 + * and variable-length arrays; variable-length arrays are initialized with a negative size. Ideally,
    ? ^^^ ^^^^^^ * we'd use complete different tag classes for those two very different types, but boost::variant and * boost::mpl put a limit of 20 on the number of field types, and we're running out. In a future * reimplementation of afw::table, we should fix this. */ template struct FieldBase< Array > { typedef ndarray::Array Value; ///< @brief the type returned by BaseRecord::get /// @brief the type returned by BaseRecord::operator[] typedef ndarray::ArrayRef Reference; /// @brief the type returned by BaseRecord::operator[] (const) typedef ndarray::ArrayRef ConstReference; typedef U Element; ///< @brief the type of subfields and array elements /** * @brief Construct a FieldBase with the given size. * * A size == 0 indicates a variable-length array. Negative sizes are not permitted. * * This constructor is implicit with a default so it can be used in the Field * constructor (as if it were an int argument) without specializing Field. In other words, * it allows one to construct a 25-element array field like this: * @code * Field< Array >("name", "documentation", 25); * @endcode * ...even though the third argument to the Field constructor takes a FieldBase, not an int. */ FieldBase(int size=0) : _size(size) { if (size < 0) throw LSST_EXCEPT(
    305 0b745ec6 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    305 2d6be90c + lsst::pex::exceptions::LogicError,
    306 0b745ec6 - "Negative sizes are not allowed."
    306 8389ad13 + "A non-negative size must be provided when constructing an array field."
    ); } /// @brief Return a string description of the field type. static std::string getTypeString(); /// @brief Return the number of subfield elements (equal to the size of the array). int getElementCount() const { return _size; } /// @brief Return the size of the array (equal to the number of subfield elements). int getSize() const { return _size; } /// @brief Return true if the field is variable-length (each record can have a different size array). bool isVariableLength() const { return _size == 0; } protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(0); } /// Defines how Fields are printed. void stream(std::ostream & os) const { os << ", size=" << _size; } /// Used to implement RecordBase::operator[] (non-const). Reference getReference(Element * p, ndarray::Manager::Ptr const & m) const { if (isVariableLength()) { return reinterpret_cast< ndarray::Array * >(p)->deep(); } return ndarray::external(p, ndarray::makeVector(_size), ndarray::ROW_MAJOR, m); } /// Used to implement RecordBase::operator[] (const). ConstReference getConstReference(Element const * p, ndarray::Manager::Ptr const & m) const { if (isVariableLength()) { return reinterpret_cast< ndarray::Array const * >(p)->deep(); } return ndarray::external(p, ndarray::makeVector(_size), ndarray::ROW_MAJOR, m); } /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const & m) const { if (isVariableLength()) { return *reinterpret_cast< ndarray::Array const * >(p); } return ndarray::external(p, ndarray::makeVector(_size), ndarray::ROW_MAJOR, m); } /// Used to implement RecordBase::set; accepts only non-const arrays of the right type, /// and allows shallow assignment of variable-length arrays (which is the only kind of /// assignment allowed for variable-length arrays - if you want deep assignment, use /// operator[] to get a reference and assign to that. void setValue( Element * p, ndarray::Manager::Ptr const &, ndarray::Array const & value ) const { if (isVariableLength()) { *reinterpret_cast< ndarray::Array* >(p) = value; } else { setValueDeep(p, value); } } /// Used to implement RecordBase::set; accepts any ndarray expression. template void setValue( Element * p, ndarray::Manager::Ptr const &, ndarray::ExpressionBase const & value ) const { if (isVariableLength()) { throw LSST_EXCEPT(
    375 0b745ec6 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    375 2d6be90c + lsst::pex::exceptions::LogicError,
    "Assignment to a variable-length array must use a non-const array of the correct type." ); } setValueDeep(p, value); } private: template void setValueDeep(Element * p, ndarray::ExpressionBase const & value) const { if (value.template getSize<0>() != _size) { throw LSST_EXCEPT(
    388 5dee136a - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    388 21597d88 + lsst::pex::exceptions::LengthError,
    "Incorrect size in array field assignment." ); } for (int i = 0; i < _size; ++i) p[i] = value[i]; } int _size; }; /** * @brief Field base class specialization for dynamically-sized covariance matrices. * * Covariance matrices are always square and symmetric, and fields are stored packed * using the same scheme as LAPACK's UPLO=U: * { (0,0), (0,1), (1,1), (0,2), (1,2), (2,2), ... } * * These elements are packed and unpacked into a dense Eigen matrix when getting and setting * the field. * * Covariance fields do not support reference (operator[]) access. */ template struct FieldBase< Covariance > { /// @brief the type returned by BaseRecord::get typedef Eigen::Matrix Value; typedef U Element; ///< @brief the type of subfields and matrix elements /** * @brief Construct a FieldBase with the given size. * * This constructor is implicit and has an invalid default so it can be used in the Field * constructor (as if it were an int argument) without specializing Field. In other words, * it allows one to construct a 25x25 covariance field like this: * @code * Field< Covariance >("name", "documentation", 25); * @endcode * ...even though the third argument to the Field constructor takes a FieldBase, not an int. */ FieldBase(int size=-1) : _size(size) { if (size < 0) throw LSST_EXCEPT(
    431 5dee136a - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    431 21597d88 + lsst::pex::exceptions::LengthError,
    "Size must be provided when constructing a covariance field." ); } /// @brief Return a string description of the field type. static std::string getTypeString(); /// @brief Return the number of subfield elements (the packed size of the covariance matrix). int getElementCount() const { return getPackedSize(); } /// @brief Return the number of rows/columns of the covariance matrix. int getSize() const { return _size; } /// @brief Return the packed size of the covariance matrix. int getPackedSize() const { return detail::computeCovariancePackedSize(_size); } protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(0); } /// Defines how Fields are printed. void stream(std::ostream & os) const { os << ", size=" << _size; } /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const &) const { Value m(_size, _size); for (int i = 0; i < _size; ++i) { for (int j = 0; j < _size; ++j) { m(i, j) = p[detail::indexCovariance(i, j)]; } } return m; } /// Used to implement RecordBase::set. template void setValue( Element * p, ndarray::Manager::Ptr const &, Eigen::MatrixBase const & value ) const { if (value.rows() != _size || value.cols() != _size) { throw LSST_EXCEPT(
    474 5dee136a - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    474 21597d88 + lsst::pex::exceptions::LengthError,
    "Incorrect size in covariance field assignment." ); } for (int i = 0; i < _size; ++i) { for (int j = 0; j < _size; ++j) { p[detail::indexCovariance(i, j)] = value(i, j); } } } int _size; }; /** * @brief Field base class specialization for covariance matrices for points. * * Covariance fields are stored packed in the following order: * { (x,x), (x,y), (y,y) } * * These elements are packed and unpacked into a dense Eigen matrix when getting and setting * the field. */ template struct FieldBase< Covariance< Point > > { static int const SIZE = 2; static int const PACKED_SIZE = 3; typedef Eigen::Matrix Value; ///< @brief the type returned by BaseRecord::get typedef U Element; ///< @brief the type of subfields and matrix elements /// @brief Return a string description of the field type. static std::string getTypeString(); /// @brief Return the number of subfield elements (the packed size of the covariance matrix). int getElementCount() const { return getPackedSize(); } /// @brief Return the number of rows/columns of the covariance matrix. int getSize() const { return SIZE; } /// @brief Return the packed size of the covariance matrix. int getPackedSize() const { return PACKED_SIZE; } #ifndef SWIG_BUG_3465431_FIXED // SWIG uses this template to define the interface for the other specializations. // We can add other methods to full specializations using %extend, but we can't add // constructors that way. FieldBase() {} FieldBase(int) { throw LSST_EXCEPT(
    525 9ccc92c4 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    525 21597d88 + lsst::pex::exceptions::LogicError,
    "Constructor disabled (it only appears to exist as a workaround for a SWIG bug)." ); } #endif protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(); } /// Defines how Fields are printed. void stream(std::ostream & os) const {} /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const &) const { Value m; for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { m(i, j) = p[detail::indexCovariance(i, j)]; } } return m; } /// Used to implement RecordBase::set. template static void setValue( Element * p, ndarray::Manager::Ptr const &, Eigen::MatrixBase const & value ) { BOOST_STATIC_ASSERT( Derived::RowsAtCompileTime == SIZE); BOOST_STATIC_ASSERT( Derived::ColsAtCompileTime == SIZE); for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { p[detail::indexCovariance(i, j)] = value(i, j); } } } }; /** * @brief Field base class specialization for covariance matrices for shapes. * * Covariance fields are stored packed in the following order: * { (xx,xx), (xx,yy), (yy,yy), (xx,xy), (yy,xy), (xy,xy) } * * These elements are packed and unpacked into a dense Eigen matrix when getting and setting * the field. */ template struct FieldBase< Covariance< Moments > > { static int const SIZE = 3; static int const PACKED_SIZE = 6; typedef Eigen::Matrix Value; ///< @brief the type returned by BaseRecord::get typedef U Element; ///< @brief the type of subfields and matrix elements /// @brief Return a string description of the field type. static std::string getTypeString(); /// @brief Return the number of subfield elements (the packed size of the covariance matrix). int getElementCount() const { return getPackedSize(); } /// @brief Return the number of rows/columns of the covariance matrix. int getSize() const { return SIZE; } /// @brief Return the packed size of the covariance matrix. int getPackedSize() const { return PACKED_SIZE; } #ifndef SWIG_BUG_3465431_FIXED // SWIG uses this template to define the interface for the other specializations. // We can add other methods to full specializations using %extend, but we can't add // constructors that way. FieldBase() {} FieldBase(int) { throw LSST_EXCEPT(
    603 9ccc92c4 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    603 21597d88 + lsst::pex::exceptions::LogicError,
    "Constructor disabled (it only appears to exist as a workaround for a SWIG bug)." ); } #endif protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(); } /// Defines how Fields are printed. void stream(std::ostream & os) const {} /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const &) const { Value m; for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { m(i, j) = p[detail::indexCovariance(i, j)]; } } return m; } /// Used to implement RecordBase::set. template static void setValue( Element * p, ndarray::Manager::Ptr const &, Eigen::MatrixBase const & value ) { BOOST_STATIC_ASSERT( Derived::RowsAtCompileTime == SIZE); BOOST_STATIC_ASSERT( Derived::ColsAtCompileTime == SIZE); for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { p[detail::indexCovariance(i, j)] = value(i, j); } } } }; /** * @brief Field base class specialization for strings. */ template <> struct FieldBase< std::string > { typedef std::string Value; ///< @brief the type returned by BaseRecord::get /// @brief the type returned by BaseRecord::operator[] typedef char * Reference; /// @brief the type returned by BaseRecord::operator[] (const) typedef char const * ConstReference; typedef char Element; ///< @brief the type of subfields and array elements /** * @brief Construct a FieldBase with the given size. * * This constructor is implicit and has an invalid default so it can be used in the Field * constructor (as if it were an int argument) without specializing Field. In other words, * it allows one to construct a 25-character string field like this: * @code * Field< std::string >("name", "documentation", 25); * @endcode * ...even though the third argument to the Field constructor takes a FieldBase, not an int. */ FieldBase(int size=-1); /// @brief Return a string description of the field type. static std::string getTypeString(); /// @brief Return the number of subfield elements (equal to the size of the string, /// including a null terminator). int getElementCount() const { return _size; } /// @brief Return the maximum length of the string, including a null terminator /// (equal to the number of subfield elements). int getSize() const { return _size; } protected: /// Needed to allow Keys to be default-constructed. static FieldBase makeDefault() { return FieldBase(0); } /// Defines how Fields are printed. void stream(std::ostream & os) const { os << ", size=" << _size; } /// Used to implement RecordBase::operator[] (non-const). Reference getReference(Element * p, ndarray::Manager::Ptr const & m) const { return p; } /// Used to implement RecordBase::operator[] (const). ConstReference getConstReference(Element const * p, ndarray::Manager::Ptr const & m) const { return p; } /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const & m) const; /// Used to implement RecordBase::set void setValue(Element * p, ndarray::Manager::Ptr const &, std::string const & value) const; private: int _size; }; }}} // namespace lsst::afw::table #endif // !AFW_TABLE_FieldBase_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0b745ec6

    commit 0b745ec681de903b911691c49f07f3ebc52c692f
    Author: Jim Bosch 
    Date:   Mon Dec 1 13:46:03 2014 -0500
    
        Add variable-length array fields to afw::table
        
        We use Array with a size of zero to indicate variable-length fields.
        It'd probably be better to use a completely different tag type, but
        Boost.Variant puts an upper limit on how many tags we have, so until
        we rewrite afw::table to avoid it, we need to limit how many we use.
    

    5dee136a

    commit 5dee136a9f602af873bc62bd6c6efb36e7aeb0d6
    Author: Jim Bosch 
    Date:   Sun Nov 20 01:21:52 2011 -0500
    
        removed per-field null bits
    

    9ccc92c4

    commit 9ccc92c4fd4e52ea5f809bd6d05404363ec0a896
    Author: Jim Bosch 
    Date:   Wed Jan 4 23:35:32 2012 -0500
    
        started SWIG for table package; Schema mostly wrapped
    

    2cf33503

    commit 2cf33503feb13b45c362d6b1d9fc16e74eafc9df
    Author: Jim Bosch 
    Date:   Fri Jan 20 18:31:39 2012 -0500
    
        added Angle and Coord field types, reworked Source measurement slots
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    2d6be90c

    commit 2d6be90c6e14ab8fa2803a84a45106345037f1f5
    Author: Lauren MacArthur 
    Date:   Thu Apr 2 13:50:52 2015 -0400
    
        Remove trailing Exception in exception names
    

    8389ad13

    commit 8389ad136cfab250ccee9de4e697acdd7e3e43b0
    Author: Jim Bosch 
    Date:   Fri Nov 21 17:18:04 2014 -0500
    
        Add variable-length array fields to afw::table
        
        We use Array with a size of zero to indicate variable-length fields.
        It'd probably be better to use a completely different tag type, but
        Boost.Variant puts an upper limit on how many tags we have, so until
        we rewrite afw::table to avoid it, we need to limit how many we use.
        
        Conflicts:
            include/lsst/afw/table/FieldBase.h
            src/table/Schema.cc
            tests/testSimpleTable.py
    

    Return to list

    include/lsst/afw/table/misc.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_misc_h_INCLUDED
                    #define AFW_TABLE_misc_h_INCLUDED
                    
                    #include "boost/cstdint.hpp"
                    #include "boost/mpl/if.hpp"
                    #include "boost/type_traits/is_const.hpp"
                    #include "boost/type_traits/add_const.hpp"
                    
                    #include "lsst/afw/geom/Angle.h"
                    #include "lsst/afw/coord/Coord.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    /**
                     *  @brief Type used for unique IDs for records.
                     *
                     *  FITS isn't fond of uint64, so we can save a lot of pain by using signed ints here unless
                     *  we really need unsigned.
                     */
                    typedef boost::int64_t RecordId;
                    
    
    23 dce194d3 + enum class CoordinateType {
    24 dce194d3 + PIXEL,
    25 dce194d3 + CELESTIAL
    26 dce194d3 + };
    27 dce194d3 +
    //@{ /** * @brief Tag types used to declare specialized field types. * * See the documentation for specializations of FieldBase and KeyBase * for more information. */ template class Point; template class Moments; template class Array; template class Covariance; class Flag; typedef lsst::afw::coord::Coord Coord; typedef lsst::afw::coord::IcrsCoord IcrsCoord; typedef lsst::afw::geom::Angle Angle; //@} }}} // namespace lsst::afw::table #endif // !AFW_TABLE_misc_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    dce194d3

    commit dce194d3b409b3718149c99ee1dbe5620ccee734
    Author: John Swinbank 
    Date:   Thu Apr 2 19:09:27 2015 -0400
    
        Extend QuadrupoleKey to celestial coords.
        
        We can thereby use the same underlying mechanism to describe quadrupoles in
        pixel and celestial coordinates. Internally, we continue to refer to "x" and
        "y", but use appropriate names and units when writing to a table.
    

    Return to list

    src/fits.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    #include 
                    #include 
                    #include 
                    
                    #include "fitsio.h"
                    extern "C" {
                    #include "fitsio2.h"
                    }
                    
                    #include "boost/regex.hpp"
                    #include "boost/filesystem.hpp"
                    #include "boost/preprocessor/seq/for_each.hpp"
                    #include "boost/cstdint.hpp"
                    #include "boost/format.hpp"
                    #include "boost/scoped_array.hpp"
                    
                    #include "lsst/utils/ieee.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Log.h"
                    #include "lsst/afw/fits.h"
                    #include "lsst/afw/geom/Angle.h"
                    
                    namespace lsst { namespace afw { namespace fits {
                    
                    // ----------------------------------------------------------------------------------------------------------
                    // ---- Miscellaneous utilities -----------------------------------------------------------------------------
                    // ----------------------------------------------------------------------------------------------------------
                    
                    namespace {
                    
                    // Strip leading and trailing single quotes and whitespace from a string.
                    std::string strip(std::string const & s) {
                        if (s.empty()) return s;
                        std::size_t i1 = s.find_first_not_of(" '");
                        std::size_t i2 = s.find_last_not_of(" '");
                        return s.substr(i1, (i1 == std::string::npos) ? 0 : 1 + i2 - i1);
                    }
                    
                    // ---- FITS binary table format codes for various C++ types. -----------------------------------------------
                    
                    char getFormatCode(bool*) { return 'X'; }
                    char getFormatCode(std::string*) { return 'A'; }
                    char getFormatCode(boost::int8_t*) { return 'S'; }
                    char getFormatCode(boost::uint8_t*) { return 'B'; }
                    char getFormatCode(boost::int16_t*) { return 'I'; }
                    char getFormatCode(boost::uint16_t*) { return 'U'; }
                    char getFormatCode(boost::int32_t*) { return 'J'; }
                    char getFormatCode(boost::uint32_t*) { return 'V'; }
                    char getFormatCode(boost::int64_t*) { return 'K'; }
                    char getFormatCode(float*) { return 'E'; }
                    char getFormatCode(double*) { return 'D'; }
                    char getFormatCode(std::complex*) { return 'C'; }
                    char getFormatCode(std::complex*) { return 'M'; }
                    char getFormatCode(lsst::afw::geom::Angle*) { return 'D'; }
                    
                    // ---- Create a TFORM value for the given type and size ----------------------------------------------------
                    
                    template 
                    std::string makeColumnFormat(int size = 1) {
                        if (size > 0) {
                            return (boost::format("%d%c") % size % getFormatCode((T*)0)).str();
                        } else if (size < 0) {
                            // variable length, max size given as -size
    
    66 e182e1df - return (boost::format("1Q%c(%d)") % getFormatCode((T*)0) % (-size)).str();
    ? ^
    66 e6936b03 + return (boost::format("1P%c(%d)") % getFormatCode((T*)0) % (-size)).str();
    ? ^ } else { // variable length, max size unknown
    69 e182e1df - return (boost::format("1Q%c") % getFormatCode((T*)0)).str();
    ? ^
    69 e6936b03 + return (boost::format("1P%c") % getFormatCode((T*)0)).str();
    ? ^ } } // ---- Traits class to get cfitsio type constants from templates ------------------------------------------- template struct FitsType; template <> struct FitsType { static int const CONSTANT = TLOGICAL; }; template <> struct FitsType { static int const CONSTANT = TSTRING; }; template <> struct FitsType { static int const CONSTANT = TBYTE; }; template <> struct FitsType { static int const CONSTANT = TSHORT; }; template <> struct FitsType { static int const CONSTANT = TUSHORT; }; template <> struct FitsType { static int const CONSTANT = TINT; }; template <> struct FitsType { static int const CONSTANT = TUINT; }; template <> struct FitsType { static int const CONSTANT = TLONG; }; template <> struct FitsType { static int const CONSTANT = TULONG; }; template <> struct FitsType { static int const CONSTANT = TLONGLONG; }; template <> struct FitsType { static int const CONSTANT = TLONGLONG; }; template <> struct FitsType { static int const CONSTANT = TFLOAT; }; template <> struct FitsType { static int const CONSTANT = TDOUBLE; }; template <> struct FitsType { static int const CONSTANT = TDOUBLE; }; template <> struct FitsType< std::complex > { static int const CONSTANT = TCOMPLEX; }; template <> struct FitsType< std::complex > { static int const CONSTANT = TDBLCOMPLEX; }; // We use TBIT when writing booleans to table cells, but TLOGICAL in headers. template struct FitsTableType : public FitsType {}; template <> struct FitsTableType { static int const CONSTANT = TBIT; }; template struct FitsBitPix; template <> struct FitsBitPix { static int const CONSTANT = BYTE_IMG; }; template <> struct FitsBitPix { static int const CONSTANT = SHORT_IMG; }; template <> struct FitsBitPix { static int const CONSTANT = USHORT_IMG; }; template <> struct FitsBitPix { static int const CONSTANT = LONG_IMG; }; // not a typo! template <> struct FitsBitPix { static int const CONSTANT = ULONG_IMG; }; template <> struct FitsBitPix { static int const CONSTANT = LONGLONG_IMG; }; template <> struct FitsBitPix { static int const CONSTANT = LONGLONG_IMG; }; template <> struct FitsBitPix { static int const CONSTANT = FLOAT_IMG; }; template <> struct FitsBitPix { static int const CONSTANT = DOUBLE_IMG; }; } // anonymous // ---------------------------------------------------------------------------------------------------------- // ---- Implementations for stuff in fits.h ----------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------- std::string makeErrorMessage(std::string const & fileName, int status, std::string const & msg) { std::ostringstream os; os << "cfitsio error"; if (fileName != "") { os << " (" << fileName << ")"; } if (status != 0) { char fitsErrMsg[FLEN_ERRMSG]; fits_get_errstatus(status, fitsErrMsg); os << ": " << fitsErrMsg << " (" << status << ")"; } if (msg != "") { os << " : " << msg; } return os.str(); } std::string makeErrorMessage(void * fptr, int status, std::string const & msg) { std::string fileName = ""; fitsfile * fd = reinterpret_cast(fptr); if (fd != 0 && fd->Fptr != 0 && fd->Fptr->filename != 0) { fileName = fd->Fptr->filename; } return makeErrorMessage(fileName, status, msg); } void MemFileManager::reset() { if (_managed) std::free(_ptr); _ptr = 0; _len = 0; _managed = true; } void MemFileManager::reset(std::size_t len) { reset(); _ptr = std::malloc(len); _len = len; _managed = true; } template int getBitPix() { return FitsBitPix::CONSTANT; } // ---------------------------------------------------------------------------------------------------------- // ---- Implementations for Fits class ---------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------- std::string Fits::getFileName() const { std::string fileName = ""; fitsfile * fd = reinterpret_cast(fptr); if (fd != 0 && fd->Fptr != 0 && fd->Fptr->filename != 0) { fileName = fd->Fptr->filename; } return fileName; } int Fits::getHdu() { int n = 0; fits_get_hdu_num(reinterpret_cast(fptr), &n); return n; } void Fits::setHdu(int hdu, bool relative) { if (relative) { fits_movrel_hdu(reinterpret_cast(fptr), hdu, 0, &status); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Incrementing HDU by %d") % hdu); } } else { if (hdu != 0) { fits_movabs_hdu(reinterpret_cast(fptr), hdu, 0, &status); } if (hdu == 0 && getHdu() == 1 && getImageDim() == 0) { // want a silent failure here int tmpStatus = status; fits_movrel_hdu(reinterpret_cast(fptr), 1, 0, &tmpStatus); } if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Moving to HDU %d") % hdu); } } } int Fits::countHdus() { int n = 0; fits_get_num_hdus(reinterpret_cast(fptr), &n, &status); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, "Getting number of HDUs in file."); } return n; } // ---- Writing and updating header keys -------------------------------------------------------------------- namespace { // Impl functions in the anonymous namespace do special handling for strings, bools, and IEEE fp values. /// Convert a double to a special string for writing FITS keyword values /// /// Non-finite values are written as special strings. If the value is finite, /// an empty string is returned. std::string nonFiniteDoubleToString(double value) { if (utils::isfinite(value)) { return ""; } if (utils::isnan(value)) { return "NAN"; } if (value < 0) { return "-INFINITY"; } return "+INFINITY"; } /// Convert a special string to double when reading FITS keyword values /// /// Returns zero if the provided string is not one of the recognised special /// strings for doubles; otherwise, returns the mapped value. double stringToNonFiniteDouble(std::string const& value) { if (value == "NAN") { return std::numeric_limits::quiet_NaN(); } if (value == "+INFINITY") { return std::numeric_limits::infinity(); } if (value == "-INFINITY") { return -std::numeric_limits::infinity(); } return 0; } template void updateKeyImpl(Fits & fits, char const * key, T const & value, char const * comment) { fits_update_key( reinterpret_cast(fits.fptr), FitsType::CONSTANT, const_cast(key), const_cast(&value), const_cast(comment), &fits.status ); } void updateKeyImpl(Fits & fits, char const * key, std::string const & value, char const * comment) { fits_update_key_longstr( reinterpret_cast(fits.fptr), const_cast(key), const_cast(value.c_str()), const_cast(comment), &fits.status ); } void updateKeyImpl(Fits & fits, char const * key, bool const & value, char const * comment) { int v = value; fits_update_key( reinterpret_cast(fits.fptr), TLOGICAL, const_cast(key), &v, const_cast(comment), &fits.status ); } void updateKeyImpl(Fits & fits, char const * key, double const & value, char const * comment) { std::string strValue = nonFiniteDoubleToString(value); if (!strValue.empty()) { updateKeyImpl(fits, key, strValue, comment); } else { fits_update_key( reinterpret_cast(fits.fptr), FitsType::CONSTANT, const_cast(key), const_cast(&value), const_cast(comment), &fits.status ); } } template void writeKeyImpl(Fits & fits, char const * key, T const & value, char const * comment) { fits_write_key( reinterpret_cast(fits.fptr), FitsType::CONSTANT, const_cast(key), const_cast(&value), const_cast(comment), &fits.status ); } void writeKeyImpl(Fits & fits, char const * key, std::string const & value, char const * comment) { if (strncmp(key, "COMMENT", 7) == 0) { fits_write_comment( reinterpret_cast(fits.fptr), const_cast(value.c_str()), &fits.status ); } else if (strncmp(key, "HISTORY", 7) == 0) { fits_write_history( reinterpret_cast(fits.fptr), const_cast(value.c_str()), &fits.status ); } else { fits_write_key_longstr( reinterpret_cast(fits.fptr), const_cast(key), const_cast(value.c_str()), const_cast(comment), &fits.status ); } } void writeKeyImpl(Fits & fits, char const * key, bool const & value, char const * comment) { int v = value; fits_write_key( reinterpret_cast(fits.fptr), TLOGICAL, const_cast(key), &v, const_cast(comment), &fits.status ); } void writeKeyImpl(Fits & fits, char const * key, double const & value, char const * comment) { std::string strValue = nonFiniteDoubleToString(value); if (!strValue.empty()) { writeKeyImpl(fits, key, strValue, comment); } else { fits_write_key( reinterpret_cast(fits.fptr), FitsType::CONSTANT, const_cast(key), const_cast(&value), const_cast(comment), &fits.status ); } } } // anonymous template void Fits::updateKey(std::string const & key, T const & value, std::string const & comment) { updateKeyImpl(*this, key.c_str(), value, comment.c_str()); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s': '%s'") % key % value); } } template void Fits::writeKey(std::string const & key, T const & value, std::string const & comment) { writeKeyImpl(*this, key.c_str(), value, comment.c_str()); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s': '%s'") % key % value); } } template void Fits::updateKey(std::string const & key, T const & value) { updateKeyImpl(*this, key.c_str(), value, 0); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s': '%s'") % key % value); } } template void Fits::writeKey(std::string const & key, T const & value) { writeKeyImpl(*this, key.c_str(), value, 0); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s': '%s'") % key % value); } } template void Fits::updateColumnKey(std::string const & prefix, int n, T const & value, std::string const & comment) { updateKey((boost::format("%s%d") % prefix % (n + 1)).str(), value, comment); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s%d': '%s'") % prefix % (n+1) % value); } } template void Fits::writeColumnKey(std::string const & prefix, int n, T const & value, std::string const & comment) { writeKey((boost::format("%s%d") % prefix % (n + 1)).str(), value, comment); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s%d': '%s'") % prefix % (n+1) % value); } } template void Fits::updateColumnKey(std::string const & prefix, int n, T const & value) { updateKey((boost::format("%s%d") % prefix % (n + 1)).str(), value); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s%d': '%s'") % prefix % (n+1) % value); } } template void Fits::writeColumnKey(std::string const & prefix, int n, T const & value) { writeKey((boost::format("%s%d") % prefix % (n + 1)).str(), value); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s%d': '%s'") % prefix % (n+1) % value); } } // ---- Reading header keys --------------------------------------------------------------------------------- namespace { template void readKeyImpl(Fits & fits, char const * key, T & value) { fits_read_key( reinterpret_cast(fits.fptr), FitsType::CONSTANT, const_cast(key), &value, 0, &fits.status ); } void readKeyImpl(Fits & fits, char const * key, std::string & value) { char * buf = 0; fits_read_key_longstr( reinterpret_cast(fits.fptr), const_cast(key), &buf, 0, &fits.status ); if (buf) { value = strip(buf); free(buf); } } void readKeyImpl(Fits & fits, char const * key, double & value) { // We need to check for the possibility that the value is a special string (for NAN, +/-Inf). // If a quote mark (') is present then it's a string. char buf[FLEN_VALUE]; fits_read_keyword(reinterpret_cast(fits.fptr), const_cast(key), buf, 0, &fits.status); if (fits.status != 0) { return; } if (std::string(buf).find('\'') != std::string::npos) { std::string unquoted; readKeyImpl(fits, key, unquoted); // Let someone else remove quotes and whitespace if (fits.status != 0) { return; } value = stringToNonFiniteDouble(unquoted); if (value == 0) { throw LSST_EXCEPT( afw::fits::FitsError, (boost::format("Unrecognised string value for keyword '%s' when parsing as double: %s") % key % unquoted).str()); } } else { fits_read_key( reinterpret_cast(fits.fptr), FitsType::CONSTANT, const_cast(key), &value, 0, &fits.status ); } } } // anonymous template void Fits::readKey(std::string const & key, T & value) { readKeyImpl(*this, key.c_str(), value); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Reading key '%s'") % key); } } void Fits::forEachKey(HeaderIterationFunctor & functor) { char key[81]; // allow for terminating NUL char value[81]; char comment[81]; int nKeys = 0; fits_get_hdrspace(reinterpret_cast(fptr), &nKeys, 0, &status); std::string keyStr; std::string valueStr; std::string commentStr; int i = 1; while (i <= nKeys) { fits_read_keyn(reinterpret_cast(fptr), i, key, value, comment, &status); keyStr = key; valueStr = value; commentStr = comment; ++i; while (valueStr.size() > 2 && valueStr[valueStr.size() - 2] == '&' && i <= nKeys) { // we're using key to hold the entire record here; the actual key is safe in keyStr fits_read_record(reinterpret_cast(fptr), i, key, &status);
    528 c547845f - if (!strncmp(key, "CONTINUE", 8) == 0) {
    ? - -
    528 2c60faef + if (strncmp(key, "CONTINUE", 8) != 0) {
    ? + // require both trailing '&' and CONTINUE to invoke long-string handling break; } std::string card = key; valueStr.erase(valueStr.size() - 2); std::size_t firstQuote = card.find('\''); if (firstQuote == std::string::npos) { throw LSST_EXCEPT( FitsError, makeErrorMessage( fptr, status, boost::format("Invalid CONTINUE at header key %d: \"%s\".") % i % card ) ); } std::size_t lastQuote = card.find('\'', firstQuote + 1); if (lastQuote == std::string::npos) { throw LSST_EXCEPT( FitsError, makeErrorMessage( fptr, status, boost::format("Invalid CONTINUE at header key %d: \"%s\".") % i % card ) ); } valueStr += card.substr(firstQuote + 1, lastQuote - firstQuote); std::size_t slash = card.find('/', lastQuote + 1); if (slash != std::string::npos) { commentStr += strip(card.substr(slash + 1)); } ++i; } if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Reading key '%s'") % keyStr); } functor(keyStr, valueStr, commentStr); } } // ---- Reading and writing PropertySet/PropertyList -------------------------------------------------------- namespace { bool isKeyIgnored(std::string const & key) { return key == "SIMPLE" || key == "BITPIX" || key == "EXTEND" || key == "GCOUNT" || key == "PCOUNT" || key == "XTENSION" || key == "TFIELDS" || key == "BSCALE" || key == "BZERO" || key.compare(0, 5, "NAXIS") == 0; } class MetadataIterationFunctor : public HeaderIterationFunctor { public: virtual void operator()( std::string const & key, std::string const & value, std::string const & comment ); template void add(std::string const & key, T value, std::string const & comment) { if (list) { list->add(key, value, comment); } else { set->add(key, value); } } bool strip; daf::base::PropertySet * set; daf::base::PropertyList * list; }; void MetadataIterationFunctor::operator()( std::string const & key, std::string const & value, std::string const & comment ) { static boost::regex const boolRegex("[tTfF]"); static boost::regex const intRegex("[+-]?[0-9]+"); static boost::regex const doubleRegex("[+-]?([0-9]*\\.?[0-9]+|[0-9]+\\.?[0-9]*)([eE][+-]?[0-9]+)?"); static boost::regex const fitsStringRegex("'(.*?) *'"); boost::smatch matchStrings; if (strip && isKeyIgnored(key)) { return; } std::istringstream converter(value); if (boost::regex_match(value, boolRegex)) { // convert the string to an bool add(key, bool(value == "T" || value == "t"), comment); } else if (boost::regex_match(value, intRegex)) { // convert the string to an int boost::int64_t val; converter >> val; if (val < (1LL << 31) && val > -(1LL << 31)) { add(key, static_cast(val), comment); } else { add(key, val, comment); } } else if (boost::regex_match(value, doubleRegex)) { // convert the string to a double double val; converter >> val; add(key, val, comment); } else if (boost::regex_match(value, matchStrings, fitsStringRegex)) { std::string const str = matchStrings[1].str(); // strip off the enclosing single quotes double val = stringToNonFiniteDouble(str); if (val != 0.0) { add(key, val, comment); } else { add(key, str, comment); }
    642 60b18593 + } else if (key == "HISTORY" || key == "COMMENT") {
    643 fb4d593b + add(key, comment, "");
    } else if (value.empty()) { // do nothing for empty values
    644 38dbacd9 - } else if (key == "HISTORY" ||
    645 38dbacd9 - (key == "COMMENT" &&
    646 38dbacd9 - comment != " FITS (Flexible Image Transport System) format is defined in 'Astronomy" &&
    647 38dbacd9 - comment != " and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H")) {
    648 38dbacd9 - if (list) {
    649 38dbacd9 - list->add(key, comment);
    650 38dbacd9 - } else {
    651 38dbacd9 - set->add(key, comment);
    652 38dbacd9 - }
    } else { throw LSST_EXCEPT( afw::fits::FitsError, (boost::format("Could not parse header value for key '%s': '%s'") % key % value).str() ); } } void writeKeyFromProperty( Fits & fits, daf::base::PropertySet const & metadata, std::string const & key, char const * comment=0 ) { std::type_info const & valueType = metadata.typeOf(key); if (valueType == typeid(bool)) { if (metadata.isArray(key)) { std::vector tmp = metadata.getArray(key); // work around unfortunate specialness of std::vector for (std::size_t i = 0; i != tmp.size(); ++i) { writeKeyImpl(fits, key.c_str(), static_cast(tmp[i]), comment); } } else { writeKeyImpl(fits, key.c_str(), metadata.get(key), comment); } } else if (valueType == typeid(int)) { if (metadata.isArray(key)) { std::vector tmp = metadata.getArray(key); for (std::size_t i = 0; i != tmp.size(); ++i) { writeKeyImpl(fits, key.c_str(), tmp[i], comment); } } else { writeKeyImpl(fits, key.c_str(), metadata.get(key), comment); } } else if (valueType == typeid(long)) { if (metadata.isArray(key)) { std::vector tmp = metadata.getArray(key); for (std::size_t i = 0; i != tmp.size(); ++i) { writeKeyImpl(fits, key.c_str(), tmp[i], comment); } } else { writeKeyImpl(fits, key.c_str(), metadata.get(key), comment); } } else if (valueType == typeid(long long)) { if (metadata.isArray(key)) { std::vector tmp = metadata.getArray(key); for (std::size_t i = 0; i != tmp.size(); ++i) { writeKeyImpl(fits, key.c_str(), tmp[i], comment); } } else { writeKeyImpl(fits, key.c_str(), metadata.get(key), comment); } } else if (valueType == typeid(boost::int64_t)) { if (metadata.isArray(key)) { std::vector tmp = metadata.getArray(key); for (std::size_t i = 0; i != tmp.size(); ++i) { writeKeyImpl(fits, key.c_str(), tmp[i], comment); } } else { writeKeyImpl(fits, key.c_str(), metadata.get(key), comment); } } else if (valueType == typeid(double)) { if (metadata.isArray(key)) { std::vector tmp = metadata.getArray(key); for (std::size_t i = 0; i != tmp.size(); ++i) { writeKeyImpl(fits, key.c_str(), tmp[i], comment); } } else { writeKeyImpl(fits, key.c_str(), metadata.get(key), comment); } } else if (valueType == typeid(std::string)) { if (metadata.isArray(key)) { std::vector tmp = metadata.getArray(key); for (std::size_t i = 0; i != tmp.size(); ++i) { writeKeyImpl(fits, key.c_str(), tmp[i], comment); } } else { writeKeyImpl(fits, key.c_str(), metadata.get(key), comment); } } else { // FIXME: inherited this error handling from fitsIo.cc; need a better option. pex::logging::Log::getDefaultLog().log( pex::logging::Log::WARN, makeErrorMessage( fits.fptr, fits.status, boost::format("In %s, unknown type '%s' for key '%s'.") % BOOST_CURRENT_FUNCTION % valueType.name() % key ) ); } if (fits.behavior & Fits::AUTO_CHECK) { LSST_FITS_CHECK_STATUS(fits, boost::format("Writing key '%s'") % key); } } } // anonymous void Fits::readMetadata(daf::base::PropertySet & metadata, bool strip) { MetadataIterationFunctor f; f.strip = strip; f.set = &metadata; f.list = dynamic_cast(&metadata); forEachKey(f); } void Fits::writeMetadata(daf::base::PropertySet const & metadata) { typedef std::vector NameList; daf::base::PropertyList const * pl = dynamic_cast(&metadata); NameList paramNames; if (pl) { paramNames = pl->getOrderedNames(); } else { paramNames = metadata.paramNames(false); } for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) { if (!isKeyIgnored(*i)) { if (pl) { writeKeyFromProperty(*this, metadata, *i, pl->getComment(*i).c_str()); } else { writeKeyFromProperty(*this, metadata, *i); } } } } // ---- Manipulating tables --------------------------------------------------------------------------------- void Fits::createTable() { char * ttype = 0; char * tform = 0; fits_create_tbl(reinterpret_cast(fptr), BINARY_TBL, 0, 0, &ttype, &tform, 0, 0, &status); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, "Creating binary table"); } } template int Fits::addColumn(std::string const & ttype, int size) { int nCols = 0; fits_get_num_cols( reinterpret_cast(fptr), &nCols, &status ); std::string tform = makeColumnFormat(size); fits_insert_col( reinterpret_cast(fptr), nCols + 1, const_cast(ttype.c_str()), const_cast(tform.c_str()), &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Adding column '%s' with size %d") % ttype % size); } return nCols; } template int Fits::addColumn(std::string const & ttype, int size, std::string const & comment) { int nCols = addColumn(ttype, size); updateColumnKey("TTYPE", nCols, ttype, comment); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Adding column '%s' with size %d") % ttype % size); } return nCols; } std::size_t Fits::addRows(std::size_t nRows) { long first = 0; fits_get_num_rows( reinterpret_cast(fptr), &first, &status ); fits_insert_rows( reinterpret_cast(fptr), first, nRows, &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Adding %d rows to binary table") % nRows); } return first; } std::size_t Fits::countRows() { long r = 0; fits_get_num_rows( reinterpret_cast(fptr), &r, &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, "Checking how many rows are in table"); } return r; } template void Fits::writeTableArray(std::size_t row, int col, int nElements, T const * value) { fits_write_col( reinterpret_cast(fptr), FitsTableType::CONSTANT, col + 1, row + 1, 1, nElements, const_cast(value), &status ); if (behavior & AUTO_CHECK) {
    854 5eb7d3cf + LSST_FITS_CHECK_STATUS(*this, boost::format("Writing value at table cell (%d, %d)") % row % col);
    861 82e9ef11 - LSST_FITS_CHECK_STATUS(
    862 82e9ef11 - *this,
    863 82e9ef11 - boost::format("Writing %d-element array at table cell (%d, %d)") % nElements % row % col
    864 82e9ef11 - );
    } } void Fits::writeTableScalar(std::size_t row, int col, std::string const & value) { // cfitsio doesn't let us specify the size of a string, it just looks for null terminator. // Using std::string::c_str() guarantees that we have one. But we can't store arbitrary // data in a string field because cfitsio will also chop off anything after the first null // terminator. char const * tmp = value.c_str(); fits_write_col( reinterpret_cast(fptr), TSTRING, col + 1, row + 1, 1, 1, const_cast(&tmp), &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Writing value at table cell (%d, %d)") % row % col); } } template void Fits::readTableArray(std::size_t row, int col, int nElements, T * value) { int anynul = false; fits_read_col( reinterpret_cast(fptr), FitsTableType::CONSTANT, col + 1, row + 1, 1, nElements, 0, value, &anynul, &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Reading value at table cell (%d, %d)") % row % col); } } void Fits::readTableScalar(std::size_t row, int col, std::string & value) { int anynul = false; long size = getTableArraySize(col); // We can't directly write into a std::string (may be changing in C++11). std::vector buf(size+1, 0); // cfitsio wants a char** because they imagine we might want an array of strings, // but we only want one element. char * tmp = &buf.front(); fits_read_col( reinterpret_cast(fptr), TSTRING, col + 1, row + 1, 1, 1, 0, &tmp, &anynul, &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Reading value at table cell (%d, %d)") % row % col); } value = std::string(tmp); } long Fits::getTableArraySize(int col) { int typecode = 0; long result = 0; long width = 0; fits_get_coltype( reinterpret_cast(fptr), col + 1, &typecode, &result, &width, &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Looking up array size for column %d") % col); } return result; } long Fits::getTableArraySize(std::size_t row, int col) { long result = 0; long offset = 0; fits_read_descript( reinterpret_cast(fptr), col + 1, row + 1, &result, &offset, &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Looking up array size for cell (%d, %d)") % row % col); } return result; } // ---- Manipulating images --------------------------------------------------------------------------------- void Fits::createEmpty() { long naxes = 0; fits_create_img(reinterpret_cast(fptr), 8, 0, &naxes, &status); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, "Creating empty image HDU"); } } template void Fits::createImageImpl(int naxis, long * naxes) { fits_create_img(reinterpret_cast(fptr), FitsBitPix::CONSTANT, naxis, naxes, &status); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, "Creating new image HDU"); } } template void Fits::writeImageImpl(T const * data, int nElements) { fits_write_img( reinterpret_cast(fptr), FitsType::CONSTANT, 1, nElements, const_cast(data), &status ); if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, "Writing image"); } } template void Fits::readImageImpl(int nAxis, T * data, long * begin, long * end, long * increment) { fits_read_subset( reinterpret_cast(fptr), FitsType::CONSTANT, begin, end, increment, 0, data, 0, &status ); if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Reading image"); } int Fits::getImageDim() { int nAxis = 0; fits_get_img_dim(reinterpret_cast(fptr), &nAxis, &status); if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting NAXIS"); return nAxis; } void Fits::getImageShapeImpl(int nAxis, long * nAxes) { fits_get_img_size(reinterpret_cast(fptr), nAxis, nAxes, &status); if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting NAXES"); } template bool Fits::checkImageType() { int bitpix = 0; fits_get_img_equivtype(reinterpret_cast(fptr), &bitpix, &status); if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting image type"); return bitpix == FitsBitPix::CONSTANT; } // ---- Manipulating files ---------------------------------------------------------------------------------- Fits::Fits(std::string const & filename, std::string const & mode, int behavior_) : fptr(0), status(0), behavior(behavior_) { if (mode == "r" || mode == "rb") { fits_open_file( reinterpret_cast(&fptr), const_cast(filename.c_str()), READONLY, &status ); } else if (mode == "w" || mode == "wb") { boost::filesystem::remove(filename); // cfitsio doesn't like over-writing files fits_create_file( reinterpret_cast(&fptr), const_cast(filename.c_str()), &status ); } else if (mode == "a" || mode == "ab") { fits_open_file( reinterpret_cast(&fptr), const_cast(filename.c_str()), READWRITE, &status ); int nHdu = 0; fits_get_num_hdus(reinterpret_cast(fptr), &nHdu, &status); fits_movabs_hdu(reinterpret_cast(fptr), nHdu, NULL, &status); if ((behavior & AUTO_CHECK) && (behavior & AUTO_CLOSE) && (status) && (fptr)) { // We're about to throw an exception, and the destructor won't get called // because we're in the constructor, so cleanup here first. int tmpStatus = 0; fits_close_file(reinterpret_cast(fptr), &tmpStatus); } } else { throw LSST_EXCEPT( FitsError, (boost::format("Invalid mode '%s' given when opening file '%s'") % mode % filename).str() ); } if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS(*this, boost::format("Opening file '%s' with mode '%s'") % filename % mode); } } Fits::Fits(MemFileManager & manager, std::string const & mode, int behavior_) : fptr(0), status(0), behavior(behavior_) { typedef void * (*Reallocator)(void *, std::size_t); // It's a shame this logic is essentially a duplicate of above, but the innards are different enough // we can't really reuse it. if (mode == "r" || mode == "rb") { fits_open_memfile( reinterpret_cast(&fptr), "unused", READONLY, &manager._ptr, &manager._len, 0, 0, // no reallocator or deltasize necessary for READONLY &status ); } else if (mode == "w" || mode == "wb") {
    1084 1f3aeb26 + if (!manager._ptr) manager.reset(2880);
    Reallocator reallocator = 0; if (manager._managed) reallocator = &std::realloc; fits_create_memfile( reinterpret_cast(&fptr), &manager._ptr, &manager._len, 0, reallocator, // use default deltasize &status ); } else if (mode == "a" || mode == "ab") { Reallocator reallocator = 0; if (manager._managed) reallocator = &std::realloc; fits_open_memfile( reinterpret_cast(&fptr), "unused", READWRITE, &manager._ptr, &manager._len, 0, reallocator, &status ); int nHdu = 0; fits_get_num_hdus(reinterpret_cast(fptr), &nHdu, &status); fits_movabs_hdu(reinterpret_cast(fptr), nHdu, NULL, &status); if ((behavior & AUTO_CHECK) && (behavior & AUTO_CLOSE) && (status) && (fptr)) { // We're about to throw an exception, and the destructor won't get called // because we're in the constructor, so cleanup here first. int tmpStatus = 0; fits_close_file(reinterpret_cast(fptr), &tmpStatus); } } else { throw LSST_EXCEPT( FitsError, (boost::format("Invalid mode '%s' given when opening memory file at '%s'") % mode % manager._ptr).str() ); } if (behavior & AUTO_CHECK) { LSST_FITS_CHECK_STATUS( *this, boost::format("Opening memory file at '%s' with mode '%s'") % manager._ptr % mode ); } } void Fits::closeFile() { fits_close_file(reinterpret_cast(fptr), &status); } #define INSTANTIATE_KEY_OPS(r, data, T) \ template void Fits::updateKey(std::string const &, T const &, std::string const &); \ template void Fits::writeKey(std::string const &, T const &, std::string const &); \ template void Fits::updateKey(std::string const &, T const &); \ template void Fits::writeKey(std::string const &, T const &); \ template void Fits::updateColumnKey(std::string const &, int, T const &, std::string const &); \ template void Fits::writeColumnKey(std::string const &, int, T const &, std::string const &); \ template void Fits::updateColumnKey(std::string const &, int, T const &); \ template void Fits::writeColumnKey(std::string const &, int, T const &); \ template void Fits::readKey(std::string const &, T &); #define INSTANTIATE_IMAGE_OPS(r, data, T) \ template void Fits::createImageImpl(int, long *); \ template void Fits::writeImageImpl(T const *, int); \ template void Fits::readImageImpl(int, T *, long *, long *, long *); \ template bool Fits::checkImageType(); \ template int getBitPix(); #define INSTANTIATE_TABLE_OPS(r, data, T) \ template int Fits::addColumn(std::string const & ttype, int size); \ template int Fits::addColumn(std::string const & ttype, int size, std::string const & comment); #define INSTANTIATE_TABLE_ARRAY_OPS(r, data, T) \ template void Fits::writeTableArray(std::size_t row, int col, int nElements, T const * value); \ template void Fits::readTableArray(std::size_t row, int col, int nElements, T * value); // ---------------------------------------------------------------------------------------------------------- // ---- Explicit instantiation ------------------------------------------------------------------------------ // ---------------------------------------------------------------------------------------------------------- #define KEY_TYPES \ (bool)(unsigned char)(short)(unsigned short)(int)(unsigned int)(long)(unsigned long)(LONGLONG) \ (float)(double)(std::complex)(std::complex)(std::string) #define COLUMN_TYPES \ (bool)(std::string)(boost::uint8_t)(boost::int16_t)(boost::uint16_t)(boost::int32_t)(boost::uint32_t) \ (boost::int64_t)(float)(double)(lsst::afw::geom::Angle)(std::complex)(std::complex) #define COLUMN_ARRAY_TYPES \ (bool)(char)(boost::uint8_t)(boost::int16_t)(boost::uint16_t)(boost::int32_t)(boost::uint32_t) \ (boost::int64_t)(float)(double)(lsst::afw::geom::Angle)(std::complex)(std::complex) #define IMAGE_TYPES \ (unsigned char)(short)(unsigned short)(int)(unsigned int)(boost::int64_t)(boost::uint64_t) \ (float)(double) BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_KEY_OPS, _, KEY_TYPES) BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_TABLE_OPS, _, COLUMN_TYPES) BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_TABLE_ARRAY_OPS, _, COLUMN_ARRAY_TYPES) BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_IMAGE_OPS, _, IMAGE_TYPES) }}} // namespace lsst::afw::fits

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    e182e1df

    commit e182e1df9a546133371923ff8f98881bc532b5c9
    Author: Jim Bosch 
    Date:   Tue Dec 30 05:40:30 2014 +0900
    
        Use 64-bit heap space in FITS writing (extension, not standard)
    

    c547845f

    commit c547845f46bda352e2ea44dc4155f20884ec3e12
    Author: Jim Bosch 
    Date:   Tue Feb 7 20:51:30 2012 -0500
    
        more support for long strings in FITS; needed to workaround lack of cfitsio support in fits_read_keyn
    

    38dbacd9

    commit 38dbacd955611d624757bc42fb0dcc275209b7ac
    Author: Jim Bosch 
    Date:   Wed Feb 8 16:49:20 2012 -0500
    
        copied FITS<->PropertySet/List code out of afw/image into afw/Fits, cleaned it up a bit.  Haven't removed original code or tested yet.
    

    82e9ef11

    commit 82e9ef116bd629d6f7ccaacf5ef99eb288871b47
    Author: Jim Bosch 
    Date:   Thu Dec 25 10:18:47 2014 -0500
    
        Slightly better error messages when CFITSIO fails to write table value
    

    Commits in /Users/nate/repos_lsst/afw/

    5eb7d3cf

    commit 5eb7d3cf2b1740a40da1d507a07e03641ab8ecf2
    Author: Jim Bosch 
    Date:   Sat Feb 25 16:13:10 2012 -0500
    
        cherry-pick of 040138; second of several to improve FITS table I/O without merging all of #1898 yet
    

    2c60faef

    commit 2c60faef19c9bd7d845eb593f1bf0d5188349d93
    Author: Russell Owen 
    Date:   Mon Oct 6 11:11:09 2014 -0700
    
        Fix a compiler warning by changing !foo(...) == 0 to foo(...) != 0
    

    1f3aeb26

    commit 1f3aeb26976b3b4d70f83ea828e8d1c62ca43fc5
    Author: Jim Bosch 
    Date:   Sat Feb 25 16:11:45 2012 -0500
    
        cherry-pick (not quite automatic) of 057928; first of several to improve table FITS support without merging all the image FITS changes
    

    fb4d593b

    commit fb4d593b278b7823830a6e9692c7ea7e5395610c
    Author: John Gates 
    Date:   Wed Dec 10 13:51:20 2014 -0600
    
        Fixed indentation.
    

    60b18593

    commit 60b18593706abdf28207f67e2f15328d573fd482
    Author: John Gates 
    Date:   Wed Dec 10 13:44:20 2014 -0600
    
        Changed readMetadata to record COMMENT and HISTORY FITS cards.
    

    e6936b03

    commit e6936b03dd13f22b3844ee5adc600a473206d461
    Author: Jim Bosch 
    Date:   Tue Jan 10 17:50:51 2012 -0500
    
        implemented and tests FITS serialization of Source footprints
    

    Return to list

    src/math/detail/cudaLanczosWrapper.cc

    Diff:

                    // -*- LSST-C++ -*- // fixed format comment for emacs
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008 - 2012 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * \file
                     *
                     * \ingroup afw
                     *
                     * \brief GPU image warping implementation
                     *
                     * \author Kresimir Cosic.
                     */
                    
                    #ifdef GPU_BUILD
                    #include 
                    #include 
                    #endif
                    
                    #include "lsst/afw/geom/Box.h"
                    
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/warpExposure.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/image/Wcs.h"
                    
                    #include "lsst/afw/gpu/GpuExceptions.h"
                    #include "lsst/afw/gpu/IsGpuBuild.h"
                    #include "lsst/afw/gpu/detail/GpuBuffer2D.h"
                    #include "lsst/afw/gpu/detail/CudaMemory.h"
                    #include "lsst/afw/gpu/detail/CudaSelectGpu.h"
                    
                    #include "lsst/afw/math/detail/CudaLanczos.h"
                    #include "lsst/afw/math/detail/CudaLanczosWrapper.h"
                    
                    using namespace std;
                    using lsst::afw::math::detail::gpu::SPoint2;
                    using lsst::afw::math::detail::gpu::SVec2;
                    using lsst::afw::math::detail::gpu::SBox2I;
                    
                    
                    namespace mathDetail = lsst::afw::math::detail;
                    namespace gpuDetail = lsst::afw::gpu::detail;
                    namespace afwMath = lsst::afw::math;
                    namespace afwGpu = lsst::afw::gpu;
                    namespace afwImage = lsst::afw::image;
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace pexLog = lsst::pex::logging;
                    namespace afwGeom = lsst::afw::geom;
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    namespace detail {
                    
                    namespace {
                    
                    int CeilDivide(int num, int divisor)
                    {
                        return (num + divisor - 1) / divisor;
                    }
                    
                    // get the number of interpolation blocks given an image dimension
                    int InterpBlkN(int size , int interpLength)
                    {
                        return CeilDivide(size , interpLength) + 1;
                    }
                    
                    // calculate the interpolated value given the data for linear interpolation
                    gpu::SPoint2 GetInterpolatedValue(afwGpu::detail::GpuBuffer2D const & interpBuf,
                                                      int blkX, int blkY, int subX, int subY
                                                     )
                    {
                        gpu::BilinearInterp interp = interpBuf.Pixel(blkX, blkY);
                        return interp.Interpolate(subX, subY);
                    }
                    
                    // calculate the interpolated value given the data for linear interpolation
                    gpu::SPoint2 GetInterpolatedValue(afwGpu::detail::GpuBuffer2D const & interpBuf,
                                                      int interpLen, int x, int y
                                                     )
                    {
                        int blkX = x / interpLen;
                        int blkY = y / interpLen;
                    
                        int subX = x % interpLen;
                        int subY = y % interpLen;
                    
                        return GetInterpolatedValue(interpBuf, blkX, blkY, subX, subY);
                    }
                    
                    // calculate the number of points falling within the srcGoodBox,
                    // given a bilinearily interpolated coordinate transform function on integer range [0,width> x [0, height>
                    int NumGoodPixels(afwGpu::detail::GpuBuffer2D const & interpBuf,
                                      int const interpLen, int const width, int const height, SBox2I srcGoodBox)
                    {
                        int cnt = 0;
                    
                        int subY = 1, blkY = 0;
                        for (int row = 0; row < height; row++, subY++) {
                            if (subY >= interpLen) {
                                subY -= interpLen;
                                blkY++;
                            }
                    
                            int subX = 1, blkX = 0;
                            gpu::BilinearInterp interp = interpBuf.Pixel(blkX, blkY);
                            gpu::LinearInterp lineY = interp.GetLinearInterp(subY);
                    
                            for (int col = 0; col < width; col++, subX++) {
                                if (subX >= interpLen) {
                                    subX -= interpLen;
                                    blkX++;
                                    interp = interpBuf.Pixel(blkX, blkY);
                                    lineY = interp.GetLinearInterp(subY);
                                }
                                gpu::SPoint2 srcPos = lineY.Interpolate(subX);
                                if (srcGoodBox.isInsideBox(srcPos)) {
                                    cnt++;
                                }
                            }
                        }
                        return cnt;
                    }
                    
                    #ifdef GPU_BUILD
                    // for (plain) Image::
                    // allocate CPU and GPU buffers, transfer data and call GPU kernel proxy
                    // precondition: order*2 < gpu::SIZE_MAX_WARPING_KERNEL
                    template< typename DestPixelT, typename SrcPixelT>
                    int WarpImageGpuWrapper(
                        afwImage::Image     &destImage,
                        afwImage::Image const &srcImage,
                        int mainKernelSize,
                        gpu::KernelType maskKernelType,
                        int maskKernelSize,
                        const lsst::afw::geom::Box2I srcBox,
                        lsst::afw::gpu::detail::GpuBuffer2D const& srcPosInterp,
                        int const interpLength,
                        typename afwImage::Image::SinglePixel padValue
                    )
                    {
                        typedef typename afwImage::Image DestImageT;
                    
                        typename DestImageT::SinglePixel const edgePixel = padValue;
                    
                        gpu::PixelIVM edgePixelGpu;
                        edgePixelGpu.img = edgePixel;
                        edgePixelGpu.var = -1;
                        edgePixelGpu.msk = -1;
                    
                        int const destWidth = destImage.getWidth();
                        int const destHeight = destImage.getHeight();
                        gpuDetail::GpuMemOwner destBufImgGpu;
                        gpuDetail::GpuMemOwner srcBufImgGpu;
                        gpuDetail::GpuMemOwner srcPosInterpGpu;
                    
                        gpu::ImageDataPtr destImgGpu;
                        destImgGpu.strideImg = destBufImgGpu.AllocImageBaseBuffer(destImage);
                        if (destBufImgGpu.ptr == NULL)  {
    
    182 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuMemoryException, "Not enough memory on GPU for output image");
    ? ^^^^^^ ^
    182 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError, "Not enough memory on GPU for output image");
    ? ^^ ^ } destImgGpu.img = destBufImgGpu.ptr; destImgGpu.var = NULL; destImgGpu.msk = NULL; destImgGpu.width = destWidth; destImgGpu.height = destHeight; gpu::ImageDataPtr srcImgGpu; srcImgGpu.strideImg = srcBufImgGpu.TransferFromImageBase(srcImage); if (srcBufImgGpu.ptr == NULL) {
    193 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuMemoryException, "Not enough memory on GPU for input image");
    ? ^^^^^^ ^
    193 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError, "Not enough memory on GPU for input image");
    ? ^^ ^ } srcImgGpu.img = srcBufImgGpu.ptr; srcImgGpu.var = NULL; srcImgGpu.msk = NULL; srcImgGpu.width = srcImage.getWidth(); srcImgGpu.height = srcImage.getHeight(); srcPosInterpGpu.Transfer(srcPosInterp); if (srcPosInterpGpu.ptr == NULL) {
    203 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuMemoryException,
    ? ^^^^^^ ^
    203 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError,
    ? ^^ ^ "Not enough memory on GPU for interpolation data for coorinate transformation"); } SBox2I srcBoxConv(srcBox.getMinX(), srcBox.getMinY(), srcBox.getMaxX() + 1, srcBox.getMaxY() + 1); WarpImageGpuCallKernel(false, destImgGpu, srcImgGpu, mainKernelSize, maskKernelType, maskKernelSize, srcBoxConv, edgePixelGpu, srcPosInterpGpu.ptr, interpLength ); int numGoodPixels = NumGoodPixels(srcPosInterp, interpLength, destWidth, destHeight, srcBoxConv); cudaThreadSynchronize(); if (cudaGetLastError() != cudaSuccess) {
    223 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    223 21597d88 + throw LSST_EXCEPT(afwGpu::GpuRuntimeError, "GPU calculation failed to run");
    } destBufImgGpu.CopyToImageBase(destImage); return numGoodPixels; } // for MaskedImage:: // allocate CPU and GPU buffers, transfer data and call GPU kernel proxy // precondition: order*2 < gpu::SIZE_MAX_WARPING_KERNEL template< typename DestPixelT, typename SrcPixelT> int WarpImageGpuWrapper( afwImage::MaskedImage &dstImage, afwImage::MaskedImageconst &srcImage, int mainKernelSize, gpu::KernelType maskKernelType, int maskKernelSize, const lsst::afw::geom::Box2I srcBox, lsst::afw::gpu::detail::GpuBuffer2D const& srcPosInterp, int const interpLength, typename afwImage::MaskedImage::SinglePixel padValue ) { typedef typename afwImage::MaskedImage DestImageT; typename DestImageT::SinglePixel const edgePixel = padValue; gpu::PixelIVM edgePixelGpu; edgePixelGpu.img = edgePixel.image(); edgePixelGpu.var = edgePixel.variance(); edgePixelGpu.msk = edgePixel.mask(); int const destWidth = dstImage.getWidth(); int const destHeight = dstImage.getHeight(); gpuDetail::GpuMemOwner destBufImgGpu; gpuDetail::GpuMemOwner destBufVarGpu; gpuDetail::GpuMemOwner destBufMskGpu; gpuDetail::GpuMemOwner srcBufImgGpu; gpuDetail::GpuMemOwner srcBufVarGpu; gpuDetail::GpuMemOwner srcBufMskGpu; gpuDetail::GpuMemOwner srcPosInterpGpu; mathDetail::gpu::ImageDataPtr destImgGpu; destImgGpu.strideImg = destBufImgGpu.AllocImageBaseBuffer(*dstImage.getImage()); destImgGpu.strideVar = destBufVarGpu.AllocImageBaseBuffer(*dstImage.getVariance()); destImgGpu.strideMsk = destBufMskGpu.AllocImageBaseBuffer(*dstImage.getMask()); if (destBufImgGpu.ptr == NULL) {
    273 9a2fd573 - throw LSST_EXCEPT(afwGpu::GpuMemoryException, "Not enough memory on GPU for output image");
    ? ^^^^^^ ^
    273 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError, "Not enough memory on GPU for output image");
    ? ^^ ^ } if (destBufVarGpu.ptr == NULL) {
    276 9a2fd573 - throw LSST_EXCEPT(afwGpu::GpuMemoryException, "Not enough memory on GPU for output variance");
    ? ^^^^^^ ^
    276 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError, "Not enough memory on GPU for output variance");
    ? ^^ ^ } if (destBufMskGpu.ptr == NULL) {
    279 9a2fd573 - throw LSST_EXCEPT(afwGpu::GpuMemoryException, "Not enough memory on GPU for output mask");
    ? ^^^^^^ ^
    279 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError, "Not enough memory on GPU for output mask");
    ? ^^ ^ } destImgGpu.img = destBufImgGpu.ptr; destImgGpu.var = destBufVarGpu.ptr; destImgGpu.msk = destBufMskGpu.ptr; destImgGpu.width = destWidth; destImgGpu.height = destHeight; gpu::ImageDataPtr srcImgGpu; srcImgGpu.strideImg = srcBufImgGpu.TransferFromImageBase(*srcImage.getImage()); if (srcBufImgGpu.ptr == NULL) {
    290 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuMemoryException, "Not enough memory on GPU for input image");
    ? ^^^^^^ ^
    290 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError, "Not enough memory on GPU for input image");
    ? ^^ ^ } srcImgGpu.strideVar = srcBufVarGpu.TransferFromImageBase(*srcImage.getVariance()); if (srcBufVarGpu.ptr == NULL) {
    294 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuMemoryException, "Not enough memory on GPU for input variance");
    ? ^^^^^^ ^
    294 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError, "Not enough memory on GPU for input variance");
    ? ^^ ^ } srcImgGpu.strideMsk = srcBufMskGpu.TransferFromImageBase(*srcImage.getMask()); if (srcBufMskGpu.ptr == NULL) {
    298 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuMemoryException, "Not enough memory on GPU for input mask");
    ? ^^^^^^ ^
    298 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError, "Not enough memory on GPU for input mask");
    ? ^^ ^ } srcImgGpu.img = srcBufImgGpu.ptr; srcImgGpu.var = srcBufVarGpu.ptr; srcImgGpu.msk = srcBufMskGpu.ptr; srcImgGpu.width = srcImage.getWidth(); srcImgGpu.height = srcImage.getHeight(); srcPosInterpGpu.Transfer(srcPosInterp); if (srcPosInterpGpu.ptr == NULL) {
    309 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuMemoryException,
    ? ^^^^^^ ^
    309 21597d88 + throw LSST_EXCEPT(afwGpu::GpuMemoryError,
    ? ^^ ^ "Not enough memory on GPU for interpolation data for coorinate transformation"); } SBox2I srcBoxConv(srcBox.getMinX(), srcBox.getMinY(), srcBox.getMaxX() + 1, srcBox.getMaxY() + 1); WarpImageGpuCallKernel(true, destImgGpu, srcImgGpu, mainKernelSize, maskKernelType, maskKernelSize, srcBoxConv, edgePixelGpu, srcPosInterpGpu.ptr, interpLength ); int numGoodPixels = NumGoodPixels(srcPosInterp, interpLength, destWidth, destHeight, srcBoxConv); cudaThreadSynchronize(); if (cudaGetLastError() != cudaSuccess) {
    328 5997ef64 - throw LSST_EXCEPT(afwGpu::GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    328 21597d88 + throw LSST_EXCEPT(afwGpu::GpuRuntimeError, "GPU calculation failed to run");
    } destBufImgGpu.CopyToImageBase(*dstImage.getImage()); destBufVarGpu.CopyToImageBase(*dstImage.getVariance()); destBufMskGpu.CopyToImageBase(*dstImage.getMask()); return numGoodPixels; } #endif //GPU_BUILD // Calculate bilinear interpolation data based on given function values // input: // srcPosInterp - contains values of original function at a mesh of equally distanced points // the values are stored in .o member // interpLength - distance between points // destWidth, destHeight - size of function domain // output: // srcPosInterp - all members are calculated and set, ready to calculate interpolation values void CalculateInterpolationData(gpuDetail::GpuBuffer2D& srcPosInterp, int interpLength, int destWidth, int destHeight) { int const interpBlkNX = InterpBlkN(destWidth , interpLength); int const interpBlkNY = InterpBlkN(destHeight, interpLength); for (int row = -1, rowBand = 0; rowBand < interpBlkNY - 1; row += interpLength, rowBand++) { double const invInterpLen = 1.0 / interpLength; double const invInterpLenRow = row + interpLength <= destHeight - 1 ? invInterpLen : 1.0 / (destHeight - 1 - row); for (int col = -1, colBand = 0; colBand < interpBlkNX - 1; col += interpLength, colBand++) { const SPoint2 p11 = srcPosInterp.Pixel(colBand , rowBand ).o; const SPoint2 p12 = srcPosInterp.Pixel(colBand + 1, rowBand ).o; const SPoint2 p21 = srcPosInterp.Pixel(colBand , rowBand + 1).o; const SPoint2 p22 = srcPosInterp.Pixel(colBand + 1, rowBand + 1).o; const SVec2 band_dY = SVec2(p11, p21); const SVec2 band_d0X = SVec2(p11, p12); const SVec2 band_d1X = SVec2(p21, p22); const SVec2 band_ddX = VecMul( VecSub(band_d1X, band_d0X), invInterpLenRow); double const invInterpLenCol = col + interpLength <= destWidth - 1 ? invInterpLen : 1.0 / (destWidth - 1 - col); gpu::BilinearInterp lin = srcPosInterp.Pixel(colBand, rowBand); //sets lin.o lin.deltaY = VecMul(band_dY , invInterpLenRow); lin.d0X = VecMul(band_d0X, invInterpLenCol); lin.ddX = VecMul(band_ddX, invInterpLenCol); srcPosInterp.Pixel(colBand, rowBand) = lin; // partially fill the last column and row, too if (colBand == interpBlkNX - 2) { srcPosInterp.Pixel(interpBlkNX - 1, rowBand).deltaY = VecMul( SVec2(p12, p22), invInterpLenRow); } if (rowBand == interpBlkNY - 2) { srcPosInterp.Pixel(colBand, interpBlkNY - 1).d0X = VecMul( SVec2(p21, p22), invInterpLenCol); } } } } } //local namespace ends // a part of public interface, see header file for description template std::pair warpImageGPU( DestImageT &destImage, ///< remapped %image SrcImageT const &srcImage, ///< source %image afwMath::LanczosWarpingKernel const &lanczosKernel, ///< warping kernel lsst::afw::math::SeparableKernel const &maskWarpingKernel, ///< mask warping kernel
    400 c31ebcf9 - SrcPosFunctor const &computeSrcPos, ///< Functor to compute source position
    ? ---
    400 624db730 + PositionFunctor const &computeSrcPos, ///< Functor to compute source position
    ? +++++ int const interpLength, ///< Distance over which WCS can be linearily interpolated, must be >0 typename DestImageT::SinglePixel padValue, ///< value to use for undefined pixels const bool forceProcessing ) { if (interpLength < 1) {
    407 57a66130 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    407 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ "GPU accelerated warping must use interpolation"); } int const srcWidth = srcImage.getWidth(); int const srcHeight = srcImage.getHeight(); pexLog::TTrace<3>("lsst.afw.math.warp", "(GPU) source image width=%d; height=%d", srcWidth, srcHeight); if (!lsst::afw::gpu::isGpuBuild()) {
    416 805a6f1f - throw LSST_EXCEPT(afwGpu::GpuRuntimeErrorException, "Afw not compiled with GPU support");
    ? ---------
    416 21597d88 + throw LSST_EXCEPT(afwGpu::GpuRuntimeError, "Afw not compiled with GPU support");
    } #ifdef GPU_BUILD gpu::KernelType maskKernelType; { if (dynamic_cast(&maskWarpingKernel)) { maskKernelType = gpu::KERNEL_TYPE_LANCZOS; } else if (dynamic_cast(&maskWarpingKernel)) { maskKernelType = gpu::KERNEL_TYPE_BILINEAR; } else if (dynamic_cast(&maskWarpingKernel)) { maskKernelType = gpu::KERNEL_TYPE_NEAREST_NEIGHBOR; } else {
    429 7808d2ad - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "unknown type of mask warping kernel");
    ? ^^^^^^ ^
    429 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "unknown type of mask warping kernel");
    ? ^^ ^ } } #endif if (gpuDetail::TryToSelectCudaDevice(!forceProcessing) == false) { return std::pair(-1, WarpImageGpuStatus::NO_GPU); } int const mainKernelSize = 2 * lanczosKernel.getOrder(); //do not process if the kernel is too large for allocated GPU local memory if (mainKernelSize * 2 > gpu::SIZE_MAX_WARPING_KERNEL) { return std::pair(-1, WarpImageGpuStatus::KERNEL_TOO_LARGE); } //do not process if the interpolation data is too large to make any speed gains if (!forceProcessing && interpLength < 3) { return std::pair(-1, WarpImageGpuStatus::INTERP_LEN_TOO_SMALL); } int const destWidth = destImage.getWidth(); int const destHeight = destImage.getHeight(); pexLog::TTrace<3>("lsst.afw.math.warp", "(GPU) remap image width=%d; height=%d", destWidth, destHeight); int const maxCol = destWidth - 1; int const maxRow = destHeight - 1;
    455 57a66130 -
    456 57a66130 - typedef typename DestImageT::SinglePixel DestPixelT;
    457 57a66130 - typedef typename SrcImageT::SinglePixel SrcPixelT;
    #ifdef GPU_BUILD // Compute borders; use to prevent applying kernel outside of srcImage afwGeom::Box2I srcGoodBBox = lanczosKernel.shrinkBBox(srcImage.getBBox(afwImage::LOCAL)); #endif int const interpBlkNX = InterpBlkN(destWidth , interpLength); int const interpBlkNY = InterpBlkN(destHeight, interpLength); //GPU kernel input, will contain: for each interpolation block, all interpolation parameters gpuDetail::GpuBuffer2D srcPosInterp(interpBlkNX, interpBlkNY); // calculate values of coordinate transform function for (int rowBand = 0; rowBand < interpBlkNY; rowBand++) { int row = min(maxRow, (rowBand * interpLength - 1)); for (int colBand = 0; colBand < interpBlkNX; colBand++) { int col = min(maxCol, (colBand * interpLength - 1)); afwGeom::Point2D srcPos = computeSrcPos(col, row); SPoint2 sSrcPos(srcPos); sSrcPos = MovePoint(sSrcPos, SVec2(-srcImage.getX0(), -srcImage.getY0())); srcPosInterp.Pixel(colBand, rowBand).o = sSrcPos; } } CalculateInterpolationData(/*in,out*/srcPosInterp, interpLength, destWidth, destHeight); int numGoodPixels = 0; pexLog::TTrace<3>("lsst.afw.math.warp", "using GPU acceleration, remapping masked image"); #ifdef GPU_BUILD int maskKernelSize; if (maskKernelType == gpu::KERNEL_TYPE_LANCZOS) { maskKernelSize = 2 * dynamic_cast(&maskWarpingKernel)->getOrder(); } else { maskKernelSize = 2; } numGoodPixels = WarpImageGpuWrapper(destImage, srcImage, mainKernelSize, maskKernelType, maskKernelSize, srcGoodBBox, srcPosInterp, interpLength, padValue ); #endif return std::pair(numGoodPixels, WarpImageGpuStatus::OK); } // // Explicit instantiations // /// \cond #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage #define IMAGE(PIXTYPE) afwImage::Image #define NL /* */ #define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT) \ template std::pair warpImageGPU( \ IMAGE(DESTIMAGEPIXELT) &destImage, \ IMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwMath::LanczosWarpingKernel const &warpingKernel, \ afwMath::SeparableKernel const &maskWarpingKernel, \
    520 c31ebcf9 - SrcPosFunctor const &computeSrcPos, \
    ? ---
    517 624db730 + PositionFunctor const &computeSrcPos, \
    ? +++++ int const interpLength, \ IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue, \ const bool forceProcessing); NL \ template std::pair warpImageGPU( \ MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \ MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwMath::LanczosWarpingKernel const &warpingKernel, \ afwMath::SeparableKernel const &maskWarpingKernel, \
    529 c31ebcf9 - SrcPosFunctor const &computeSrcPos, \
    ? ---
    526 624db730 + PositionFunctor const &computeSrcPos, \
    ? +++++ int const interpLength, \ MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue, \ const bool forceProcessing); INSTANTIATE(double, double) INSTANTIATE(double, float) INSTANTIATE(double, int) INSTANTIATE(double, boost::uint16_t) INSTANTIATE(float, float) INSTANTIATE(float, int) INSTANTIATE(float, boost::uint16_t) INSTANTIATE(int, int) INSTANTIATE(boost::uint16_t, boost::uint16_t) /// \endcond } } } } //namespace lsst::afw::math::detail ends

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    c31ebcf9

    commit c31ebcf91bbcbc4de7a046a83af1ac3f3da22545
    Merge: 46325ba 8e1872d
    Author: Kresimir Cosic 
    Date:   Sat Mar 3 10:10:28 2012 +0100
    
        Fixed conflicts, adapted to changes
    

    9a2fd573

    commit 9a2fd573c49c4a438433348aaecef2eb3a6f18e4
    Author: Kresimir Cosic 
    Date:   Sat Sep 1 16:40:59 2012 +0200
    
        GPU warping: A small fix of error messages text.
    

    5997ef64

    commit 5997ef64b7efeb2f97777cab13e4e5399b4b5d4e
    Author: Kresimir Cosic 
    Date:   Mon Feb 27 04:48:01 2012 +0100
    
        Beautified source code
    

    805a6f1f

    commit 805a6f1fae226747c7f56a01bb128059251886d7
    Author: Kresimir Cosic 
    Date:   Wed Jul 18 02:28:16 2012 +0200
    
        Idented source files. Warping control object can now accept GPU acceleration with mask kernels
    

    57a66130

    commit 57a661302306aa3cbb7ba8c159187b5c2d063d23
    Author: Kresimir Cosic 
    Date:   Mon Feb 13 18:35:19 2012 +0100
    
        GPU warping works, but related python tests segfault on exit
    

    7808d2ad

    commit 7808d2ad566372eb3f94f73e05969f5b585e015e
    Author: Kresimir Cosic 
    Date:   Wed Jul 18 01:13:52 2012 +0200
    
        Initial version which implements most of the required behavior.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    624db730

    commit 624db730b18aee1cfa2bed9d4b6c64a67da00a26
    Author: Steven Bickerton 
    Date:   Tue Feb 18 18:24:47 2014 +0900
    
        renamed SrcPosFunctor -> PositionFunctor
    

    Return to list

    python/lsst/afw/coord/observatory.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    %{
    
    27 d304da93 - #include "lsst/afw/coord/Utils.h"
    #include "lsst/afw/coord/Observatory.h" %}
    31 d304da93 - %include "lsst/afw/coord/Utils.h"
    30 4d62652f + %useValueEquality(lsst::afw::coord::Observatory);
    31 4d62652f +
    %include "lsst/afw/coord/Observatory.h"
    34 4d62652f + %addStreamRepr(lsst::afw::coord::Observatory);

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d304da93

    commit d304da93ccf6b9879ea8a52bd737816b61d5eca6
    Author: bick 
    Date:   Thu Mar 11 23:55:19 2010 +0000
    
        Added point3d.
    

    Commits in /Users/nate/repos_lsst/afw/

    4d62652f

    commit 4d62652fa86a1c53d99c71ca845d3ea3af63565f
    Author: Russell Owen 
    Date:   Wed Apr 22 16:57:18 2015 -0700
    
        Improved string representations of Coords
        
        Improved os << Coord (in C++) and Coord.__str__ and __repr__ in Python
        for Coord and all subclasses, as follows:
        - The coordinate system is shown, even for clones (without the need to cast)
        - Positions are in degrees, instead of radians
        - IcrsCoord and GalacticCoord do not show the epoch
        - TopocentricCoord now has string representations, and the data includes Observatory
        - Coord.__str__ now uses C++ os << Coord, for simplicity and uniformity
        - Coord.__repr__ shows numbers (except observatory to full precision
          (except for observatory data for TopocentricCoord, since it didn't seem worth the extra clutter).
        - Coord.__repr__ omits the leading "afwCoord."
        
        Note: I would prefer to make Coord.__repr__ the same as __str__
        but it was more detailed so I left that feature.
        
        Make Coord.__str__ use << and add observatory information for topo
    

    Return to list

    src/math/detail/convCpuGpuShared.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * @file
                     *
                     * @brief Contains AssertDimensionsOK function
                     *
                     * @author Kresimir Cosic
                     * @author Original code by Russell Owen
                     *
                     * @note Extraction to this file requested by RHL during code review
                     *
                     * @ingroup afw
                     */
                    
                    #include "boost/cstdint.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/detail/Convolve.h"
                    #include "lsst/afw/math/detail/ConvCpuGpuShared.h"
                    
                    namespace afwImage = lsst::afw::image;
                    namespace mathDetail = lsst::afw::math::detail;
                    
                    /*
                     * Assert that the dimensions of convolvedImage, inImage and kernel are compatible with convolution.
                     *
    
    52 d1596c6d - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dim.
    ? ^^^^^^ ^
    52 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dim.
    ? ^^ ^
    53 d1596c6d - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or h.
    ? ^^^^^^ ^
    53 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or h.
    ? ^^ ^
    54 d1596c6d - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    54 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^ * * @note Same as assertDimensionsOK in basicConvolve.cc, copy-pasted */ template void mathDetail::assertDimensionsOK( OutImageT const &convolvedImage, InImageT const &inImage, lsst::afw::math::Kernel const &kernel ) { if (convolvedImage.getDimensions() != inImage.getDimensions()) { std::ostringstream os; os << "convolvedImage dimensions = ( " << convolvedImage.getWidth() << ", " << convolvedImage.getHeight() << ") != (" << inImage.getWidth() << ", " << inImage.getHeight() << ") = inImage dimensions";
    69 d1596c6d - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    69 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } if (inImage.getWidth() < kernel.getWidth() || inImage.getHeight() < kernel.getHeight()) { std::ostringstream os; os << "inImage dimensions = ( " << inImage.getWidth() << ", " << inImage.getHeight() << ") smaller than (" << kernel.getWidth() << ", " << kernel.getHeight() << ") = kernel dimensions in width and/or height";
    77 d1596c6d - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    77 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } if ((kernel.getWidth() < 1) || (kernel.getHeight() < 1)) { std::ostringstream os; os << "kernel dimensions = ( " << kernel.getWidth() << ", " << kernel.getHeight() << ") smaller than (1, 1) in width and/or height";
    84 d1596c6d - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    84 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } } /* * Explicit instantiation */ /// \cond #define IMAGE(PIXTYPE) afwImage::Image #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage #define NL /* */ // Instantiate Image or MaskedImage versions #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \ template void mathDetail::assertDimensionsOK( \ IMGMACRO(OUTPIXTYPE) const &convolvedImage, \ IMGMACRO(INPIXTYPE) const &inImage, \ lsst::afw::math::Kernel const &kernel \ ); // Instantiate both Image and MaskedImage versions #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE) INSTANTIATE(double, double) INSTANTIATE(double, float) INSTANTIATE(double, int) INSTANTIATE(double, boost::uint16_t) INSTANTIATE(float, float) INSTANTIATE(float, int) INSTANTIATE(float, boost::uint16_t) INSTANTIATE(int, int) INSTANTIATE(boost::uint16_t, boost::uint16_t) /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d1596c6d

    commit d1596c6d0a9e2d5c95f341f75aea83555a4d7edd
    Author: cosic 
    Date:   Mon Nov 14 11:55:28 2011 +0000
    
        Code style improvements. Less reliance on ifdefs.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/table/Simple.cc

    Diff:

                    // -*- lsst-c++ -*-
                    #include 
                    
                    #include "lsst/afw/table/io/FitsWriter.h"
                    #include "lsst/afw/table/Simple.h"
                    #include "lsst/afw/table/detail/Access.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    //-----------------------------------------------------------------------------------------------------------
                    //----- Private SimpleTable/Record classes ---------------------------------------------------------------
                    //-----------------------------------------------------------------------------------------------------------
                    
                    // These private derived classes are what you actually get when you do SimpleTable::make; like the
                    // private classes in BaseTable.cc, it's more convenient to have an extra set of trivial derived
                    // classes than to do a lot of friending.
                    
                    namespace {
                    
                    class SimpleTableImpl;
                    
                    class SimpleRecordImpl : public SimpleRecord {
                    public:
                    
                        explicit SimpleRecordImpl(PTR(SimpleTable) const & table) : SimpleRecord(table) {}
                    
                    };
                    
                    class SimpleTableImpl : public SimpleTable {
                    public:
                    
                        explicit SimpleTableImpl(Schema const & schema, PTR(IdFactory) const & idFactory) : 
                            SimpleTable(schema, idFactory)
                        {}
                    
                        SimpleTableImpl(SimpleTableImpl const & other) : SimpleTable(other) {}
                    
                    private:
                    
                        virtual PTR(BaseTable) _clone() const {
                            return boost::make_shared(*this);
                        }
                    
                        virtual PTR(BaseRecord) _makeRecord() {
                            PTR(SimpleRecord) record = boost::make_shared(getSelf());
                            if (getIdFactory()) record->setId((*getIdFactory())());
                            return record;
                        }
                    
                    };
                    
                    } // anonymous
                    
                    //-----------------------------------------------------------------------------------------------------------
                    //----- SimpleFitsWriter ---------------------------------------------------------------------------------
                    //-----------------------------------------------------------------------------------------------------------
                    
                    // A custom FitsWriter for Simple - this just sets the AFW_TYPE key to SIMPLE, which should ensure
                    // we use SimpleFitsReader to read it.
                    
                    namespace {
                    
                    class SimpleFitsWriter : public io::FitsWriter {
                    public:
                    
                        explicit SimpleFitsWriter(Fits * fits, int flags) : io::FitsWriter(fits, flags) {}
                    
                    protected:
                        
                        virtual void _writeTable(CONST_PTR(BaseTable) const & table, std::size_t nRows);
                    
                    };
                    
                    void SimpleFitsWriter::_writeTable(CONST_PTR(BaseTable) const & t, std::size_t nRows) {
                        CONST_PTR(SimpleTable) table = boost::dynamic_pointer_cast(t);
                        if (!table) {
                            throw LSST_EXCEPT(
    
    78 1e296bda - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    78 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot use a SimpleFitsWriter on a non-Simple table." ); } io::FitsWriter::_writeTable(table, nRows); _fits->writeKey("AFW_TYPE", "SIMPLE", "Tells lsst::afw to load this as a Simple table."); } } // anonymous //----------------------------------------------------------------------------------------------------------- //----- SimpleFitsReader --------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------- // A custom FitsReader for SimpleTable/Record - this gets registered with name SIMPLE, so it should get used // whenever we read a table with AFW_TYPE set to that value. namespace { class SimpleFitsReader : public io::FitsReader { public: explicit SimpleFitsReader(Fits * fits, PTR(io::InputArchive) archive, int flags) : io::FitsReader(fits, archive, flags) {} protected: virtual PTR(BaseTable) _readTable(); }; PTR(BaseTable) SimpleFitsReader::_readTable() { PTR(daf::base::PropertyList) metadata = boost::make_shared(); _fits->readMetadata(*metadata, true); Schema schema(*metadata, true); PTR(SimpleTable) table = SimpleTable::make(schema, PTR(IdFactory)());
    114 1e296bda + table->setMetadata(metadata);
    _startRecords(*table);
    115 6c49463c - if (metadata->exists("AFW_TYPE")) metadata->remove("AFW_TYPE");
    116 1e296bda - table->setMetadata(metadata);
    return table; } // registers the reader so FitsReader::make can use it. static io::FitsReader::FactoryT referenceFitsReaderFactory("SIMPLE"); } // anonymous //----------------------------------------------------------------------------------------------------------- //----- SimpleTable/Record member function implementations ----------------------------------------------- //----------------------------------------------------------------------------------------------------------- SimpleRecord::SimpleRecord(PTR(SimpleTable) const & table) : BaseRecord(table) {} PTR(SimpleTable) SimpleTable::make(Schema const & schema, PTR(IdFactory) const & idFactory) { if (!checkSchema(schema)) { throw LSST_EXCEPT(
    134 1e296bda - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    133 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Schema for Simple must contain at least the keys defined by makeMinimalSchema()." ); } return boost::make_shared(schema, idFactory); } SimpleTable::SimpleTable(Schema const & schema, PTR(IdFactory) const & idFactory) : BaseTable(schema), _idFactory(idFactory) {} SimpleTable::SimpleTable(SimpleTable const & other) : BaseTable(other), _idFactory(other._idFactory ? other._idFactory->clone() : other._idFactory) {} SimpleTable::MinimalSchema::MinimalSchema() { id = schema.addField("id", "unique ID"); coord = schema.addField("coord", "position in ra/dec", "IRCS; radians"); schema.getCitizen().markPersistent(); } SimpleTable::MinimalSchema & SimpleTable::getMinimalSchema() { static MinimalSchema it; return it; } PTR(io::FitsWriter) SimpleTable::makeFitsWriter(fits::Fits * fitsfile, int flags) const { return boost::make_shared(fitsfile, flags); } template class CatalogT; template class CatalogT; template class SortedCatalogT; template class SortedCatalogT; }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    1e296bda

    commit 1e296bda917d1eeac92c30040cc4fd5a929344ad
    Author: Jim Bosch 
    Date:   Fri Feb 24 00:04:33 2012 -0500
    
        added SimpleTable/Record as (future) base class for all tables/records with IDs and celestial coordinates
    

    6c49463c

    commit 6c49463cf28838980e05aea39554d9dc0794dca5
    Author: Jim Bosch 
    Date:   Thu Mar 22 13:05:11 2012 -0400
    
        fix bug in FLAGCOL key handling logic that broke FITS read support for tables with no flag fields
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    1e296bda

    commit 1e296bda917d1eeac92c30040cc4fd5a929344ad
    Author: Jim Bosch 
    Date:   Fri Feb 24 00:04:33 2012 -0500
    
        added SimpleTable/Record as (future) base class for all tables/records with IDs and celestial coordinates
    

    Return to list

    python/lsst/afw/geom/ellipses/ellipsesLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define ellipsesLib_DOCSTRING
                    "
                    Python interface to lsst::afw::geom::ellipses classes and functions
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.geom.ellipses", docstring=ellipsesLib_DOCSTRING) ellipsesLib
                    
                    %{
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/geom/ellipses.h"
    
    37 3b0e9527 - #define PY_ARRAY_UNIQUE_SYMBOL LSST_AFW_GEOM_ELLIPSES_NUMPY_ARRAY_API
    38 3b0e9527 - #include "numpy/arrayobject.h"
    37 3b0e9527 + %}
    38 3b0e9527 +
    39 3b0e9527 + %include "lsst/p_lsstSwig.i"
    40 3b0e9527 + %lsst_exceptions();
    41 3b0e9527 +
    42 853c5734 + %initializeNumPy(afw_geom_ellipses)
    43 853c5734 + %{
    #include "ndarray/swig.h" #include "ndarray/swig/eigen.h" %}
    42 3b0e9527 -
    43 3b0e9527 - %init%{
    44 3b0e9527 - import_array();
    45 3b0e9527 - %}
    46 3b0e9527 -
    47 3b0e9527 - %include "lsst/p_lsstSwig.i"
    48 3b0e9527 -
    49 3b0e9527 - %lsst_exceptions();
    50 3b0e9527 -
    %include "ndarray.i"
    48 853c5734 +
    %import "lsst/afw/geom/geomLib.i" %pythondynamic lsst::afw::geom::ellipses::Ellipse; %ignore lsst::afw::geom::ellipses::BaseCore::transform; %ignore lsst::afw::geom::ellipses::BaseCore::convolve; %ignore lsst::afw::geom::ellipses::BaseCore::getGridTransform; %ignore lsst::afw::geom::ellipses::BaseCore::readParameters; %ignore lsst::afw::geom::ellipses::BaseCore::writeParameters; %ignore lsst::afw::geom::ellipses::BaseCore::as; %rename(assign) lsst::afw::geom::ellipses::BaseCore::operator=; %declareNumPyConverters(lsst::afw::geom::ellipses::BaseCore::Jacobian); %declareNumPyConverters(lsst::afw::geom::ellipses::BaseCore::ParameterVector); %shared_ptr(lsst::afw::geom::ellipses::BaseCore); %include "lsst/afw/geom/ellipses/BaseCore.h" %define %EllipseCore_PREINCLUDE(NAME) %feature(notabstract) lsst::afw::geom::ellipses::NAME; %implicitconv lsst::afw::geom::ellipses::NAME; %shared_ptr(lsst::afw::geom::ellipses::NAME); %ignore lsst::afw::geom::ellipses::NAME::writeParameters; %ignore lsst::afw::geom::ellipses::NAME::readParameters; %rename(assign) lsst::afw::geom::ellipses::NAME::operator=; %enddef %define %EllipseCore_POSTINCLUDE(NAME) %extend lsst::afw::geom::ellipses::NAME { %feature("shadow") _transform %{ def transform(self, t): return $action(self, t) %} %feature("shadow") _transformInPlace %{ def transformInPlace(self, t): $action(self, t) %} %feature("shadow") _convolve %{ def convolve(self, t): return $action(self, t) %} %feature("shadow") _getGridTransform %{ def getGridTransform(self): return $action(self) %} lsst::afw::geom::ellipses::NAME::Ptr _transform( lsst::afw::geom::LinearTransform const & t ) { return boost::static_pointer_cast( self->transform(t).copy() ); } void _transformInPlace(lsst::afw::geom::LinearTransform const & t) { self->transform(t).inPlace(); } lsst::afw::geom::ellipses::NAME::Ptr _convolve( lsst::afw::geom::ellipses::BaseCore const & other ) { return boost::static_pointer_cast( self->convolve(other).copy() ); } lsst::afw::geom::LinearTransform _getGridTransform() { return self->getGridTransform(); } static lsst::afw::geom::ellipses::NAME::Ptr cast( lsst::afw::geom::ellipses::BaseCore::Ptr const & p ) { return boost::dynamic_pointer_cast(p); } } %enddef %EllipseCore_PREINCLUDE(Axes); %EllipseCore_PREINCLUDE(Quadrupole); %include "lsst/afw/geom/ellipses/Axes.h" %include "lsst/afw/geom/ellipses/Quadrupole.h" %EllipseCore_POSTINCLUDE(Axes); %EllipseCore_POSTINCLUDE(Quadrupole); %extend lsst::afw::geom::ellipses::Axes {
    139 b7f4d5fe - %pythoncode {
    136 81c3bd10 + %pythoncode %{
    ? + def __repr__(self): return "Axes(a=%r, b=%r, theta=%r)" % (self.getA(), self.getB(), self.getTheta()) def __reduce__(self): return (Axes, (self.getA(), self.getB(), self.getTheta())) def __str__(self): return "(a=%s, b=%s, theta=%s)" % (self.getA(), self.getB(), self.getTheta())
    146 b7f4d5fe - }
    143 81c3bd10 + %}
    ? + } %extend lsst::afw::geom::ellipses::Quadrupole {
    150 b7f4d5fe - %pythoncode {
    147 81c3bd10 + %pythoncode %{
    ? + def __repr__(self): return "Quadrupole(ixx=%r, iyy=%r, ixy=%r)" % (self.getIxx(), self.getIyy(), self.getIxy()) def __reduce__(self): return (Quadrupole, (self.getIxx(), self.getIyy(), self.getIxy())) def __str__(self): return "(ixx=%s, iyy=%s, ixy=%s)" % (self.getIxx(), self.getIyy(), self.getIxy())
    157 b7f4d5fe - }
    154 81c3bd10 + %}
    ? + } %include "Separable.i" %feature("valuewrapper") lsst::afw::geom::ellipses::Ellipse; %ignore lsst::afw::geom::ellipses::Ellipse::getCore; %ignore lsst::afw::geom::ellipses::Ellipse::transform; %ignore lsst::afw::geom::ellipses::Ellipse::convolve; %ignore lsst::afw::geom::ellipses::Ellipse::getGridTransform; %ignore lsst::afw::geom::ellipses::Ellipse::readParameters; %ignore lsst::afw::geom::ellipses::Ellipse::writeParameters; %rename(assign) lsst::afw::geom::ellipses::Ellipse::operator=; %shared_ptr(lsst::afw::geom::ellipses::Ellipse); %declareNumPyConverters(lsst::afw::geom::ellipses::Ellipse::ParameterVector); %extend lsst::afw::geom::ellipses::Ellipse { %feature("shadow") _transform %{ def transform(self, t): return $action(self, t) %} %feature("shadow") _transformInPlace %{ def transformInPlace(self, t): $action(self, t) %} %feature("shadow") _convolve %{ def convolve(self, t): return $action(self, t) %} %feature("shadow") _getGridTransform %{ def getGridTransform(self): return $action(self) %} %feature("shadow") getCorePtr %{ def getCore(self): return $action(self).cast() %} lsst::afw::geom::ellipses::Ellipse _transform(lsst::afw::geom::AffineTransform const & t) { return self->transform(t); } void _transformInPlace(lsst::afw::geom::AffineTransform const & t) { self->transform(t).inPlace(); } lsst::afw::geom::ellipses::Ellipse _convolve(lsst::afw::geom::ellipses::Ellipse const & other) { return self->convolve(other); } lsst::afw::geom::AffineTransform _getGridTransform() { return self->getGridTransform(); }
    210 3b0e9527 - %pythoncode {
    207 81c3bd10 + %pythoncode %{
    ? + def __repr__(self): return "Ellipse(%r, %r)" % (self.getCore(), self.getCenter()) def __reduce__(self): return (Ellipse, (self.getCore(), self.getCenter())) def __str__(self): return "(%s, %s)" % (self.getCore(), self.getCenter())
    217 3b0e9527 - }
    214 81c3bd10 + %}
    ? + } %include "lsst/afw/geom/ellipses/Ellipse.h" %include "lsst/afw/geom/ellipses/Parametric.h" %include "lsst/afw/geom/ellipses.h" // just for Separable typedefs %include "PixelRegion.i"

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3b0e9527

    commit 3b0e9527db8456ec69bbbc04fc51e5c64ab75490
    Author: dubcovsky 
    Date:   Sun Feb 6 06:37:31 2011 +0000
    
        #1556 *ahem* actually added the updated swig wrappers for lsst::afw::geom::ellipses
    

    b7f4d5fe

    commit b7f4d5fe5cc7316dfbc5891f111bd22a34160855
    Author: jbosch 
    Date:   Sun Mar 13 03:15:28 2011 +0000
    
        afw #1556 - tweaks to ellipses SWIG code, added moments computation to shapelets library, fixed missing documentation in images
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    3b0e9527

    commit 3b0e9527db8456ec69bbbc04fc51e5c64ab75490
    Author: dubcovsky 
    Date:   Sun Feb 6 06:37:31 2011 +0000
    
        #1556 *ahem* actually added the updated swig wrappers for lsst::afw::geom::ellipses
    

    853c5734

    commit 853c5734ee13f55fd35e9e18ed5ac69a0073b97f
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:18:28 2015 -0400
    
        Utilize new numeric scalar typemaps and NumPy import macro.
    

    Return to list

    src/cameraGeom/Detector.cc

    Diff:

                    /* 
                     * LSST Data Management System
    
    3 a6d55f08 - * Copyright 2008, 2009, 2010 LSST Corporation.
    ? ------------ ^
    3 4384a0a2 + * Copyright 2014 LSST Corporation.
    ? ^ * * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the LSST License Statement and * the GNU General Public License along with this program. If not, * see . */
    22 4384a0a2 +
    23 4384a0a2 + #include
    22 a6d55f08 -
    23 60edffcc - /**
    24 60edffcc - * \file
    25 60edffcc - */
    26 60edffcc - #include
    ? ^ --- ^^
    24 4384a0a2 + #include
    ? ^^^ ^
    27 60edffcc - #include "lsst/afw/cameraGeom/Id.h"
    #include "lsst/afw/cameraGeom/Detector.h"
    29 a5bdff61 - #include "lsst/afw/cameraGeom/Orientation.h"
    30 9a0b3ed0 - #include "lsst/afw/cameraGeom/Distortion.h"
    31 e88ff0cd - #include "lsst/afw/cameraGeom/FpPoint.h"
    32 60edffcc -
    33 60edffcc - namespace afwGeom = lsst::afw::geom;
    34 60edffcc - namespace afwImage = lsst::afw::image;
    35 d95640da - namespace pexEx = lsst::pex::exceptions;
    namespace lsst { namespace afw { namespace cameraGeom {
    31 4384a0a2 + Detector::Detector(
    32 4384a0a2 + std::string const &name,
    33 d1426bf7 + int id,
    34 4384a0a2 + DetectorType type,
    35 4384a0a2 + std::string const &serial,
    36 5caed4f7 + geom::Box2I const &bbox,
    37 18439e6c + table::AmpInfoCatalog const &InfoCatalog,
    38 4384a0a2 + Orientation const &orientation,
    39 5046e7f3 + geom::Extent2D const & pixelSize,
    40 6f5ea58d + CameraTransformMap::Transforms const &transforms
    41 4384a0a2 + ) :
    42 4384a0a2 + _name(name),
    43 d1426bf7 + _id(id),
    44 4384a0a2 + _type(type),
    45 4384a0a2 + _serial(serial),
    46 5caed4f7 + _bbox(bbox),
    47 5046e7f3 + _ampInfoCatalog(ampInfoCatalog),
    48 5046e7f3 + _ampNameIterMap(),
    49 4384a0a2 + _orientation(orientation),
    50 4384a0a2 + _pixelSize(pixelSize),
    51 6f5ea58d + _transformMap(CameraSys(PIXELS.getSysName(), name), transforms)
    52 4384a0a2 + {
    53 e6a90084 + _init();
    54 4384a0a2 + }
    42 20ea8e44 - /************************************************************************************************************/
    43 20ea8e44 - /// Test for equality of two Ids; ignore serial if < 0 and name if == ""
    44 d95640da - bool Id::operator==(Id const& rhs) const {
    45 20ea8e44 - if (_serial >= 0 && rhs._serial >= 0) {
    46 20ea8e44 - bool const serialEq = (_serial == rhs._serial);
    47 20ea8e44 - if (serialEq) {
    48 20ea8e44 - if (_name != "" && rhs._name != "") {
    49 20ea8e44 - return _name == rhs._name;
    56 5caed4f7 + std::vector Detector::getCorners(CameraSys const &cameraSys) const {
    57 7911ee94 + std::vector fromVec = geom::Box2D(_bbox).getCorners();
    58 5caed4f7 + return _transformMap.transform(fromVec, _transformMap.getNativeCoordSys(), cameraSys);
    59 5caed4f7 + }
    60 5caed4f7 +
    61 03b91f22 + std::vector Detector::getCorners(CameraSysPrefix const &cameraSysPrefix) const {
    62 03b91f22 + return getCorners(makeCameraSys(cameraSysPrefix));
    63 03b91f22 + }
    64 03b91f22 +
    65 03b91f22 + CameraPoint Detector::getCenter(CameraSys const &cameraSys) const {
    66 03b91f22 + CameraPoint ctrPix = makeCameraPoint(geom::Box2D(_bbox).getCenter(), _transformMap.getNativeCoordSys());
    67 03b91f22 + return transform(ctrPix, cameraSys);
    68 03b91f22 + }
    69 03b91f22 +
    70 03b91f22 + CameraPoint Detector::getCenter(CameraSysPrefix const &cameraSysPrefix) const {
    71 03b91f22 + return getCenter(makeCameraSys(cameraSysPrefix));
    72 03b91f22 + }
    73 03b91f22 +
    74 5046e7f3 + const table::AmpInfoRecord & Detector::operator[](std::string const &name) const {
    75 5046e7f3 + _AmpInfoMap::const_iterator ampIter = _ampNameIterMap.find(name);
    76 5046e7f3 + if (ampIter == _ampNameIterMap.end()) {
    77 4384a0a2 + std::ostringstream os;
    78 4384a0a2 + os << "Unknown amplifier \"" << name << "\"";
    79 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    80 4384a0a2 + }
    81 5046e7f3 + return *(ampIter->second);
    82 4384a0a2 + }
    83 4384a0a2 +
    84 dab65f42 + bool Detector::hasTransform(CameraSys const &cameraSys) const {
    85 dab65f42 + return _transformMap.contains(cameraSys);
    86 dab65f42 + }
    87 dab65f42 +
    88 dab65f42 + bool Detector::hasTransform(CameraSysPrefix const &cameraSysPrefix) const {
    89 dab65f42 + return hasTransform(makeCameraSys(cameraSysPrefix));
    90 dab65f42 + }
    91 dab65f42 +
    92 dab65f42 + CONST_PTR(afw::geom::XYTransform) Detector::getTransform(CameraSys const &cameraSys) const {
    93 dab65f42 + return _transformMap[cameraSys];
    94 dab65f42 + }
    95 dab65f42 +
    96 dab65f42 + CONST_PTR(afw::geom::XYTransform) Detector::getTransform(CameraSysPrefix const &cameraSysPrefix) const {
    97 dab65f42 + return getTransform(makeCameraSys(cameraSysPrefix));
    98 dab65f42 + }
    99 dab65f42 +
    100 dab65f42 +
    101 dab65f42 + void Detector::_init() {
    102 5046e7f3 + // make _ampNameIterMap
    103 18439e6c + for (table::AmpInfoCatalog::const_iterator ampIter = _ampInfoCatalog.begin();
    104 5046e7f3 + ampIter != _ampInfoCatalog.end(); ++ampIter) {
    105 5046e7f3 + _ampNameIterMap.insert(std::make_pair(ampIter->getName(), ampIter));
    106 4384a0a2 + }
    107 5046e7f3 + if (_ampNameIterMap.size() != _ampInfoCatalog.size()) {
    108 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    109 5046e7f3 + "Invalid ampInfoCatalog: not all amplifier names are unique");
    110 e6a90084 + }
    111 e6a90084 +
    112 e6a90084 + // check detector name in CoordSys in transform registry
    113 6f5ea58d + for (CameraTransformMap::Transforms::const_iterator trIter = _transformMap.begin();
    114 6f5ea58d + trIter != _transformMap.end(); ++trIter) {
    115 6f5ea58d + if (trIter->first.hasDetectorName() && trIter->first.getDetectorName() != _name) {
    116 e6a90084 + std::ostringstream os;
    117 6f5ea58d + os << "Invalid transformMap: " << trIter->first << " detector name != \"" << _name << "\"";
    118 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    }
    51 20ea8e44 - }
    52 20ea8e44 -
    53 20ea8e44 - return serialEq;
    54 20ea8e44 - } else {
    55 20ea8e44 - return _name == rhs._name;
    } }
    59 20ea8e44 - /// Test for ordering of two Ids; ignore serial if < 0 and name if == ""
    60 d95640da - bool Id::operator<(Id const& rhs) const {
    61 20ea8e44 - if (_serial >= 0 && rhs._serial >= 0) {
    62 20ea8e44 - if (_serial == rhs._serial) {
    63 20ea8e44 - if (_name != "" && rhs._name != "") {
    64 20ea8e44 - return _name < rhs._name;
    65 20ea8e44 - }
    66 20ea8e44 - }
    67 20ea8e44 - return _serial < rhs._serial;
    68 20ea8e44 - } else {
    69 20ea8e44 - return _name < rhs._name;
    70 20ea8e44 - }
    71 20ea8e44 - }
    72 20ea8e44 -
    73 20ea8e44 - /************************************************************************************************************/
    74 f846bf5f - /**
    75 e193729a - * Return the Detector's footprint without applying any rotations that were used when inserting
    76 e193729a - * it into its parent (e.g. Raft)
    77 e193729a - */
    78 a8f86353 - afwGeom::BoxI
    79 d95640da - Detector::getAllPixelsNoRotation(bool isTrimmed ///< Has the bias/overclock have been removed?
    80 d95640da - ) const
    81 e193729a - {
    82 a8f86353 - afwGeom::BoxI allPixels = (_hasTrimmablePixels && isTrimmed) ? _trimmedAllPixels : _allPixels;
    83 e193729a -
    84 e193729a - int const n90 = _orientation.getNQuarter();
    85 e193729a - if (n90 != 0) {
    86 d95640da - allPixels = detail::rotateBBoxBy90(allPixels, -n90, getAllPixels(false).getDimensions());
    87 e193729a - }
    88 e193729a -
    89 e193729a - return allPixels;
    90 e193729a - }
    91 e193729a -
    92 e193729a - /************************************************************************************************************/
    93 e3c14206 -
    94 e3c14206 - afwGeom::Point2D Detector::getCenterPixel() const {
    95 e3c14206 - return afwGeom::Point2D(0.5*(getAllPixels(true).getWidth() - 1),
    96 e3c14206 - 0.5*(getAllPixels(true).getHeight() - 1));
    97 e3c14206 - }
    98 e3c14206 -
    99 e3c14206 - /************************************************************************************************************/
    100 e193729a - /**
    101 f846bf5f - * Return size in mm of this Detector
    102 f846bf5f - */
    103 d95640da - FpExtent Detector::getSize() const {
    104 f846bf5f - bool const isTrimmed = true;
    105 ffc2778f -
    106 d95640da - return FpExtent(afwGeom::Extent2D(getAllPixels(isTrimmed).getWidth()*_pixelSize,
    107 e88ff0cd - getAllPixels(isTrimmed).getHeight()*_pixelSize));
    108 f846bf5f - }
    109 f846bf5f -
    110 60edffcc - /**
    111 0b6830ca - * Return the offset from the mosaic centre, in mm, given a pixel position
    112 0b6830ca - */
    113 d95640da - FpPoint Detector::getPositionFromPixel(
    114 3b14cb8d - lsst::afw::geom::Point2D const& pix ///< Pixel coordinates wrt bottom left of Detector
    115 3b14cb8d - ) const {
    116 bc368ef9 - double cosYaw = _orientation.getCosYaw();
    117 bc368ef9 - double sinYaw = _orientation.getSinYaw();
    118 bc368ef9 -
    119 bc368ef9 - afwGeom::Extent2D offset = afwGeom::Extent2D(cosYaw * pix.getX() - sinYaw * pix.getY(),
    120 bc368ef9 - sinYaw * pix.getX() + cosYaw * pix.getY());
    121 bc368ef9 - offset -= afwGeom::Extent2D(getCenterPixel());
    122 bc368ef9 - offset *= getPixelSize();
    123 bc368ef9 - return _center + FpPoint(offset);
    124 bc368ef9 - }
    125 0b6830ca -
    126 4b6acf34 -
    127 4b6acf34 - /**
    128 4b6acf34 - * Return the pixel position given an offset from the mosaic centre in mm
    129 4b6acf34 - */
    130 d95640da - afwGeom::Point2D Detector::getPixelFromPosition(
    131 3b14cb8d - FpPoint const &pos ///< Offset from mosaic centre, mm
    132 3b14cb8d - ) const {
    133 bc368ef9 - double cosYaw = _orientation.getCosYaw();
    134 bc368ef9 - double sinYaw = _orientation.getSinYaw();
    135 bc368ef9 -
    136 bc368ef9 - afwGeom::Extent2D offset((pos - getCenter()).getPixels(getPixelSize()));
    137 bc368ef9 - offset += afwGeom::Extent2D(getCenterPixel());
    138 bc368ef9 - return afwGeom::Point2D(cosYaw * offset.getX() + sinYaw * offset.getY(),
    139 bc368ef9 - -sinYaw * offset.getX() + cosYaw * offset.getY());
    140 60edffcc - }
    141 60edffcc -
    142 1ac3f936 -
    143 d95640da - afwGeom::AffineTransform Detector::linearizePixelFromPosition(FpPoint const &q) const
    144 61d4e3d9 - {
    145 61d4e3d9 - afwGeom::Point2D p = this->getPixelFromPosition(q);
    146 61d4e3d9 - afwGeom::Point2D px = p + afwGeom::Extent2D(1,0);
    147 61d4e3d9 - afwGeom::Point2D py = p + afwGeom::Extent2D(0,1);
    148 61d4e3d9 -
    149 61d4e3d9 - afwGeom::Point2D qx = this->getPositionFromPixel(px).getMm();
    150 61d4e3d9 - afwGeom::Point2D qy = this->getPositionFromPixel(py).getMm();
    151 61d4e3d9 -
    152 61d4e3d9 - return afwGeom::makeAffineTransformFromTriple(q.getMm(), qx, qy, p, px, py);
    153 61d4e3d9 - }
    154 61d4e3d9 -
    155 61d4e3d9 -
    156 d95640da - afwGeom::AffineTransform Detector::linearizePositionFromPixel(afwGeom::Point2D const &p) const
    157 61d4e3d9 - {
    158 61d4e3d9 - afwGeom::Point2D px = p + afwGeom::Extent2D(1,0);
    159 61d4e3d9 - afwGeom::Point2D py = p + afwGeom::Extent2D(0,1);
    160 61d4e3d9 -
    161 61d4e3d9 - afwGeom::Point2D q = this->getPositionFromPixel(p).getMm();
    162 61d4e3d9 - afwGeom::Point2D qx = this->getPositionFromPixel(px).getMm();
    163 61d4e3d9 - afwGeom::Point2D qy = this->getPositionFromPixel(py).getMm();
    164 61d4e3d9 -
    165 61d4e3d9 - return afwGeom::makeAffineTransformFromTriple(p, px, py, q, qx, qy);
    166 61d4e3d9 - }
    167 61d4e3d9 -
    168 61d4e3d9 -
    169 1ac3f936 - /// Offset a Detector by the specified amount
    170 d95640da - void Detector::shift(int dx, ///< How much to offset in x (pixels)
    171 d95640da - int dy ///< How much to offset in y (pixels)
    172 d95640da - ) {
    173 a8f86353 - afwGeom::Extent2I offset(dx, dy);
    174 1ac3f936 -
    175 3263f939 - _allPixels.shift(offset);
    176 3263f939 - _trimmedAllPixels.shift(offset);
    177 1ac3f936 - }
    178 4b6acf34 -
    179 4b6acf34 - /************************************************************************************************************/
    180 06309dc2 - //
    181 06309dc2 - // We're rotating an Image through an integral number of quarter turns,
    182 06309dc2 - // modify this BBox accordingly
    183 06309dc2 - //
    184 06309dc2 - afwGeom::Box2I detail::rotateBBoxBy90(
    185 06309dc2 - lsst::afw::geom::Box2I const& bbox,
    186 06309dc2 - int n90,
    187 06309dc2 - lsst::afw::geom::Extent2I const& dimensions
    188 4b6acf34 - )
    189 4b6acf34 - {
    190 4b6acf34 - while (n90 < 0) {
    191 4b6acf34 - n90 += 4;
    192 4b6acf34 - }
    193 4b6acf34 - n90 %= 4;
    194 4b6acf34 -
    195 4b6acf34 - int s, c; // sin/cos of the rotation angle
    196 4b6acf34 - switch (n90) {
    197 4b6acf34 - case 0:
    198 4b6acf34 - s = 0; c = 1;
    199 4b6acf34 - break;
    200 4b6acf34 - case 1:
    201 4b6acf34 - s = 1; c = 0;
    202 4b6acf34 - break;
    203 4b6acf34 - case 2:
    204 4b6acf34 - s = 0; c = -1;
    205 4b6acf34 - break;
    206 4b6acf34 - case 3:
    207 4b6acf34 - s = -1; c = 0;
    208 4b6acf34 - break;
    209 4b6acf34 - default:
    210 d30faf6b - c = s = 0; // make compiler happy
    211 d30faf6b - assert(n90 >= 0 && n90 <= 3); // we said "%= 4"
    212 4b6acf34 - }
    213 4b6acf34 - //
    214 4b6acf34 - // To work
    215 4b6acf34 - //
    216 25e61ab4 - afwGeom::Point2I const centerPixel = afwGeom::Point2I(dimensions[0]/2, dimensions[1]/2);
    217 7ffd25c1 -
    218 4b6acf34 - int x0, y0; // minimum x/y
    219 4b6acf34 - int x1, y1; // maximum x/y
    220 4b6acf34 - int xCorner[4], yCorner[4]; // corners of Detector, wrt centerPixel
    221 4b6acf34 -
    222 4b6acf34 - int i = 0;
    223 3263f939 - xCorner[i] = bbox.getMinX() - centerPixel[0];
    224 3263f939 - yCorner[i] = bbox.getMinY() - centerPixel[1];
    225 4b6acf34 - ++i;
    226 4b6acf34 -
    227 3263f939 - xCorner[i] = bbox.getMaxX() - centerPixel[0];
    228 3263f939 - yCorner[i] = bbox.getMinY() - centerPixel[1];
    229 4b6acf34 - ++i;
    230 4b6acf34 -
    231 3263f939 - xCorner[i] = bbox.getMaxX() - centerPixel[0];
    232 3263f939 - yCorner[i] = bbox.getMaxY() - centerPixel[1];
    233 4b6acf34 - ++i;
    234 4b6acf34 -
    235 3263f939 - xCorner[i] = bbox.getMinX() - centerPixel[0];
    236 3263f939 - yCorner[i] = bbox.getMaxY() - centerPixel[1];
    237 4b6acf34 - ++i;
    238 4b6acf34 - //
    239 4b6acf34 - // Now see which is the smallest/largest
    240 4b6acf34 - i = 0;
    241 4b6acf34 - x0 = x1 = c*xCorner[i] - s*yCorner[i];
    242 4b6acf34 - y0 = y1 = s*xCorner[i] + c*yCorner[i];
    243 4b6acf34 - ++i;
    244 4b6acf34 -
    245 4b6acf34 - for (; i != 4; ++i) {
    246 4b6acf34 - int x = c*xCorner[i] - s*yCorner[i];
    247 4b6acf34 - int y = s*xCorner[i] + c*yCorner[i];
    248 4b6acf34 -
    249 4b6acf34 - if (x < x0) {
    250 4b6acf34 - x0 = x;
    251 4b6acf34 - }
    252 4b6acf34 - if (x > x1) {
    253 4b6acf34 - x1 = x;
    254 4b6acf34 - }
    255 4b6acf34 - if (y < y0) {
    256 4b6acf34 - y0 = y;
    257 4b6acf34 - }
    258 4b6acf34 - if (y > y1) {
    259 4b6acf34 - y1 = y;
    260 4b6acf34 - }
    261 4b6acf34 - }
    262 4b6acf34 - //
    263 4b6acf34 - // Fiddle things a little if the detector has an even number of pixels so that square BBoxes
    264 4b6acf34 - // will map into themselves
    265 4b6acf34 - //
    266 4b6acf34 - if(n90 == 1) {
    267 e2db5f35 - if (dimensions[0]%2 == 0) {
    268 4b6acf34 - x0--; x1--;
    269 e2db5f35 - }
    270 4b6acf34 - } else if (n90 == 2) {
    271 e2db5f35 - if (dimensions[0]%2 == 0) {
    272 4b6acf34 - x0--; x1--;
    273 e2db5f35 - }
    274 e2db5f35 - if (dimensions[1]%2 == 0) {
    275 4b6acf34 - y0--; y1--;
    276 e2db5f35 - }
    277 4b6acf34 - } else if(n90 == 3) {
    278 e2db5f35 - if (dimensions[1]%2 == 0) {
    279 4b6acf34 - y0--; y1--;
    280 e2db5f35 - }
    281 4b6acf34 - }
    282 7ffd25c1 -
    283 c9c89e06 - afwGeom::Point2I LLC(centerPixel[0] + x0, centerPixel[1] + y0);
    284 c9c89e06 - afwGeom::Point2I URC(centerPixel[0] + x1, centerPixel[1] + y1);
    285 7ffd25c1 -
    286 c9c89e06 - afwGeom::Box2I newBbox(LLC, URC);
    287 7ffd25c1 -
    288 31bfc9f3 - //int const dxy0 = (dimensions[1]/2 - dimensions[0]/2); // how far the origin moved
    289 31bfc9f3 -
    290 31bfc9f3 - int const dxy0 = centerPixel[0] - centerPixel[1];
    291 4b6acf34 - if (n90%2 == 1 && dxy0 != 0) {
    292 31bfc9f3 - newBbox.shift(geom::Extent2I(-dxy0, dxy0));
    293 4b6acf34 - }
    294 7ffd25c1 -
    295 4b6acf34 - return newBbox;
    296 4b6acf34 - }
    297 4b6acf34 -
    298 4b6acf34 - ///
    299 4b6acf34 - /// Set the Detector's Orientation
    300 4b6acf34 - ///
    301 d95640da - void Detector::setOrientation(
    302 d95640da - Orientation const& orientation // the detector's new Orientation
    303 d95640da - )
    304 4b6acf34 - {
    305 4b6acf34 - int const n90 = orientation.getNQuarter() - _orientation.getNQuarter();
    306 4b6acf34 - _orientation = orientation;
    307 4b6acf34 - //
    308 4b6acf34 - // Now update the private members
    309 4b6acf34 - //
    310 d95640da - _allPixels = detail::rotateBBoxBy90(
    311 a8f86353 - _allPixels, n90, getAllPixels(false).getDimensions()
    312 a8f86353 - );
    313 d95640da - _trimmedAllPixels = detail::rotateBBoxBy90(
    314 a8f86353 - _trimmedAllPixels, n90, getAllPixels(true).getDimensions()
    315 a8f86353 - );
    316 4b6acf34 - if (n90 == 1 || n90 == 3) {
    317 25e61ab4 - _size = afwGeom::Extent2D(_size[1], _size[0]);
    318 4b6acf34 - }
    319 4b6acf34 - }
    320 9a0b3ed0 -
    321 9a0b3ed0 -
    322 d95640da - void Detector::setDistortion(CONST_PTR(Distortion) distortion) {
    323 9a0b3ed0 - _distortion = distortion;
    324 9a0b3ed0 - }
    325 9a0b3ed0 -
    326 d95640da - CONST_PTR(Distortion) Detector::getDistortion() const {
    327 9a0b3ed0 -
    328 9a0b3ed0 - // if we have a distortion ... return it
    329 9a0b3ed0 - if (_distortion) {
    330 9a0b3ed0 - return _distortion;
    331 9a0b3ed0 -
    332 f1f92bbc - // otherwise, return our parent's ... no parent? return Null
    333 9a0b3ed0 - } else {
    334 f3c9341f - CONST_PTR(Detector) parent = this->getParent();
    335 9a0b3ed0 - if (parent) {
    336 9a0b3ed0 - return parent->getDistortion();
    337 9a0b3ed0 - } else {
    338 f3c9341f - return CONST_PTR(Distortion)(); //new Distortion());
    339 9a0b3ed0 - }
    340 9a0b3ed0 - }
    341 9a0b3ed0 -
    342 f3c9341f - return CONST_PTR(Distortion)(); //new Distortion());
    343 9a0b3ed0 - }
    344 d95640da -
    345 d95640da -
    346 d95640da -
    347 d95640da - // -----------------------------------------------------------------------------------------------------------
    348 d95640da - //
    349 d95640da - // DetectorXYTransform
    350 d95640da -
    351 d95640da -
    352 d95640da - DetectorXYTransform::DetectorXYTransform(CONST_PTR(XYTransform) fpTransform,
    353 d95640da - CONST_PTR(Detector) detector)
    354 d95640da - : XYTransform(false), _fpTransform(fpTransform), _detector(detector)
    355 d95640da - {
    356 d95640da - if (!fpTransform->inFpCoordinateSystem()) {
    357 d95640da - throw LSST_EXCEPT(pexEx::InvalidParameterException,
    358 d95640da - "DetectorXYTransform base must be in FP coordinate system");
    359 d95640da - }
    360 d95640da - }
    361 d95640da -
    362 d95640da - PTR(geom::XYTransform) DetectorXYTransform::clone() const
    363 d95640da - {
    364 d95640da - // note: there is no detector->clone()
    365 d95640da - return boost::make_shared (_fpTransform->clone(), _detector);
    366 d95640da - }
    367 d95640da -
    368 d95640da - PTR(geom::XYTransform) DetectorXYTransform::invert() const
    369 d95640da - {
    370 d95640da - return boost::make_shared (_fpTransform->invert(), _detector);
    371 d95640da - }
    372 d95640da -
    373 d95640da - geom::Point2D DetectorXYTransform::forwardTransform(Point2D const &p) const
    374 d95640da - {
    375 d95640da - Point2D q;
    376 d95640da - q = _detector->getPositionFromPixel(p).getMm();
    377 d95640da - q = _fpTransform->forwardTransform(q);
    378 d95640da - q = _detector->getPixelFromPosition(FpPoint(q));
    379 d95640da - return q;
    380 d95640da - }
    381 d95640da -
    382 d95640da - geom::Point2D DetectorXYTransform::reverseTransform(Point2D const &p) const
    383 d95640da - {
    384 d95640da - Point2D q;
    385 d95640da - q = _detector->getPositionFromPixel(p).getMm();
    386 d95640da - q = _fpTransform->reverseTransform(q);
    387 d95640da - q = _detector->getPixelFromPosition(FpPoint(q));
    388 d95640da - return q;
    389 d95640da - }
    390 d95640da -
    391 d95640da - geom::AffineTransform DetectorXYTransform::linearizeForwardTransform(Point2D const &p) const
    392 d95640da - {
    393 d95640da - AffineTransform a;
    394 d95640da - a = _detector->linearizePositionFromPixel(p);
    395 d95640da - a = _fpTransform->linearizeForwardTransform(a(p)) * a;
    396 d95640da - a = _detector->linearizePixelFromPosition(FpPoint(a(p))) * a;
    397 d95640da - return a;
    398 d95640da - }
    399 d95640da -
    400 d95640da - geom::AffineTransform DetectorXYTransform::linearizeReverseTransform(Point2D const &p) const
    401 d95640da - {
    402 d95640da - AffineTransform a;
    403 d95640da - a = _detector->linearizePositionFromPixel(p);
    404 d95640da - a = _fpTransform->linearizeReverseTransform(a(p)) * a;
    405 d95640da - a = _detector->linearizePixelFromPosition(FpPoint(a(p))) * a;
    406 d95640da - return a;
    407 d95640da - }
    408 d95640da -
    }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9a0b3ed0

    commit 9a0b3ed09fa81b663487c75696e7198af0cf257d
    Author: bick 
    Date:   Fri Aug 26 23:03:09 2011 +0000
    
        #1753 (not yet working) distortion stuff initial check-in.
    

    20ea8e44

    commit 20ea8e447836046d5e9c15511e9221e2119dfa64
    Author: rhl 
    Date:   Wed Feb 10 21:34:03 2010 +0000
    
        Sort components by Id; #1168
    

    7ffd25c1

    commit 7ffd25c1b6fa71ec4641f4718d6eddc839f7a758
    Author: rhl 
    Date:   Sun Apr 4 15:59:56 2010 +0000
    
        Added support for amps being stored on disk in separate files
    

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    0b6830ca

    commit 0b6830cacae0b64aeb66079b4acd73c03c0d5ca2
    Author: rhl 
    Date:   Mon Jan 11 05:38:33 2010 +0000
    
        Nearly got things working with detector centres; off to Japan...
    

    61d4e3d9

    commit 61d4e3d9786f54bc560d5bd4e36fe08ca51c4d1d
    Author: Kendrick Smith 
    Date:   Wed Feb 6 16:09:29 2013 -0500
    
        add routines to linearize the pixel->FP coordinate change
    

    3b14cb8d

    commit 3b14cb8da4418308bcd4430d02b3cc42e4227160
    Author: Jim Bosch 
    Date:   Thu Feb 28 21:02:08 2013 +0900
    
        Removed (broken) option to transform between focal plane coordinates and untrimmed detector coordinates.
    

    e2db5f35

    commit e2db5f350ff2de3f767262cf04f4aee513be725b
    Author: krughoff 
    Date:   Thu Nov 10 23:55:40 2011 +0000
    
        Final changes to geometry before merge
    

    31bfc9f3

    commit 31bfc9f31902f0ad236817b57f40e7c2a3f2dbe1
    Merge: 1dc2df2 2fec316
    Author: krughoff 
    Date:   Wed Oct 26 18:30:59 2011 +0000
    
        Camera geometry tests now passing
    

    f1f92bbc

    commit f1f92bbc998b8a4a4c97c80f6dc5ff02a3f1d218
    Author: Steven Bickerton 
    Date:   Sun Jan 29 18:29:23 2012 -0600
    
        distort lanc order to 3 or PSF border too big.  Detector needs Null Distort default.  Psf offset buffers to 0.
    

    a8f86353

    commit a8f86353b4d794d8e2accd0ce6950e72a06c3f66
    Merge: a128aac 246b6dd
    Author: dubcovsky 
    Date:   Thu Mar 31 20:50:37 2011 +0000
    
        #1556 trunk merged to ticket branch
    

    1ac3f936

    commit 1ac3f9368c1453487cfea8334ba310c339552ede
    Author: rhl 
    Date:   Wed Jan 6 19:59:28 2010 +0000
    
        Initial version of Raft code
    

    4b6acf34

    commit 4b6acf347c723a61081eb7211584ce7712372ddb
    Author: rhl 
    Date:   Wed Jan 13 06:32:59 2010 +0000
    
        Got rotation of detectors by 90n degrees (and non-square dataSecs) working
    

    bc368ef9

    commit bc368ef93c84110b6e992778343c63e6508c284b
    Author: Jim Bosch 
    Date:   Thu Feb 28 20:46:46 2013 +0900
    
        Make yaw rotate about detector origin, not center, for compatibility with meas_mosaic
    

    f3c9341f

    commit f3c9341fa4bb1f322df3de025bb1aad936224ac0
    Author: Steven Bickerton 
    Date:   Thu Feb 2 10:33:55 2012 -0600
    
        continuing work on the master merge
    

    a5bdff61

    commit a5bdff614c8d29d8e6cf30d324b1da20522190b8
    Author: Robert Lupton the Good 
    Date:   Wed Feb 1 12:31:03 2012 -0500
    
        Remove some header file includes
    

    e88ff0cd

    commit e88ff0cd6d8b7e3b4173c8fd71f33e78b407c782
    Author: Steven Bickerton 
    Date:   Tue Jan 31 10:02:20 2012 -0600
    
        split FpPosition to FpPoint/Extent.
    

    ffc2778f

    commit ffc2778fcf414a7bf95fdcb429cc5d14c8a079e6
    Author: rhl 
    Date:   Sat Jan 9 14:45:15 2010 +0000
    
        Got pixel -> position working.  Position -> pixel is still broken
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    e3c14206

    commit e3c14206282f922b11613a08ddf4fac57f4ca4a8
    Author: Jim Bosch 
    Date:   Thu Feb 28 15:41:36 2013 +0900
    
        Disable setting center pixel in cameraGeom.
        
        The parts of cameraGeom that are known to work - getPixelFromPosition and getPositionFromPixel - do not make use of the _centerPixel data member; instead they compute the center pixel directly from the bounding boxes.  That makes being able to set the center pixel a potention source of errors, as it seems to affect some operations but does not in fact modify the all-important coordinate transformations.  This change removes setCenterPixel and the _centerPixel data member, and instead implements getCenterPixel by computing the center pixel of the bounding box, just as getPixelFromPosition and getPositionFromPixel do.
        
        I have also removed methods that relied on the old, inconsistent definition of _centerPixel, including DetectorMosaic::findDetectorPixel, which purports to find the detector that contains a point in pixel coordinates.  At some level, that's clearly nonsensical, because e.g. all CCDs in a camera will have a (0,0) pixel.  I'm not sure it was used for anything other than circular unit tests.
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    60edffcc

    commit 60edffccd7fc85402e9e6f1c0e5fa0021f9af237
    Author: rhl 
    Date:   Tue Jan 5 22:24:46 2010 +0000
    
        Initial implementation of cameraGeom up to Ccd/Detector
    

    d95640da

    commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
    Author: Kendrick Smith 
    Date:   Tue Feb 19 23:44:14 2013 -0500
    
        move afw::image::XYTransform -> afw::geom::XYTransform
             afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
             afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
        
        wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom
    

    d30faf6b

    commit d30faf6b4da3af0340b2535ce9d319ec1470b3f3
    Author: rhl 
    Date:   Sun Jan 17 15:02:36 2010 +0000
    
        Add support for bad columns; some icc cleanup
    

    f846bf5f

    commit f846bf5f70d586fbc1d57759baddd6182dbf4c6a
    Author: rhl 
    Date:   Thu Jan 7 14:14:46 2010 +0000
    
        Worked on camera geometry and building a Camera as an Raft of Rafts
    

    06309dc2

    commit 06309dc2c9dbc3abe69f66c040ae75a1950eee14
    Author: Russell Owen 
    Date:   Thu Jun 13 16:25:55 2013 -0700
    
        Fix the remaining build warning (for rotateBBoxBy90, which was due to prepending
        lsst::afw::cameraGeom to the name in the .cc file) and centralize the doxygen documentation
        for it in the .h file (the documentation was shared between the .cc and .h files
        and the former was more complete).
    

    e193729a

    commit e193729ad24e2b0d48b1abcd0ddb2aaad6ba4188
    Author: rhl 
    Date:   Wed Feb 23 12:27:29 2011 +0000
    
        Worked on cameraGeom; all pixel positions are now floating (to permit transfer of centroids to boresight coordinates)
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    Commits in /Users/nate/repos_lsst/afw/

    6f5ea58d

    commit 6f5ea58df69e1713505a44d25dbbd0e121bd6aff
    Author: Russell Owen 
    Date:   Tue Feb 18 11:25:54 2014 -0800
    
        Rename TransformRegistry to TransformMap and TransformMap to TransformMap::Transforms
    

    03b91f22

    commit 03b91f2271b901654ac340375900e33df79d669c
    Author: Russell Owen 
    Date:   Mon Mar 3 13:17:43 2014 -0800
    
        Allow == and != comparisons of CameraSys and CameraSysPrefix instances (which always return False
        if the classes are different). The SWIG is a bit verbose, but it works.
        Test this change.
        Add Detector.getCenter(CameraSys) and a test for it.
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    4384a0a2

    commit 4384a0a2406e91369beef236ede8a30bff0b122a
    Author: Russell Owen 
    Date:   Tue Jan 28 12:33:00 2014 -0800
    
        Detector: added missing accessors for amplifiers (including adding an internal unordered_map
        for fast access by name).
        Amplifier and RawAmplifier: marked methods const.
        TransformRegistry: switched to explicitly using boost::unordered_map.
    

    18439e6c

    commit 18439e6c1fd05dc7d44b17a6178ef0de5c1b7e38
    Author: Russell Owen 
    Date:   Fri Feb 14 09:30:39 2014 -0800
    
        Detector tests pass.
    

    7911ee94

    commit 7911ee946edad9f1f95b38049679799efe317cd6
    Author: Russell Owen 
    Date:   Thu Feb 20 13:47:43 2014 -0800
    
        Added getCorners method to Box2D and Box2I C++ (and removed Python-only version).
        Updated Detector.cc to use it.
    

    e6a90084

    commit e6a90084e77396fe175f998cf9c3dd13a175ff4f
    Author: Russell Owen 
    Date:   Fri Jan 31 11:11:19 2014 -0800
    
        Fixed Detector.convert's handling of CameraSysPrefix.
        Improved SWIG files, getting rename and ignore to work in most cases
        (TransformRegistry still needs %extend to handle operator[] for reasons I don't understand).
        Finished detector unit test.
    

    5046e7f3

    commit 5046e7f3f0a4f8591e21a396b1e1ee0dd205f659
    Author: Russell Owen 
    Date:   Thu Feb 13 17:35:58 2014 -0800
    
        Got the basics of AmpInfo catalogs working.
        However, I don't know how to SWIG-wrap ConstAmpInfoCatalog, and it looks messy,
        so I will try making Detector's constructor take a non-const catalog
        and copying that internally to a const catalog. (I should then test that
        changing the original catalog does not change the one inside Detector).
    

    d1426bf7

    commit d1426bf78a5f78cf0d9487ac3fc83f75c66a01d1
    Author: Russell Owen 
    Date:   Mon Mar 10 14:28:23 2014 -0700
    
        Added id field to Detector and propagated the changes through to DetectorCollection.
    

    5caed4f7

    commit 5caed4f7bfef8ecaf1daec5e793c09f9d0ca990a
    Author: Russell Owen 
    Date:   Wed Feb 19 17:51:36 2014 -0800
    
        Fixed a bug in the list version of TransformMap.transform
        Added a unit test for the above.
        Added bbox argument to Detector's constructor.
        Added getBBox and getCorners methods to Detector, and unit tests for same.
    

    dab65f42

    commit dab65f422ed168d8b81f8b23fad67b62dca8b506
    Author: Russell Owen 
    Date:   Thu Apr 2 14:03:20 2015 -0700
    
        Add hasTransform and getTransform to cameraGeom Detector
        
        Add overloaded member functions hasTransform and getTransform to cameraGeom Detector,
        which accept a CameraSys or a CameraSysPrefix. This greatly simplifies getting
        appropriate transforms from the detector's transform map, since one need not explicitly
        first generate a CameraSys for that detector.
        Added a test for the new functions to testDetector.py.
        Made a minor improvement to documentation in TransformMap.h
        
        Fix grammatical errors in two doc strings.
    

    Return to list

    include/lsst/afw/coord/Observatory.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #if !defined(LSST_AFW_COORD_OBSERVATORY_H)
                    #define LSST_AFW_COORD_OBSERVATORY_H
                    /**
                     * @file
                     * @brief Class to hold observatory information
                     * @ingroup afw
                     * @author Steve Bickerton
                     *
                     *
                     */ 
                    
                    #include 
    
    37 d304da93 - #include "lsst/afw/coord/Utils.h"
    #include "lsst/afw/geom/Angle.h" namespace lsst { namespace afw { namespace coord { /** * @class Observatory * @brief Store information about an observatory ... lat/long, elevation */ class Observatory { public: Observatory(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude, double const elevation); Observatory(std::string const longitude, std::string const latitude, double const elevation); void setLatitude(lsst::afw::geom::Angle const latitude); void setLongitude(lsst::afw::geom::Angle const longitude); void setElevation(double const elevation); lsst::afw::geom::Angle getLatitude() const; lsst::afw::geom::Angle getLongitude() const; double getElevation() const { return _elevation; } std::string getLatitudeStr() const; std::string getLongitudeStr() const; bool operator==(Observatory const& rhs) const { return ((_latitude - rhs._latitude) == 0.0) && ((_longitude - rhs._longitude) == 0.0) && ((_elevation - rhs._elevation) == 0.0); } bool operator!=(Observatory const& rhs) const { return !(*this == rhs); } private: lsst::afw::geom::Angle _latitude; lsst::afw::geom::Angle _longitude; double _elevation; }; std::ostream & operator<<(std::ostream &os, Observatory const& obs); }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d304da93

    commit d304da93ccf6b9879ea8a52bd737816b61d5eca6
    Author: bick 
    Date:   Thu Mar 11 23:55:19 2010 +0000
    
        Added point3d.
    

    Commits in /Users/nate/repos_lsst/afw/

    Return to list

    include/lsst/afw/image/TanWcs.h

    Diff:

                    // -*- lsst-c++ -*-
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    #ifndef LSST_AFW_IMAGE_TANWCS_H
                    #define LSST_AFW_IMAGE_TANWCS_H
                    
                    #include "Eigen/Core"
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/daf/base/Persistable.h"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/geom/AffineTransform.h"
                    #include "lsst/afw/image/Wcs.h"
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/geom/Extent.h"
                    
                    struct wcsprm;                          // defined in wcs.h
                    
                    namespace lsst {
                    namespace daf {
                        namespace base {
                            class PropertySet;
                        }
                    }
                    namespace afw {
                        namespace formatters {
                            class TanWcsFormatter;
                        }
                    namespace image {
                    
                    /**
                     *  @brief Implementation of the WCS standard for the special case of the Gnomonic
                     *  (tangent plane) projection.
                     * 
                     *  This class treats the special case of tangent plane projection. It extends the Wcs standard by
                     *  optionally accounting for distortion in the image plane using the Simple Imaging Polynomial (SIP)
                     *  convention.
                     *  This convention is described in Shupe et al. (2005) (Astronomical Data Analysis Software and Systems
                     *  XIV, Asp Conf. Series Vol XXX, Ed: Shopbell et al.), and descibed in some more detail in
                     *  http://web.ipac.caltech.edu/staff/fmasci/home/wise/codeVdist.html
                     * 
                     *  To convert from pixel coordintates to radec ("intermediate world coordinates"), first use the matrices
                     *  _sipA and _sipB to calculate undistorted coorinates (i.e where on the chip the image would lie if
                     *  the optics gave undistorted images), then pass these undistorted coorinates wcsp2s() to calculate radec.
                     * 
                     *  For the reverse, radec -> pixels, convert the radec to undistorted coords, and then use the _sipAp and
                     *  _sipBp matrices to add in the distortion terms.
                     */
                    class TanWcs : public afw::table::io::PersistableFacade, public lsst::afw::image::Wcs {
                    public:
                        typedef boost::shared_ptr Ptr;
                        typedef boost::shared_ptr ConstPtr;
                    
                        /// Decode the SIP headers for a given matrix, if present.
                        static void decodeSipHeader(
                            daf::base::PropertySet const & fitsMetadata,
                            std::string const & which,
                            Eigen::MatrixXd & m
                        );
                    
                        /**
                         *  @brief Construct a tangent plane wcs without distortion terms
                         *
                         *  @param crval    The sky position of the reference point
                         *  @param crpix    The pixel position corresponding to crval in Lsst units
                         *  @param cd       Matrix describing transformations from pixel to sky positions
                         *  @param equinox  Equinox of coordinate system, eg 2000 (Julian) or 1950 (Besselian)
                         *  @param raDecSys System used to describe right ascension or declination, e.g FK4, FK5 or ICRS
                         *  @param cunits1  Units of sky position. One of deg, arcmin or arcsec
                         *  @param cunits2  Units of sky position. One of deg, arcmin or arcsec
                         */
                        TanWcs(
                            geom::Point2D const & crval, geom::Point2D const & crpix,
                            Eigen::Matrix2d const & cd,
                            double equinox=2000, std::string const & raDecSys="FK5",
                            std::string const & cunits1="deg", std::string const & cunits2="deg"
                        );
                    
                        /**
                         *  @brief Construct a tangent plane wcs with distortion terms
                         *
                         *  @param crval    The sky position of the reference point
                         *  @param crpix    The pixel position corresponding to crval in Lsst units
                         *  @param cd       Matrix describing transformations from pixel to sky positions
                         *  @param sipA     Forward distortion matrix for axis 1
                         *  @param sipB     Forward distortion matrix for axis 2
                         *  @param sipAp    Reverse distortion matrix for axis 1
                         *  @param sipBp    Reverse distortion matrix for axis 2
                         *  @param equinox  Equinox of coordinate system, eg 2000 (Julian) or 1950 (Besselian)
                         *  @param raDecSys System used to describe right ascension or declination, e.g FK4, FK5 or ICRS
                         *  @param cunits1  Units of sky position. One of deg, arcmin or arcsec
                         *  @param cunits2  Units of sky position. One of deg, arcmin or arcsec
                         */
                        TanWcs(
                            geom::Point2D const & crval, geom::Point2D const & crpix,
                            Eigen::Matrix2d const & cd,
                            Eigen::MatrixXd const & sipA,
                            Eigen::MatrixXd const & sipB,
                            Eigen::MatrixXd const & sipAp,
                            Eigen::MatrixXd const & sipBp,
                            double equinox=2000, std::string const & raDecSys="FK5",
                            std::string const & cunits1="deg", std::string const & cunits2="deg"
                        );
                    
                        virtual ~TanWcs() {};
                    
                        /// Polymorphic deep-copy.
                        virtual PTR(Wcs) clone() const;
                    
                        /// Returns the pixel scale, in Angle/pixel.
                        geom::Angle pixelScale() const;
                    
                        /// Applies the SIP AP and BP distortion (used in the skyToPixel direction)
                        // NOTE that this accepts and returns FITS-style 1-indexed pixel coords, NOT LSST style 0-indexed
                        geom::Point2D distortPixel(geom::Point2D const & pixel) const;
                    
                        /// Applies the SIP A and B un-distortion (used in the pixelToSky direction)
                        // NOTE that this accepts and returns FITS-style 1-indexed pixel coords, NOT LSST style 0-indexed
                        geom::Point2D undistortPixel(geom::Point2D const & pixel) const;
                    
                        bool hasDistortion() const { return _hasDistortion;};
                    
                        PTR(daf::base::PropertyList) getFitsMetadata() const;
                    
                    
                        /**
                         *  @brief Set the distortion matrices
                         *
                         *  @param sipA  Forward distortion matrix for 1st axis
                         *  @param sipB  Forward distortion matrix for 2nd axis
                         *  @param sipAp Reverse distortion matrix for 1st axis
                         *  @param sipBp Reverse distortion matrix for 2nd axis
                         *
                         *  Because the base class provides the option of creating a Wcs without distortion coefficients
                         *  we supply a way of setting them here. This also help make code neater by breaking an
                         *  enormous constructor (above) into two small pieces.
                         */
                        void setDistortionMatrices(
                            Eigen::MatrixXd const & sipA,
                            Eigen::MatrixXd const & sipB,
                            Eigen::MatrixXd const & sipAp,
                            Eigen::MatrixXd const & sipBp
                        );
                    
    
    164 a0b9d98c + protected:
    165 a0b9d98c +
    166 a0b9d98c + TanWcs(TanWcs const & rhs);
    167 a0b9d98c +
    168 a0b9d98c + virtual void pixelToSkyImpl(double pixel1, double pixel2, geom::Angle skyTmp[2]) const;
    169 a0b9d98c + virtual geom::Point2D skyToPixelImpl(geom::Angle sky1, geom::Angle sky2) const;
    170 a0b9d98c +
    private: friend PTR(Wcs) makeWcs(PTR(daf::base::PropertySet) const& metadata, bool); friend class TanWcsFactory; virtual std::string getPersistenceName() const; virtual void write(OutputArchiveHandle & handle) const; virtual bool _isSubset(Wcs const &) const; // Create an empty, invalid TanWcs. Only used by TanWcsFormatter. TanWcs(); /* * Create a Wcs from a fits header. * * Don't call this directly. Use makeWcs() instead, which will figure out which (if any) * sub-class of Wcs is appropriate. */ TanWcs(CONST_PTR(daf::base::PropertySet) const & fitsMetadata);
    187 473b834b - TanWcs(TanWcs const & rhs);
    188 473b834b -
    TanWcs(afw::table::BaseRecord const & mainRecord, CONST_PTR(afw::table::BaseRecord) sipRecord); TanWcs & operator = (const TanWcs &);
    192 473b834b -
    193 473b834b - virtual void pixelToSkyImpl(double pixel1, double pixel2, geom::Angle skyTmp[2]) const;
    194 473b834b - virtual geom::Point2D skyToPixelImpl(geom::Angle sky1, geom::Angle sky2) const;
    //Allow the formatter to access private goo LSST_PERSIST_FORMATTER(lsst::afw::formatters::TanWcsFormatter) bool _hasDistortion; Eigen::MatrixXd _sipA, _sipB, _sipAp, _sipBp; }; }}} // namespace lsst::afw::image #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    473b834b

    commit 473b834bd398778eb0bf090b3a6da22e5a4d504a
    Author: Jim Bosch 
    Date:   Mon Nov 26 14:06:58 2012 -0500
    
        Lots of cleanup for TanWcs.
        
        Includes:
         - Indentation
         - Doxygen moved to .h file, made prettier.
         - Replace some pass-by-const-value with pass-by-const-reference.
         - Make decodeSipHeaders public (will reduce code duplication in meas_mosaic in future).
    

    Commits in /Users/nate/repos_lsst/afw/

    a0b9d98c

    commit a0b9d98c33134ce69b177a9b6b6260de9f2bccfd
    Author: Russell Owen 
    Date:   Thu Jan 22 17:41:16 2015 -0800
    
        Added DistortedTanWcs and a unit test.
        
        fixup! Added DistortedTanWcs and a preliminary unit test.
        
        Fixed some incorrect names in DistortedTanWcs and improved argument names accordingly.
        
        Ignore _build files
    

    Return to list

    include/lsst/afw/cameraGeom.h

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
    
    23 60edffcc - #if !defined(LSST_IP_ISR_CAMERAGEOM_H)
    ? ^^^^^^
    23 dabee87e + #if !defined(LSST_AFW_CAMERAGEOM_H)
    ? ^^^
    24 60edffcc - #define LSST_IP_ISR_CAMERAGEOM_H
    ? ^^^^^^
    24 dabee87e + #define LSST_AFW_CAMERAGEOM_H
    ? ^^^
    26 60edffcc - #include "lsst/afw/cameraGeom/Id.h"
    27 60edffcc - #include "lsst/afw/cameraGeom/Amp.h"
    ? ^ ^
    26 7b9f89c5 + #include "lsst/afw/cameraGeom/CameraSys.h"
    ? ^^ ^^^^^^
    28 e88ff0cd - #include "lsst/afw/cameraGeom/FpPoint.h"
    ? ^^
    27 7b9f89c5 + #include "lsst/afw/cameraGeom/CameraPoint.h"
    ? ^^^^^^ #include "lsst/afw/cameraGeom/Detector.h"
    30 fcffe104 - #include "lsst/afw/cameraGeom/DetectorMosaic.h"
    31 60edffcc - #include "lsst/afw/cameraGeom/Ccd.h"
    32 1ac3f936 - #include "lsst/afw/cameraGeom/Raft.h"
    33 12fe8a71 - #include "lsst/afw/cameraGeom/Camera.h"
    34 9a0b3ed0 - #include "lsst/afw/cameraGeom/Distortion.h"
    ? ^ ^ ^^
    29 7b9f89c5 + #include "lsst/afw/cameraGeom/Orientation.h"
    ? ^^ ^^ ^ #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9a0b3ed0

    commit 9a0b3ed09fa81b663487c75696e7198af0cf257d
    Author: bick 
    Date:   Fri Aug 26 23:03:09 2011 +0000
    
        #1753 (not yet working) distortion stuff initial check-in.
    

    e88ff0cd

    commit e88ff0cd6d8b7e3b4173c8fd71f33e78b407c782
    Author: Steven Bickerton 
    Date:   Tue Jan 31 10:02:20 2012 -0600
    
        split FpPosition to FpPoint/Extent.
    

    12fe8a71

    commit 12fe8a71ecd4720374bcfabd70c42c7108607f97
    Author: rhl 
    Date:   Fri Jan 8 00:33:43 2010 +0000
    
        Made Camera a real C++ object, not just a python alias for Raft
    

    1ac3f936

    commit 1ac3f9368c1453487cfea8334ba310c339552ede
    Author: rhl 
    Date:   Wed Jan 6 19:59:28 2010 +0000
    
        Initial version of Raft code
    

    60edffcc

    commit 60edffccd7fc85402e9e6f1c0e5fa0021f9af237
    Author: rhl 
    Date:   Tue Jan 5 22:24:46 2010 +0000
    
        Initial implementation of cameraGeom up to Ccd/Detector
    

    fcffe104

    commit fcffe104d0facbb57b73c22ba5d2ee6cd6e1e29d
    Author: rhl 
    Date:   Thu Jan 7 15:33:24 2010 +0000
    
        Move Raft implementation into DetectorMosaic
    

    Commits in /Users/nate/repos_lsst/afw/

    dabee87e

    commit dabee87ebd82283629d6941dd0786857aea304ca
    Author: Russell Owen 
    Date:   Sat Jan 25 15:26:33 2014 -0800
    
        Removed old code and fixed many C++ errors in the new code.
    

    7b9f89c5

    commit 7b9f89c5d3a8bdedaf50793abaf4d5322716b892
    Author: Russell Owen 
    Date:   Mon Jan 27 16:31:54 2014 -0800
    
        Switch TransformRegistry to unordered_map.
        It all builds but the swig wrapper for cameraGeom isn't working due to a missing symbol.
    

    Return to list

    src/math/AnalyticKernel.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/KernelPersistenceHelper.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwMath = lsst::afw::math;
                    namespace afwImage = lsst::afw::image;
                    
                    afwMath::AnalyticKernel::AnalyticKernel()
                    :
                        Kernel(),
                        _kernelFunctionPtr()
                    {}
                    
                    afwMath::AnalyticKernel::AnalyticKernel(
                        int width,
                        int height,
                        KernelFunction const &kernelFunction,
                        Kernel::SpatialFunction const &spatialFunction
                    ) :
                        Kernel(width, height, kernelFunction.getNParameters(), spatialFunction),
                        _kernelFunctionPtr(kernelFunction.clone())
                    {}
                    
                    afwMath::AnalyticKernel::AnalyticKernel(
                        int width,
                        int height,
                        KernelFunction const &kernelFunction,
                        std::vector const &spatialFunctionList
                    ) :
                        Kernel(width, height, spatialFunctionList),
                        _kernelFunctionPtr(kernelFunction.clone())
                    {
                        if (kernelFunction.getNParameters() != spatialFunctionList.size()) {
                            std::ostringstream os;
                            os << "kernelFunction.getNParameters() = " << kernelFunction.getNParameters()
                                << " != " << spatialFunctionList.size() << " = " << "spatialFunctionList.size()";
    
    64 d7b24982 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    64 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } } PTR(afwMath::Kernel) afwMath::AnalyticKernel::clone() const { PTR(afwMath::Kernel) retPtr; if (this->isSpatiallyVarying()) { retPtr.reset(new afwMath::AnalyticKernel(this->getWidth(), this->getHeight(), *(this->_kernelFunctionPtr), this->_spatialFunctionList)); } else { retPtr.reset(new afwMath::AnalyticKernel(this->getWidth(), this->getHeight(), *(this->_kernelFunctionPtr))); } retPtr->setCtr(this->getCtr()); return retPtr; } double afwMath::AnalyticKernel::computeImage( lsst::afw::image::Image &image, bool doNormalize, double x, double y ) const { afwGeom::Extent2I llBorder = (image.getDimensions() - getDimensions()) / 2; image.setXY0(afwGeom::Point2I(-afwGeom::Extent2I(getCtr()+ llBorder))); if (this->isSpatiallyVarying()) { this->setKernelParametersFromSpatialModel(x, y); } return doComputeImage(image, doNormalize); } afwMath::AnalyticKernel::KernelFunctionPtr afwMath::AnalyticKernel::getKernelFunction( ) const { return _kernelFunctionPtr->clone(); } std::string afwMath::AnalyticKernel::toString(std::string const& prefix) const { std::ostringstream os; os << prefix << "AnalyticKernel:" << std::endl; os << prefix << "..function: " << (_kernelFunctionPtr ? _kernelFunctionPtr->toString() : "None") << std::endl; os << Kernel::toString(prefix + "\t"); return os.str(); } std::vector afwMath::AnalyticKernel::getKernelParameters() const { return _kernelFunctionPtr->getParameters(); } // // Protected Member Functions // double afwMath::AnalyticKernel::doComputeImage( afwImage::Image &image, bool doNormalize ) const { double imSum = 0; for (int y = 0; y != image.getHeight(); ++y) { double const fy = image.indexToPosition(y, afwImage::Y); afwImage::Image::x_iterator ptr = image.row_begin(y); for (int x = 0; x != image.getWidth(); ++x, ++ptr) { double const fx = image.indexToPosition(x, afwImage::X); Pixel const pixelVal = (*_kernelFunctionPtr)(fx, fy); *ptr = pixelVal; imSum += pixelVal; } } if (doNormalize && (imSum != 1)) { if (imSum == 0) {
    134 92570c02 - throw LSST_EXCEPT(pexExcept::OverflowErrorException, "Cannot normalize; kernel sum is 0");
    ? ---------
    134 21597d88 + throw LSST_EXCEPT(pexExcept::OverflowError, "Cannot normalize; kernel sum is 0");
    } image /= imSum; imSum = 1; } return imSum; } void afwMath::AnalyticKernel::setKernelParameter(unsigned int ind, double value) const { _kernelFunctionPtr->setParameter(ind, value); } // ------ Persistence --------------------------------------------------------------------------------------- namespace lsst { namespace afw { namespace math { namespace { struct AnalyticKernelPersistenceHelper : public Kernel::PersistenceHelper { table::Key kernelFunction; explicit AnalyticKernelPersistenceHelper(int nSpatialFunctions) : Kernel::PersistenceHelper(nSpatialFunctions), kernelFunction( schema.addField( "kernelfunction", "archive ID for analytic function used to produce kernel images" ) ) {} explicit AnalyticKernelPersistenceHelper(table::Schema const & schema_) : Kernel::PersistenceHelper(schema_), kernelFunction(schema["kernelfunction"]) {} }; } // anonymous class AnalyticKernel::Factory : public afw::table::io::PersistableFactory { public: virtual PTR(afw::table::io::Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const { LSST_ARCHIVE_ASSERT(catalogs.size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); AnalyticKernelPersistenceHelper const keys(catalogs.front().getSchema()); afw::table::BaseRecord const & record = catalogs.front().front(); PTR(AnalyticKernel::KernelFunction) kernelFunction = archive.get(record.get(keys.kernelFunction)); PTR(AnalyticKernel) result; if (keys.spatialFunctions.isValid()) { result = boost::make_shared( record.get(keys.dimensions.getX()), record.get(keys.dimensions.getY()), *kernelFunction, keys.readSpatialFunctions(archive, record) ); } else { result = boost::make_shared( record.get(keys.dimensions.getX()), record.get(keys.dimensions.getY()), *kernelFunction ); } result->setCtr(record.get(keys.center)); return result; } explicit Factory(std::string const & name) : afw::table::io::PersistableFactory(name) {} }; namespace { std::string getAnalyticKernelPersistenceName() { return "AnalyticKernel"; } AnalyticKernel::Factory registration(getAnalyticKernelPersistenceName()); } // anonymous std::string AnalyticKernel::getPersistenceName() const { return getAnalyticKernelPersistenceName(); } void AnalyticKernel::write(OutputArchiveHandle & handle) const { AnalyticKernelPersistenceHelper const keys(_spatialFunctionList.size()); PTR(afw::table::BaseRecord) record = keys.write(handle, *this); record->set(keys.kernelFunction, handle.put(_kernelFunctionPtr.get())); } }}} // namespace lsst::afw::math

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    92570c02

    commit 92570c02a059d1547b68e84d8a7326f68938b71b
    Author: Russell Owen 
    Date:   Tue May 7 10:23:10 2013 -0700
    
        Implement ticket #2620: computeImage should set xy0.
        Removed the ability to pass a smaller image to LinearCombinationKernel::computeImage.
        AnalyticKernel::computeImage can still be called with an image of any dimensions,
        but only on that class; if you try to do this on a pointer or reference to Kernel
        then Kernel::computeImage is called,which rejects images whose dimensions do not match that of Kernel
        (Jim Bosch and I consider this a feature).
        Added a unit test to tests/kernel.py that exercises the dimension checking code.
        Moved some boilerplate code for computeImage into a protected member function doComputeImage
        and made Kernel::computeImage nonvirtual.
    

    d7b24982

    commit d7b24982db8562dc77c4bcc33c84107c65fd686d
    Author: rowen 
    Date:   Thu Oct 29 00:15:47 2009 +0000
    
        Fixed ticket #1000 by adding a missing test to a LinearCombinationKernel constructor.
        Updated tests/Kernel.cc as suggested by Serge so it would not trigger the problem.
        Updated many exceptions in kernel constructors to print more details.
        Added unit tests for the exceptions in kernel methods.
        
        Note: the current code has a swig warning about a shadowed constructor in LinearCombinationKernel.
        This should be resolved before committing the changes to the trunk. See my email to lsst-data.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/gpu/detail/CudaMemory.h

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008 - 2012 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * @file
                     *
                     * @brief Functions and a class to help allocating GPU global memory and transferring data to and from a GPU
                     *
                     * @author Kresimir Cosic
                     *
                     * Contents of this file are available only when GPU_BUILD is defined (i.e. when cuda_toolkit package is setup)
                     *
                     * requires:
                     *   - include 
                     *   - include 
                     *   - include "lsst/afw/gpu/detail/GpuBuffer2D.h"
                     *
                     * @ingroup afw
                     */
                    
                    #ifdef GPU_BUILD
                    
                    namespace lsst {
                    namespace afw {
                    namespace gpu {
                    namespace detail {
                    
                    /**
                     * \brief Allocates memory on GPU for an array
                     *
                     * \return Pointer to allocated GPU memory, or NULL on failure
                     *
                     * \arg size: specifies the number of elements of array that will be allocated
                     *
                     * Allocates a continuos block of GPU memory, and returns a GPU pointer to the allocated memory.
                     * If GPU memory allocation fails, returns NULL, so the return value should always be verified.
                     * Use function CopyToGpu() to copy data to the GPU into the allocated block, or CopyFromGpu()
                     * to copy data from the allocated GPU memory to local buffers.
                     *
                     * It is obligatory to free the allocated GPU memory with cudaFree() (available from cuda_runtime.h)
                     */
                    template
                    T* AllocOnGpu(int size)
                    {
                        T* dataGpu;
                        cudaError_t cudaError = cudaMalloc((void**)&dataGpu, size * sizeof(T));
                        if (cudaError != cudaSuccess) {
                            return NULL;
                        }
                        return dataGpu;
                    }
                    
                    /**
                     * \brief Copies an array of elements from GPU memory to an array in main memory
                     * \arg destCpu: pointer to the destination array (in main memory)
                     * \arg sourceGpu: pointer to the source array, in GPU memory
                     * \arg size: number of elements of the array to copy
                     *
                     * Copies data from GPU to CPU memory. destCpu should be a valid pointer into any allocated CPU memory,
                     * and sourceGpu should be a valid parameter into any allocated GPU memory.
                     *
                     * A failure to copy is generaly not expected. It could be due to invalid arguments,
                     * or due to CUDA or GPu device not being initialized properly, or not in a correct state.
                     *
    
    86 af8f5ebe - * \throw lsst::afw::math::detail::GpuMemoryException if data copying fails
    ? ^^^^^^ ^
    86 21597d88 + * \throw lsst::afw::math::detail::GpuMemoryError if data copying fails
    ? ^^ ^ */ template void CopyFromGpu(T* destCpu, T* sourceGpu, int size) { cudaError_t cudaError = cudaMemcpy( /* Desination:*/ destCpu, /* Source: */ sourceGpu, /* Size in bytes: */ size * sizeof(T), /* Direction */ cudaMemcpyDeviceToHost ); if (cudaError != cudaSuccess)
    98 af8f5ebe - throw LSST_EXCEPT(GpuMemoryException, "CopyFromGpu: failed");
    ? ^^^^^^ ^
    98 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "CopyFromGpu: failed");
    ? ^^ ^ } /** * \brief Copies an array of elements from main memory to GPU memory * \arg destGpu: pointer to the destination array, in GPU memory * \arg sourceCpu: pointer to the source array (in main memory) * \arg size: number of elements of the array to copy * * Copies data from CPU to GPU memory. destGpu should be a valid pointer into any allocated GPU memory, * and sourceCpu should be a valid parameter into any allocated CPU memory. * * A failure to copy is generaly not expected. It could be due to invalid arguments, * or due to CUDA or GPU device not being initialized properly, or not in a correct state. *
    113 af8f5ebe - * \throw lsst::afw::math::GpuMemoryException if data copying fails
    ? ^^^^^^ ^
    113 21597d88 + * \throw lsst::afw::math::GpuMemoryError if data copying fails
    ? ^^ ^ */ template void CopyToGpu(T* destGpu, T* sourceCpu, int size) { cudaError_t cudaError; cudaError = cudaMemcpy( /* Desination:*/ destGpu, /* Source: */ sourceCpu, /* Size in bytes: */ size * sizeof(T), /* Direction */ cudaMemcpyHostToDevice ); if (cudaError != cudaSuccess) {
    126 af8f5ebe - throw LSST_EXCEPT(GpuMemoryException, "CopyToGpu: failed");
    ? ^^^^^^ ^
    126 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "CopyToGpu: failed");
    ? ^^ ^ } } /** * \brief Transfers data from an array to the GPU * \arg sourceCpu: pointer to the source array (in CPU main memory) * \arg size: number of elements of the array to copy * \return Pointer to allocated GPU memory where data was transferred int, or NULL on GPU memory allocation failure * * Allocates a continuos block of GPU memory which will contain the transferred data, * and returns a GPU pointer to the allocated memory. Then copies data from CPU to GPU memory. * sourceCpu should be a valid parameter into any allocated CPU memory. * If GPU memory allocation fails, returns NULL, so the return value should always be verified. * Use function CopyFromGpu() to copy data from the allocated GPU memory to local buffers. * * It is obligatory to free the allocated GPU memory with cudaFree() (available from cuda_runtime.h) * * Throws exception if data copying fails. A failure to copy is generaly not expected. It could be due to * invalid arguments, or due to CUDA or GPU device not being initialized properly, or not in a correct state. *
    147 af8f5ebe - * \throw lsst::afw::math::GpuMemoryException if data copying fails
    ? ^^^^^^ ^
    147 21597d88 + * \throw lsst::afw::math::GpuMemoryError if data copying fails
    ? ^^ ^ */ template T* TransferToGpu(const T* sourceCpu, int size) { T* dataGpu; cudaError_t cudaError = cudaMalloc((void**)&dataGpu, size * sizeof(T)); if (cudaError != cudaSuccess) { return NULL; } cudaError = cudaMemcpy( /* Desination:*/ dataGpu, /* Source: */ sourceCpu, /* Size in bytes: */ size * sizeof(T), /* Direction */ cudaMemcpyHostToDevice ); if (cudaError != cudaSuccess) {
    164 af8f5ebe - throw LSST_EXCEPT(GpuMemoryException, "TransferToGpu: transfer failed");
    ? ^^^^^^ ^
    164 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "TransferToGpu: transfer failed");
    ? ^^ ^ } return dataGpu; } /** \brief A class for simplified GPU memory managment and copying data to and from a GPU Automatically releases GPU memory on destruction, simplifying GPU memory management The objects of this class have two states: free (when this->ptr == NULL) and bound (otherwise) free - this object is not bound to any GPU memory bound - a block of GPU memory has been allocated by this object and it is bound to it Some of the available functions change the state of this object from free to bound. Some of the functions can be called only in a particular state. When this object is destroyed, if it was in a bound state, it will free the allocated GPU memory block. The objects of this class are non-copyable */ template class GpuMemOwner { private: void operator=(const GpuMemOwner& rhs); public: GpuMemOwner(const GpuMemOwner& rhs) { assert(rhs.getPtr() == NULL); ptr=NULL; } T* ptr; ///> pointer to the allocated GPU memory block, or NULL int size; ///> size (as element count) of the allocated GPU memory block, valid whenever this->ptr != NULL /** \brief Creates a GpuMemOwner object in a free state (see GpuMemOwner class description) */ GpuMemOwner() : ptr(NULL) {} /** \brief returns the value of this->ptr */ T* getPtr() const { return ptr; } /** \brief returns the value of this->size */ int getSize() const { return size; } /** * \brief Transfers data from an array to the GPU * \arg source: pointer to the source array (in CPU main memory) * \arg size: number of elements of the array to copy * \return Pointer to allocated GPU memory where data was transferred into, or NULL on GPU mem. allocation failure * * \pre this->ptr must be NULL (this object must be in the free state, see class description) * * If transfer succeeds, this->ptr will be set to point to the GPU memory block where data was transferred into. * The same value (equal to this->ptr will be returned). It will change the * state of this object to bound. Sets this->size to the value of the argument size_p * If GPU memory allocation fails, returns NULL, and sets this->ptr to NULL, so the return value should * always be verified. * * Use member function CopyFromGpu() to copy data from the bound GPU memory. * * Also see function lsst:afw::gpu::detail::TransferToGpu(). * * Throws exception if data copying fails. A failure to copy is generaly not expected. It could be due to invalid * arguments, or due to CUDA or GPU device not being initialized properly, or not in a correct state. *
    233 af8f5ebe - * \throw lsst::afw::math::GpuMemoryException if data copying fails
    ? ^^^^^^ ^
    233 21597d88 + * \throw lsst::afw::math::GpuMemoryError if data copying fails
    ? ^^ ^ */ T* Transfer(const T* source, int size_p) { assert(ptr == NULL); size = size_p; ptr = TransferToGpu(source, size); return ptr; } /** * \brief Transfers data from an GpuBuffer2D to the GPU * \arg source: source GpuBuffer2D (in CPU main memory) * \return Pointer to allocated GPU memory where data was transferred into, or NULL on GPU mem. allocation failure * * \pre this->ptr must be NULL (this object must be in the free state, see class description) * * \copydetails GpuMemOwner::Transfer(const T* source, int size_p) *
    251 af8f5ebe - * \throw lsst::afw::math::GpuMemoryException if data copying fails
    ? ^^^^^^ ^
    251 21597d88 + * \throw lsst::afw::math::GpuMemoryError if data copying fails
    ? ^^ ^ */ T* Transfer(const GpuBuffer2D& source) { assert(ptr == NULL); size = source.Size(); ptr = TransferToGpu(source.img, size); return ptr; } /** * \brief Transfers data from a vector to the GPU * \arg source: source vector (in CPU main memory) * \return Pointer to allocated GPU memory where data was transferred into, or NULL on GPU mem. allocation failure * * \pre this->ptr must be NULL (this object must be in the free state, see class description) * * \copydetails GpuMemOwner::Transfer(const T* source, int size_p) *
    269 af8f5ebe - * \throw lsst::afw::math::GpuMemoryException if data copying fails
    ? ^^^^^^ ^
    269 21597d88 + * \throw lsst::afw::math::GpuMemoryError if data copying fails
    ? ^^ ^ */ T* TransferVec(const std::vector& source) { assert(ptr == NULL); size = int(source.size()); ptr = TransferToGpu(&source[0], size); return ptr; } /** * \brief Allocates GPU memory for an array * \arg size: number of elements of the array * \return Pointer to allocated GPU memory, or NULL on GPU memory allocation failure * * \pre this->ptr must be NULL (this object must be in the free state, see class description) * * If allocation succeeds, this->ptr will be set to point to the allocated GPU memory block. * The same value (equal to this->ptr will be returned). It will change the * state of this object to bound. Sets this->size to the value of the argument size_p * If GPU memory allocation fails, returns NULL, and sets this->ptr to NULL, so the return value should * always be verified. * * Use member function CopyFromGpu() to copy data from the bound GPU memory. * * Also see function lsst:afw::gpu::detail::AllocOnGpu(). */ T* Alloc(int size_p) { assert(ptr == NULL); size = size_p; ptr = AllocOnGpu(size); return ptr; } /** \brief Copies GpuBuffer2D data to bound GPU memory * * Also see lsst::afw::math::detail::CopyToGpu, which this function delegates to. */ T* CopyToGpu(detail::GpuBuffer2D& source) const { assert(ptr != NULL); assert(source.Size() == size); lsst::afw::gpu::detail::CopyToGpu(ptr, source.img, size); return ptr; } /** \brief Copies GpuBuffer2D data from bound GPU memory * * Also see lsst::afw::math::detail::CopyFromGpu, which this function delegates to. */ T* CopyFromGpu(detail::GpuBuffer2D& dest) const { assert(ptr != NULL); assert(dest.Size() == size); lsst::afw::gpu::detail::CopyFromGpu(dest.img, ptr, size); return ptr; } /** \brief Copies data from bound GPU memory to CPU memory * * Also see lsst::afw::gpu::detail::CopyFromGpu, which this function delegates to. */ T* CopyFromGpu(T* dest) const { assert(ptr != NULL); lsst::afw::gpu::detail::CopyFromGpu(dest, ptr, size); return ptr; } /** \brief Transfers data from an ImageBase to the GPU. The stride from ImageBase is retained. * * Also see ImageBase::Transfer() function, which this function delegates to. */ int TransferFromImageBase(const lsst::afw::image::ImageBase& img); /** \brief Allocates a block of GPU memory into which ImageBases' data can fit into. * * The stride required for data of a given ImageBase is taken into account. * * Also see ImageBase::Alloc() function, which this function delegates to. */ int AllocImageBaseBuffer(const lsst::afw::image::ImageBase& img); /** \brief Copies data from bound GPU memory into an ImageBase. * * The stride of ImageBase must be taken into account, and the easiest way to assure that * is to bind GPU memory with ImageBase::TransferFromImageBase() or ImageBase::AllocImageBaseBuffer() . * * Also see ImageBase::CopyFromGpu() function, which this function delegates to. */ void CopyToImageBase(lsst::afw::image::ImageBase& img) const; /** * \brief Frees bound GPU memory block * * If this object is in bound state, frees bound GPU memory. Otherwise does nothing. * Also see GpuMemOwner class description */ ~GpuMemOwner() { if (ptr != NULL) cudaFree(ptr); } }; }}}} // namespace lsst::afw::gpu::detail ends #endif //IS_GPU_BUILD

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    af8f5ebe

    commit af8f5ebef4f524d96fa4c824d3c8eb1cf11a6869
    Author: Kresimir Cosic 
    Date:   Mon Feb 27 03:39:36 2012 +0100
    
        Added afw::gpu namespace, reorganized files and interfaces to use this namespace
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/table/BaseRecord.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/table/BaseRecord.h"
                    #include "lsst/afw/table/SchemaMapper.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    namespace {
                    
                    // A Schema::forEach and SchemaMapper::forEach functor that copies data from one record to another.
                    struct CopyValue {
                    
                        template 
                        void operator()(Key const & inputKey, Key const & outputKey) const {
                            typename Field::Element const * inputElem = _inputRecord->getElement(inputKey);
                            std::copy(inputElem, inputElem + inputKey.getElementCount(), _outputRecord->getElement(outputKey));
                        }
                    
                        template 
                        void operator()(Key< Array > const & inputKey, Key< Array > const & outputKey) const {
                            if (inputKey.isVariableLength()) {
                                assert(outputKey.isVariableLength());
                                ndarray::Array value = ndarray::copy(_inputRecord->get(inputKey));
                                _outputRecord->set(outputKey, value);
                                return;
                            }
                            typename Field::Element const * inputElem = _inputRecord->getElement(inputKey);
                            std::copy(inputElem, inputElem + inputKey.getElementCount(), _outputRecord->getElement(outputKey));
                        }
                    
                        void operator()(Key const & inputKey, Key const & outputKey) const {
                            _outputRecord->set(outputKey, _inputRecord->get(inputKey));
                        }
                    
                        template 
                        void operator()(SchemaItem const & item) const {
                            (*this)(item.key, item.key);
                        }
                    
                        CopyValue(BaseRecord const * inputRecord, BaseRecord * outputRecord) :
                            _inputRecord(inputRecord), _outputRecord(outputRecord)
                        {}
                    
                    private:
                        BaseRecord const * _inputRecord;
                        BaseRecord * _outputRecord;
                    };
                    
                    } // anonymous
                    
                    void BaseRecord::assign(BaseRecord const & other) {
                        if (this->getSchema() != other.getSchema()) {
                            throw LSST_EXCEPT(
    
    57 12eb4fe1 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    57 21597d88 + lsst::pex::exceptions::LogicError,
    "Unequal schemas in record assignment." ); } this->getSchema().forEach(CopyValue(&other, this)); this->_assign(other); // let derived classes assign their own stuff } void BaseRecord::assign(BaseRecord const & other, SchemaMapper const & mapper) { if (!other.getSchema().contains(mapper.getInputSchema())) { throw LSST_EXCEPT(
    68 12eb4fe1 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    68 21597d88 + lsst::pex::exceptions::LogicError,
    "Unequal schemas between input record and mapper." ); } if (!this->getSchema().contains(mapper.getOutputSchema())) { throw LSST_EXCEPT(
    74 12eb4fe1 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    74 21597d88 + lsst::pex::exceptions::LogicError,
    "Unequal schemas between output record and mapper." ); } mapper.forEach(CopyValue(&other, this)); // use the functor we defined above this->_assign(other); // let derived classes assign their own stuff } }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    12eb4fe1

    commit 12eb4fe1168de7f45068342d279e5c85f679bd33
    Author: Jim Bosch 
    Date:   Mon Jan 23 18:54:33 2012 -0500
    
        started rewrite of RecordBase/TableBase with aim of fixing constness and inheritance with an extra layer of indirection
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/table/Catalog.i

    Diff:

                    /*
                     * Wrappers for CatalogT, instantiation of BaseCatalog, and macros used in wrapping other catalogs.
                     */
                    
                    %{
                    #include "lsst/afw/table/Catalog.h"
                    %}
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    template 
                    class CatalogT {
                    public:
                    
                        typedef typename RecordT::Table Table;
                        typedef typename RecordT::ColumnView ColumnView;
                    
                        PTR(Table) getTable() const;
                    
                        %feature("autodoc", "Return the table shared by all the catalog's records.") getTable;
                    
                        Schema getSchema() const;
                    
                        %feature("autodoc", "Shortcut for self.getTable().getSchema()") getSchema;
                    
                        explicit CatalogT(PTR(Table) const & table);
                    
                        explicit CatalogT(Schema const & table);
                    
                        CatalogT(CatalogT const & other);
                    
                        %feature(
                            "autodoc", 
                            "Constructors:  __init__(self, table) -> empty catalog with the given table\n"
                            "               __init__(self, schema) -> empty catalog with a new table with the given schema\n"
                            "               __init__(self, catalog) -> shallow copy of the given catalog\n"
                        ) CatalogT;
                    
                        void writeFits(std::string const & filename, std::string const & mode="w", int flags=0) const;
                        void writeFits(fits::MemFileManager & manager, std::string const & mode="w", int flags=0) const;
                    
                        static CatalogT readFits(std::string const & filename, int hdu=0, int flags=0);
                        static CatalogT readFits(fits::MemFileManager & manager, int hdu=0, int flags=0);
                    
                        ColumnView getColumnView() const;
                    
                        bool isContiguous() const;
                    
                        std::size_t capacity() const;
                    
                        void reserve(std::size_t n);
                    
                        void clear();
                    
                        %pythonappend getColumnView %{
                            self._columns = val
                        %}
                    
                        PTR(RecordT) addNew();
                    
                        %pythonprepend addNew %{
                            self._columns = None
                        %}
                    
                        CatalogT subset(ndarray::Array const & mask) const;
                    
                        CatalogT subset(std::ptrdiff_t start, std::ptrdiff_t stop, std::ptrdiff_t step) const;
                    
                        template 
                        bool isSorted(Key const & key) const;
                    
                        template 
                        void sort(Key const & key);
                    };
                    
                    %extend CatalogT {
                        std::size_t __len__() const { return self->size(); }
                        PTR(RecordT) __getitem__(std::ptrdiff_t i) const {
                            if (i < 0) i = self->size() + i;
                            if (std::size_t(i) >= self->size()) {
                                throw LSST_EXCEPT(
    
    82 05b57bc6 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    82 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Catalog index %d out of range.") % i).str() ); } return self->get(i); } void extend(CatalogT const & other, bool deep) { self->insert(self->end(), other.begin(), other.end(), deep); } void extend(CatalogT const & other, SchemaMapper const & mapper) { self->insert(mapper, self->end(), other.begin(), other.end()); } %feature("shadow") extend %{
    95 4df3fd5a - def extend(self, iterable, deep=None, mapper=None):
    ? ^^^
    95 31914a76 + def extend(self, iterable, deep=False, mapper=None):
    ? ^^^^ """Append all records in the given iterable to the catalog. Arguments: iterable ------ any Python iterable containing records deep ---------- if True, the records will be deep-copied; ignored if mapper is not None (that always implies True). mapper -------- a SchemaMapper object used to translate records """ self._columns = None
    105 f01f01a5 + # We can't use isinstance here, because the SchemaMapper symbol isn't available
    106 f01f01a5 + # when this code is part of a subclass of Catalog in another package.
    107 f01f01a5 + if type(deep).__name__ == "SchemaMapper":
    108 a9485a48 + mapper = deep
    109 a9485a48 + deep = None
    if isinstance(iterable, type(self)): if mapper is not None: $action(self, iterable, mapper) else: $action(self, iterable, deep) else: for record in iterable: if mapper is not None: self.append(self.table.copyRecord(record, mapper)) elif deep: self.append(self.table.copyRecord(record)) else: self.append(record.cast(self.Record)) %} %feature("shadow") __getitem__ %{ def __getitem__(self, k): """Return the record at index k if k is an integer, return a column if k is a string field name or Key, or return a subset of the catalog if k is a slice or boolean NumPy array. """ if type(k) is slice: (start, stop, step) = (k.start, k.stop, k.step) if step is None: step = 1 if start is None: start = 0 if stop is None: stop = len(self) return self.subset(start, stop, step) elif isinstance(k, numpy.ndarray): return self.subset(k) try: return $action(self, k) except TypeError: return self.columns[k] %} void __setitem__(std::ptrdiff_t i, PTR(RecordT) const & p) { if (i < 0) i = self->size() + i; if (std::size_t(i) >= self->size()) { throw LSST_EXCEPT(
    146 05b57bc6 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    151 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Catalog index %d out of range.") % i).str() ); } self->set(i, p); } void __delitem__(std::ptrdiff_t i) { if (i < 0) i = self->size() + i; if (std::size_t(i) >= self->size()) { throw LSST_EXCEPT(
    156 05b57bc6 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    161 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Catalog index %d out of range.") % i).str() ); } self->erase(self->begin() + i); } void append(PTR(RecordT) const & p) { self->push_back(p); } void insert(std::ptrdiff_t i, PTR(RecordT) const & p) { if (i < 0) i = self->size() + i; if (std::size_t(i) > self->size()) { throw LSST_EXCEPT(
    167 05b57bc6 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    172 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Catalog index %d out of range.") % i).str() ); } self->insert(self->begin() + i, p); } %feature("pythonprepend") __setitem__ %{ self._columns = None %} %feature("pythonprepend") __delitem__ %{ self._columns = None %} %feature("pythonprepend") append %{ self._columns = None %} %feature("pythonprepend") insert %{ self._columns = None %} %feature("shadow") writeFits %{ def writeFits(self, filename, mode='w', flags=0): """Write the catalog to a FITS binary table. @param[in] filename Name of the file to write or a MemFileManager object. @param[in] mode Write mode; one of 'w'=write (and clobber) or 'a'=append. @param[in] flags Subclass-defined flags to control the details of how the catalog is written. """ $action(self, filename, mode, flags) %} %pythoncode %{ def __getColumns(self): if not hasattr(self, "_columns") or self._columns is None: self._columns = self.getColumnView() return self._columns columns = property(__getColumns, doc="a column view of the catalog") def __iter__(self): for i in xrange(len(self)): yield self[i] def get(self, k): """Synonym for self[k]; provided for consistency with C++ interface.""" return self[k] def cast(self, type_, deep=False): """Return a copy of the catalog with the given type, optionally cloning the table and deep-copying all records if deep==True. """ if deep: table = self.table.clone() table.preallocate(len(self)) else: table = self.table newTable = table.cast(type_.Table) copy = type_(newTable) copy.extend(self, deep=deep) return copy def copy(self, deep=False): return self.cast(type(self), deep) def __getattribute__(self, name): # Catalog forwards unknown method calls to its table and column view # for convenience. (Feature requested by RHL; complaints about magic # should be directed to him.) # We have to use __getattribute__ because SWIG overrides __getattr__. try: return object.__getattribute__(self, name) except AttributeError: # self._columns is created the when self.columns is accessed - # looking for it in self.columns below would trigger infinite # recursion. if name == "_columns": raise try: return getattr(self.table, name) except AttributeError: return getattr(self.columns, name) table = property(getTable) schema = property(getSchema) def __reduce__(self): return lsst.afw.fits.reduceToFits(self) def find(self, value, key): """Return the record for which record.get(key) == value If no such record is found, return None; if multiple such records are found, return one of them. The catalog must be sorted by this key before this method is called. """ return _Catalog_find(self, value, key) def lower_bound(self, value, key): """Return the index of the first record for which record.get(key) >= value. If all elements in the catalog column are greater than or equal to the given value, returns 0; if all elements in the catalog are less than the given value, returns len(self). The catalog must be sorted by this key before this method is called. """ return _Catalog_lower_bound(self, value, key) def upper_bound(self, value, key): """Return the record for which record.get(key) == value If all elements in the catalog column are greater than the given value, returns 0; if all elements in the catalog are less or equal to the given value, returns len(self). The catalog must be sorted by this key before this method is called. """ return _Catalog_upper_bound(self, value, key) def between(self, lower, upper, key): """Return a slice object representing the records for which record.get(key) is between lower (inclusive) and upper(exclusive). The catalog must be sorted by this key before this method is called. """ return slice(self.lower_bound(lower, key), self.upper_bound(upper, key)) def equal_range(self, value, key): """Return a slice object representing the records for which record.get(key) is equal to the given value The catalog must be sorted by this key before this method is called. """ lower, upper = _Catalog_equal_range(self, value, key) return slice(lower, upper) %} } // See comments by definitions in Catalog.h for why these exist template PTR(RecordT) _Catalog_find(Catalog const & catalog, T value, Key const & key); template int _Catalog_lower_bound(Catalog const & catalog, T value, Key const & key); template int _Catalog_upper_bound(Catalog const & catalog, T value, Key const & key); template std::pair _Catalog_equal_range(Catalog const & catalog, T value, Key const & key); }}} // namespace lsst::afw::table %template(IntPair) std::pair; %define %instantiateCatalogSearchMethods(PREFIX, TMPL, TYPE) %template(_Catalog_find) lsst::afw::table::_Catalog_find< PREFIX ## Record, TMPL< PREFIX ## Record >, TYPE >; %template(_Catalog_lower_bound) lsst::afw::table::_Catalog_lower_bound< TMPL< PREFIX ## Record >, TYPE >; %template(_Catalog_upper_bound) lsst::afw::table::_Catalog_upper_bound< TMPL< PREFIX ## Record >, TYPE >; %template(_Catalog_equal_range) lsst::afw::table::_Catalog_equal_range< TMPL< PREFIX ## Record >, TYPE >; %enddef %define %instantiateCatalogSortMethods(TYPE) %template(isSorted) lsst::afw::table::CatalogT::isSorted< TYPE >; %template(sort) lsst::afw::table::CatalogT::sort< TYPE >; %enddef %instantiateCatalogSortMethods(boost::int32_t) %instantiateCatalogSortMethods(boost::int64_t) %instantiateCatalogSortMethods(float) %instantiateCatalogSortMethods(double) %instantiateCatalogSortMethods(lsst::afw::geom::Angle) // Macro that should be used to instantiate a Catalog type. %define %declareCatalog(TMPL, PREFIX) %pythondynamic TMPL< PREFIX ## Record >; %instantiateCatalogSearchMethods(PREFIX, TMPL, boost::int32_t) %instantiateCatalogSearchMethods(PREFIX, TMPL, boost::int64_t) %instantiateCatalogSearchMethods(PREFIX, TMPL, float) %instantiateCatalogSearchMethods(PREFIX, TMPL, double) %instantiateCatalogSearchMethods(PREFIX, TMPL, lsst::afw::geom::Angle) %template (PREFIX ## Catalog) TMPL< PREFIX ## Record >; typedef TMPL< PREFIX ## Record > PREFIX ## Catalog; %extend TMPL< PREFIX ## Record > { %pythoncode %{ Table = PREFIX ## Table Record = PREFIX ## Record ColumnView = PREFIX ## ColumnView %} } // Can't put this in class %extend blocks because they need to come after all class blocks in Python. %pythoncode %{ PREFIX ## Record.Table = PREFIX ## Table PREFIX ## Record.Catalog = PREFIX ## Catalog PREFIX ## Record.ColumnView = PREFIX ## ColumnView PREFIX ## Table.Record = PREFIX ## Record PREFIX ## Table.Catalog = PREFIX ## Catalog PREFIX ## Table.ColumnView = PREFIX ## ColumnView PREFIX ## ColumnView.Record = PREFIX ## Record PREFIX ## ColumnView.Table = PREFIX ## Table PREFIX ## ColumnView.Catalog = PREFIX ## Catalog %} %enddef

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4df3fd5a

    commit 4df3fd5a8256e34884656c918ca87911ca14b766
    Author: Jim Bosch 
    Date:   Wed Jun 13 23:57:49 2012 -0400
    
        Add functionality to Catalog.extend in Python to make use of a SchemaMapper and/or iterate in C++ when possible.
    

    05b57bc6

    commit 05b57bc6bd9d24100bcfa217a409a858e2e3c03e
    Author: Jim Bosch 
    Date:   Sat Jan 28 21:49:57 2012 -0500
    
        remove Set and SourceSet - too complicated; probably best to wait until we need Object
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    31914a76

    commit 31914a76119b90fbe2e1883c2b9a108b98a4d712
    Author: John Swinbank 
    Date:   Thu Dec 18 19:21:45 2014 -0500
    
        Use BaseCatalog.extend(..., deep=False) as default
        
        This is passed through Swig to C++ code, which requires a bool argument.
        
        Fix for DM-1710.
    

    a9485a48

    commit a9485a486e70ea83dece113adef1243e5ffddb0f
    Author: Jim Bosch 
    Date:   Wed Dec 31 11:17:25 2014 -0800
    
        Allow SchemaMapper as positional argument to Catalog.extend
    

    f01f01a5

    commit f01f01a542889ceae4ce889f66d885162f70ff2f
    Author: Jim Bosch 
    Date:   Wed Dec 31 18:20:39 2014 -0800
    
        Fix for downstream problem in ap introduced in DM-1514.
        
        The previous use of isinstance(deep, SchemaMapper) didn't work in ap,
        where Catalog is subclassed, because the SchemaMapper symbol isn't
        defined there.  And I couldn't figure out a way to import that symbol
        in ap without breaking afw.
    

    Return to list

    include/lsst/afw/table/Schema.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_Schema_h_INCLUDED
                    #define AFW_TABLE_Schema_h_INCLUDED
                    
                    #include 
                    
                    #include "boost/shared_ptr.hpp"
                    #include "boost/ref.hpp"
                    
                    #include "ndarray.h"
    
    11 5a8fd800 + #include "lsst/base.h"
    #include "lsst/afw/table/Key.h" #include "lsst/afw/table/Field.h" #include "lsst/afw/table/detail/SchemaImpl.h" #include "lsst/afw/table/Flag.h"
    16 5a8fd800 + #include "lsst/afw/table/AliasMap.h"
    namespace lsst { namespace afw { namespace table { class SubSchema; class BaseRecord; /** * @brief Defines the fields and offsets for a table. * * Schema behaves like a container of SchemaItem objects, mapping a descriptive Field object * with the Key object used to access record and ColumnView values. A Schema is the most * important ingredient in creating a table. * * Because offsets for fields are assigned when the field is added to the Schema, * Schemas do not support removing fields, though they do allow renaming. * * Field names in Schemas are expected to be dot-separated names (e.g. 'a.b.c'). The SubSchema * class and Schema::operator[] provide a heirarchical interface to these names, but are * implemented entirely as string splitting/joining operations that ultimately forward to * member functions that operate on the fully-qualified field name, so there is no requirement * that names be separated by periods, and no performance advantage to using a SubSchema. * * A SchemaMapper object can be used to define a relationship between two Schemas to be used * when copying values from one table to another or loading/saving selected fields to disk. * * Schema uses copy-on-write, and hence should always be held by value rather than smart pointer. * When creating a Python interface, functions that return Schema by const reference should be * converted to return by value (%returnCopy) to ensure proper memory management and encapsulation. */ class Schema { typedef detail::SchemaImpl Impl; public:
    50 4223afcb + // This variable is defined in SchemaImpl, but is replicated here as
    51 4223afcb + // a static so that it is available to SWIG.
    52 4223afcb + static int const DEFAULT_VERSION = detail::SchemaImpl::DEFAULT_VERSION;
    53 56df42d2 +
    /** * @brief Bit flags used when comparing schemas. * * All quantities are compared in insertion order, so if two schemas have the same * fields added in opposite order, they will not be considered equal. */ enum ComparisonFlags { EQUAL_KEYS =0x01, ///< Keys have the same types offsets, and sizes. EQUAL_NAMES =0x02, ///< Fields have the same names (ordered). EQUAL_DOCS =0x04, ///< Fields have the same documentation (ordered). EQUAL_UNITS =0x08, ///< Fields have the same units (ordered).
    65 1cdc3abd + EQUAL_FIELDS =0x0F, ///< Fields are identical (but aliases may not be).
    66 1cdc3abd + EQUAL_ALIASES =0x10, ///< Schemas have identical AliasMaps
    59 1c147ab4 - IDENTICAL =0x0F ///< Everything is the same.
    ? ^
    67 1cdc3abd + IDENTICAL =0x1F ///< Everything is the same.
    ? ^ };
    69 1c147ab4 +
    70 4899a4da + //@{
    71 4899a4da + /// Join strings using the field delimiter appropriate for this Schema's version
    72 4899a4da + std::string join(std::string const & a, std::string const & b) const;
    73 4899a4da + std::string join(std::string const & a, std::string const & b, std::string const & c) const {
    74 4899a4da + return join(join(a, b), c);
    75 4899a4da + }
    76 4899a4da + std::string join(
    77 4899a4da + std::string const & a, std::string const & b, std::string const & c, std::string const & d
    78 4899a4da + ) const {
    79 4899a4da + return join(join(a, b), join(c, d));
    80 4899a4da + }
    81 4899a4da + //@}
    /** * @brief Find a SchemaItem in the Schema by name. * * Names corresponding to named subfields are accepted, and will * return a SchemaItem whose field is copied from the parent field * with only the name changed. */ template SchemaItem find(std::string const & name) const; /** * @brief Find a SchemaItem in the Schema by key. * * Keys corresponding to named subfields are accepted, and will * return a SchemaItem whose field is copied from the parent field * with only the name changed. Keys corresponding to unnamed * subfields (such as array elements) are not accepted. */ template SchemaItem find(Key const & key) const; /**
    84 adb41ee9 - * @brief Lookup a (possibly incomplete) name in the Schema.
    105 02e44d9b + * @brief Look up a (possibly incomplete) name in the Schema.
    ? + * * See SubSchema for more information. * * This member function should generally only be used on * "finished" Schemas; modifying a Schema after a SubSchema * to it has been constructed will not allow the proxy to track * the additions, and will invoke the copy-on-write * mechanism of the Schema itself. */ SubSchema operator[](std::string const & name) const; /** * @brief Return a set of field names in the schema. * * If topOnly==true, return a unique list of only the part * of the names before the first period. For example, * if the full list of field names is ['a.b.c', 'a.d', 'e.f'], * topOnly==true will return ['a', 'e']. * * Returns an instance of Python's builtin set in Python.
    126 02e44d9b + *
    127 02e44d9b + * Aliases are not returned.
    */ std::set getNames(bool topOnly=false) const; /// @brief Return the raw size of a record in bytes. int getRecordSize() const { return _impl->getRecordSize(); } /// The total number of fields. int getFieldCount() const { return _impl->getFieldCount(); } /// The number of Flag fields. int getFlagFieldCount() const { return _impl->getFlagFieldCount(); } /// The number of non-Flag fields. int getNonFlagFieldCount() const { return _impl->getNonFlagFieldCount(); } /** * @brief Add a new field to the Schema, and return the associated Key. * * The offsets of fields are determined by the order they are added, but * may be not contiguous (the Schema may add padding to align fields, and how * much padding is considered an implementation detail). * * If doReplace is true and the field exists, it will be replaced instead of * throwing an exception. */ template Key addField(Field const & field, bool doReplace=false); /** * @brief Add a new field to the Schema, and return the associated Key. * * This is simply a convenience wrapper, equivalent to: * @code * addField(Field(name, doc, units, base), doReplace) * @endcode */ template Key addField( std::string const & name, std::string const & doc, std::string const & units = "", FieldBase const & base = FieldBase(), bool doReplace=false ) { return addField(Field(name, doc, units, base), doReplace); } /** * @brief Add a new field to the Schema, and return the associated Key. * * This is simply a convenience wrapper, equivalent to: * @code * addField(Field(name, doc, base), doReplace) * @endcode */ template Key addField( std::string const & name, std::string const & doc, FieldBase const & base, bool doReplace=false ) { return addField(Field(name, doc, base), doReplace); } /// @brief Replace the Field (name/description) for an existing Key. template void replaceField(Key const & key, Field const & field); /** * @brief Apply a functor to each SchemaItem in the Schema. * * The functor must have a templated or sufficiently overloaded operator() that supports * SchemaItems of all supported field types - even those that are not present in this * particular Schema. * * The functor will be passed by value by default; use boost::ref to pass it by reference. * * Fields will be processed in the order they were added to the schema. */ template void forEach(F func) const { Impl::VisitorWrapper::type &> visitor(func); std::for_each(_impl->getItems().begin(), _impl->getItems().end(), visitor); } //@{ /** * @brief Equality comparison * * Schemas are considered equal according the standard equality operator if their sequence * of keys are identical (same types with the same offsets); names and descriptions of * fields are not considered. For a more precise comparison, use compare() or contains(). */ bool operator==(Schema const & other) const { return compare(other, EQUAL_KEYS); } bool operator!=(Schema const & other) const { return !this->operator==(other); } //@} /** * @brief Do a detailed equality comparison of two schemas. * * See ComparisonFlags for a description of the possible return values * * @param[in] other The other schema to compare to. * @param[in] flags Which types of comparisions to perform. Flag bits not present here * will never be returned. */ int compare(Schema const & other, int flags=EQUAL_KEYS) const; /** * @brief Test whether the given schema is a subset of this. * * This function behaves very similarly to compare(), but ignores fields that are present * in this but absent in other. */ int contains(Schema const & other, int flags=EQUAL_KEYS) const; /** * @brief Return true if the given item is in this schema. * * The flags must include the EQUAL_KEYS bit, and if the item cannot be found by key no bits * will be set on return. */ template int contains(SchemaItem const & item, int flags=EQUAL_KEYS) const;
    249 5a8fd800 + /**
    250 5a8fd800 + * Return the map of aliases
    251 02e44d9b + *
    252 5a8fd800 + * Note that while this is a const method, it does allow the Schema's aliases to be
    253 5a8fd800 + * edited - this allows the aliases to be modified even after a Table has been constructed
    254 5a8fd800 + * from the Schema.
    255 02e44d9b + *
    256 5a8fd800 + * See AliasMap for more information on schema aliases.
    257 02e44d9b + */
    258 a7452ce2 + PTR(AliasMap) getAliasMap() const { return _aliases; }
    259 02e44d9b +
    260 5a8fd800 + /**
    261 5a8fd800 + * Set the alias map
    262 5a8fd800 + *
    263 5a8fd800 + * This resets the internal pointer to the alias map, disconnecting
    264 5a8fd800 + * this schema from any others it shares aliases with.
    265 5a8fd800 + *
    266 5a8fd800 + * Passing a null pointer is equivalent to passing an empty map.
    267 5a8fd800 + */
    268 a7452ce2 + void setAliasMap(PTR(AliasMap) aliases);
    269 02e44d9b +
    270 5a8fd800 + /// Sever the connection between this schema and any others with which it shares aliases
    271 5a8fd800 + void disconnectAliases();
    272 02e44d9b +
    /// @brief Construct an empty Schema.
    274 56df42d2 + Schema();
    275 56df42d2 +
    276 56df42d2 + /// @brief Construct an empty Schema with the given version.
    227 dbc20e58 - explicit Schema();
    277 56df42d2 + explicit Schema(int version);
    ? +++++++++++ /// @brief Copy constructor.
    230 47a82785 - Schema(Schema const & other) : _impl(other._impl) {}
    280 5a8fd800 + Schema(Schema const & other);
    /** * @brief Construct from a PropertyList, interpreting it as a FITS binary table header. * * @param[in,out] metadata PropertyList that contains the FITS header keys * corresponding to a binary table extension. We can't * use a PropertySet here, because the order does matter. * @param[in] stripMetadata If true, the keys used to define the schema will be removed * from the PropertySet. * * If the column types in the FITS header are not compatible with Schema field types, * of if some required keys (TTYPEn, TFORMn) are not present for some columns, * afw::fits::FitsError will be thrown. * * This constructor does not support strong exception safety guarantee when stripMetadata is True; * the PropertyList may be modified when an exception is thrown. */ explicit Schema(daf::base::PropertyList & metadata, bool stripMetadata); /** * @brief Construct from a PropertyList, interpreting it as a FITS binary table header. * * @param[in,out] metadata PropertyList that contains the FITS header keys * corresponding to a binary table extension. We can't * use a PropertySet here, because the order does matter. * * If the column types in the FITS header are not compatible with Schema field types, * of if some required keys (TTYPEn, TFORMn) are not present for some columns, * afw::fits::FitsError will be thrown. * * This overload never strips metadata, allowing it to accept a const PropertyList. */ explicit Schema(daf::base::PropertyList const & metadata); /// Stringification. friend std::ostream & operator<<(std::ostream & os, Schema const & schema); /// @brief Get the Citizen corresponding to this Schema (SchemaImpl is what inherits from Citizen). daf::base::Citizen & getCitizen() { return *_impl; }
    321 bd692192 + /// @brief Return the table's version.
    322 bd692192 + int getVersion() const { return _impl->getVersion(); }
    323 bd692192 +
    324 bd692192 + /// @brief Set the table's version.
    325 bd692192 + void setVersion(int version) { _edit();_impl->setVersion(version); }
    326 bd692192 +
    private: friend class detail::Access; friend class SubSchema;
    275 9d4a8b87 -
    331 02e44d9b +
    276 8270348f - /// @brief Copy on write; should be called by all mutators.
    332 d9cc4a85 + /// @brief Copy on write; should be called by all mutators (except for alias mutators).
    ? ++++++++++++++++++++++++++++ void _edit();
    279 4909a663 - boost::shared_ptr _impl;
    335 5a8fd800 + PTR(Impl) _impl;
    336 5a8fd800 + PTR(AliasMap) _aliases;
    }; /** * @brief A proxy type for name lookups in a Schema. * * Elements of schema names are assumed to be separated by periods ("a.b.c.d"); * an incomplete lookup is one that does not resolve to a field. Not that even * complete lookups can have nested names; a Point field, for instance, has "x" * and "y" nested names. * * This proxy object is implicitly convertible to both the appropriate Key type * and the appropriate Field type, if the name is a complete one, and supports * additional find() operations for nested names. * * SubSchema is implemented as a proxy that essentially calls Schema::find * after concatenating strings. It does not provide any performance advantage * over using Schema::find directly. It is also lazy, so looking up a name * prefix that does not exist within the schema is not considered an error * until the proxy is used. * * Some examples: * @code * Schema schema(false); * Key a_i = schema.addField("a.i", "integer field"); * Key< Point > a_p = schema.addField< Point >("a.p", "point field"); * * assert(schema["a.i"] == a_i); * SubSchema a = schema["a"]; * assert(a["i"] == a_i); * Field f_a_i = schema["a.i"]; * assert(f_a_i.getDoc() == "integer field"); * assert(schema["a.i"] == "a.i"); * assert(schema.find("a.p.x") == a_p.getX()); * @endcode */ class SubSchema { typedef detail::SchemaImpl Impl; public: /// @brief Find a nested SchemaItem by name. template SchemaItem find(std::string const & name) const; /// @brief Return a nested proxy. SubSchema operator[](std::string const & name) const; /// @brief Return the prefix that defines this SubSchema relative to its parent Schema. std::string const & getPrefix() const { return _name; } /** * @brief Return a set of nested names that start with the SubSchema's prefix. * * Returns an instance of Python's builtin set in Python. * @sa Schema::getNames */ std::set getNames(bool topOnly=false) const; /** * @brief Implicit conversion to the appropriate Key type. * * Implicit conversion operators cannot be translated to Python. Instead, the SWIG * wrappers provide an equivalent asKey() method. */ template
    344 4909a663 - operator Key() const { return _impl->find(_name).key; }
    401 46f8852c + operator Key() const { return _impl->find(_aliases->apply(_name)).key; }
    ? ++++++++++++++++ + /** * @brief Implicit conversion to the appropriate Key type. * * Implicit conversion operators cannot be translated to Python. Instead, the SWIG * wrappers provide an equivalent asField() method. */ template
    353 4909a663 - operator Field() const { return _impl->find(_name).field; }
    410 46f8852c + operator Field() const { return _impl->find(_aliases->apply(_name)).field; }
    ? ++++++++++++++++ + private: friend class Schema;
    359 9ccc92c4 - SubSchema(boost::shared_ptr const & data, std::string const & name) : _impl(data), _name(name) {}
    416 5a8fd800 + SubSchema(PTR(Impl) impl, PTR(AliasMap) aliases, std::string const & name);
    361 4909a663 - boost::shared_ptr _impl;
    418 5a8fd800 + PTR(Impl) _impl;
    419 5a8fd800 + PTR(AliasMap) _aliases;
    std::string _name; }; inline SubSchema Schema::operator[](std::string const & name) const {
    366 4909a663 - return SubSchema(_impl, name);
    424 5a8fd800 + return SubSchema(_impl, _aliases, name);
    ? ++++++++++ } }}} // namespace lsst::afw::table #endif // !AFW_TABLE_Schema_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    47a82785

    commit 47a82785e72101346846b8a2823ec2ff9b1f7f0f
    Author: Jim Bosch 
    Date:   Mon Jan 9 17:18:42 2012 -0500
    
        moved all schema tests to Python, made Schema name sets return Python tuples instead of wrapped std::sets, moved common SWIG stuff to utils' p_lsstSwig.i
    

    9ccc92c4

    commit 9ccc92c4fd4e52ea5f809bd6d05404363ec0a896
    Author: Jim Bosch 
    Date:   Wed Jan 4 23:35:32 2012 -0500
    
        started SWIG for table package; Schema mostly wrapped
    

    9d4a8b87

    commit 9d4a8b875a6970fbf73b6e12caeb25dd6f1b8764
    Author: Jim Bosch 
    Date:   Tue Nov 1 19:58:14 2011 -0400
    
        made Layout use pImpl
    

    1c147ab4

    commit 1c147ab469f93e95cbfe5c535622199cf683536f
    Author: Jim Bosch 
    Date:   Mon Dec 10 12:51:20 2012 -0500
    
        More detailed comparisons for Schema.
    

    4909a663

    commit 4909a663c907e0bd31fe4a48200b47ead26d6292
    Author: Jim Bosch 
    Date:   Wed Dec 14 13:36:28 2011 -0500
    
        renamed SchemaData -> SchemaImpl and made it more encapsulated, more support for subfield access with Schema::find
    

    adb41ee9

    commit adb41ee9be684c9913cef33b6479aa5488ce1e1a
    Author: Jim Bosch 
    Date:   Tue Dec 13 18:54:04 2011 -0500
    
        started adding dotted namespace support for fields - stubby SchemaProxy and subfield lookup by name in Schema::find
    

    8270348f

    commit 8270348ff7fb7f1285044ab55743ff6e4cad2ba5
    Author: Jim Bosch 
    Date:   Fri Dec 2 17:51:42 2011 -0500
    
        cleaned up Layout and made more of LayoutData private
    

    dbc20e58

    commit dbc20e585ec07b70b8c9dc3bbf9707ee3c200480
    Author: Jim Bosch 
    Date:   Wed Jan 25 20:07:49 2012 -0500
    
        lots of shuffling code around.  FITS table support now much better organized
    

    Commits in /Users/nate/repos_lsst/afw/

    4899a4da

    commit 4899a4dafc36ff465cca197db1051b2525209af7
    Author: Jim Bosch 
    Date:   Wed Oct 1 14:41:45 2014 -0400
    
        Add Schema methods to join strings using appropriate delimiter.
        
        The appropriate delimiter for field names depends on the schema version, making it
        difficult to write version-independent code without something like these
        convenience methods.
    

    56df42d2

    commit 56df42d2bb5dd4ebec2e5c67b0d16a137bb1dee2
    Author: Jim Bosch 
    Date:   Wed Aug 20 13:27:23 2014 -0400
    
        Add constructors to Schema and SchemaMapper to set version immediately.
    

    1cdc3abd

    commit 1cdc3abd3e98c1e71e2a76754e02ece73b08230c
    Author: Jim Bosch 
    Date:   Wed Jan 21 16:56:28 2015 -0500
    
        Include aliases in Schema comparison methods.
    

    4223afcb

    commit 4223afcb1247eb4bf8ed03f919d169b2fba462ca
    Author: Perry Gee 
    Date:   Fri Aug 29 17:54:47 2014 -0700
    
        DM-1070 Change the DEFAULT_VERSION of Schema from 0 to 1
        
        DEFAULT_VERSION moved to SchemaImpl, but is copied by Schema so that
        it is visible to SWIG.
        Fix up tests which assumed version 0.
    

    d9cc4a85

    commit d9cc4a85a50010218b7b6b972ff318037be0ebb1
    Author: Jim Bosch 
    Date:   Tue Jul 8 19:15:12 2014 -0400
    
        Make alias modifiers const and copy-on-write
    

    a7452ce2

    commit a7452ce222551998eaff639f457528a35a31dd54
    Author: Jim Bosch 
    Date:   Thu Jul 10 11:36:08 2014 -0400
    
        Rename AliasMap accessors
    

    bd692192

    commit bd692192367d33bb64a79ca008bff10eb9b41932
    Author: pgee 
    Date:   Mon Aug 18 15:06:04 2014 -0700
    
        Move API version number from BaseTable to Schema
        
        In FitsReader, move reading the AFW_TABLE_VERSION header key into the
        Schema-from-metadata constructor.
        In FitsWriter, use the version attached to the table schema to write the
        metadata.
    

    02e44d9b

    commit 02e44d9b44fd74662b230dc5858419ca24d10788
    Author: Jim Bosch 
    Date:   Mon Oct 1 18:50:43 2012 -0400
    
        first implementation of aliases for Schemas; no persistence yet
    

    46f8852c

    commit 46f8852ccf7079ee42119d5da0cc7170dd45f1f6
    Author: Jim Bosch 
    Date:   Mon Aug 25 01:05:02 2014 -0400
    
        Need to apply aliases in SubSchema implicit conversions
    

    1c147ab4

    commit 1c147ab469f93e95cbfe5c535622199cf683536f
    Author: Jim Bosch 
    Date:   Mon Dec 10 12:51:20 2012 -0500
    
        More detailed comparisons for Schema.
    

    5a8fd800

    commit 5a8fd8002be06d2b85139d4b81685f725b266f84
    Author: Jim Bosch 
    Date:   Wed Jul 9 15:52:43 2014 -0400
    
        Move Schema aliases into their own object
        
        Aliases are now used by SubSchema as well, and are shared
        by Schemas when Schemas are copied; disconnecting them
        is explicit (this may be a little confusing, but it matches what
        we want 99% of the time, and we'd need a bigger refactor to
        get an unconfusing solution).
    

    Return to list

    src/math/offsetImage.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file
                     *
                     * Offset an Image (or Mask or MaskedImage) by a constant vector (dx, dy)
                     */
                    #include 
                    #include "lsst/afw/math/offsetImage.h"
                    #include "lsst/afw/geom/Box.h"
                    #include "lsst/afw/geom/Extent.h"
                    #include "lsst/afw/image/ImageUtils.h"
                    #include "lsst/afw/math/warpExposure.h"
                    
                    namespace afwImage = lsst::afw::image;
                    namespace afwGeom = lsst::afw::geom;
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    
                    /**
                     * @brief Return an image offset by (dx, dy) using the specified algorithm
                     *
                     * @note The image pixels are always offset by a fraction of a pixel and the image origin (XY0)
                     * picks is modified to handle the integer portion of the offset.
                     * In the special case that the offset in both x and y lies in the range (-1, 1) the origin is not changed.
                     * Otherwise the pixels are shifted by (-0.5, 0.5] pixels and the origin shifted accordingly.
                     *
    
    52 f58b9679 - * @throw lsst::pex::exceptions::InvalidParameterException if the algorithm is invalid
    ? ^^^^^^ ^
    52 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the algorithm is invalid
    ? ^^ ^ */ template typename ImageT::Ptr offsetImage(ImageT const& inImage, ///< The %image to offset float dx, ///< move the %image this far in the column direction float dy, ///< move the %image this far in the row direction std::string const& algorithmName, ///< Type of resampling Kernel to use unsigned int buffer ///< Width of buffer (border) around kernel image ///< to allow for warping edge effects (pixels). ///< Values < 0 are treated as 0. ///< This is only used during computation; the final image ///< has the same dimensions as the kernel. ) { SeparableKernel::Ptr offsetKernel = makeWarpingKernel(algorithmName); typename ImageT::Ptr buffImage; if (buffer > 0) { // Paste input image into buffered image afwGeom::Extent2I const &dims = inImage.getDimensions(); typename ImageT::Ptr buffered(new ImageT(dims.getX() + 2 * buffer, dims.getY() + 2 * buffer)); buffImage = buffered; afwGeom::Box2I box(afwGeom::Point2I(buffer, buffer), dims); typename ImageT::Ptr buffSmall(new ImageT(*buffImage, box, afwImage::LOCAL, false)); *buffSmall <<= inImage; } else { buffImage = boost::make_shared(inImage); } if (offsetKernel->getWidth() > buffImage->getWidth() || offsetKernel->getHeight() > buffImage->getHeight()) {
    82 0255edbe - throw LSST_EXCEPT(pexExcept::LengthErrorException,
    ? ---------
    82 21597d88 + throw LSST_EXCEPT(pexExcept::LengthError,
    (boost::format("Image of size %dx%d is too small to offset using a %s kernel" "(minimum %dx%d)") % buffImage->getWidth() % buffImage->getHeight() % algorithmName % offsetKernel->getWidth() % offsetKernel->getHeight()).str()); } // typename ImageT::Ptr convImage(new ImageT(buffImage, true)); // output image, a deep copy typename ImageT::Ptr convImage(new ImageT(buffImage->getDimensions())); // Convolved image int dOrigX, dOrigY; double fracX, fracY; // If the offset in both axes is in (-1, 1) use it as is, and don't shift the origin if (dx > -1 && dx < 1 && dy > -1 && dy < 1) { dOrigX = 0; dOrigY = 0; fracX = dx; fracY = dy; } else { dOrigX = static_cast(std::floor(dx + 0.5)); dOrigY = static_cast(std::floor(dy + 0.5)); fracX = dx - dOrigX; fracY = dy - dOrigY; } // We seem to have to pass -fracX, -fracY to setKernelParameters, for reasons RHL doesn't understand double dKerX = -fracX; double dKerY = -fracY; // // If the shift is -ve, the generated shift kernel (e.g. Lanczos5) is quite asymmetric, with the // largest coefficients to the left of centre. We therefore move the centre of calculated shift kernel // one to the right to center up the largest coefficients // if (dKerX < 0) { offsetKernel->setCtrX(offsetKernel->getCtrX() + 1); } if (dKerY < 0) { offsetKernel->setCtrY(offsetKernel->getCtrY() + 1); } offsetKernel->setKernelParameters(std::make_pair(dKerX, dKerY)); convolve(*convImage, *buffImage, *offsetKernel, true, true); typename ImageT::Ptr outImage; if (buffer > 0) { afwGeom::Box2I box(afwGeom::Point2I(buffer, buffer), inImage.getDimensions()); typename ImageT::Ptr out(new ImageT(*convImage, box, afwImage::LOCAL, true)); outImage = out; } else { outImage = convImage; } // adjust the origin; do this after convolution since convolution also sets XY0 outImage->setXY0(geom::Point2I(inImage.getX0() + dOrigX, inImage.getY0() + dOrigY)); return outImage; } /************************************************************************************************************/ // // Explicit instantiations // /// \cond #define INSTANTIATE(TYPE) \ template afwImage::Image::Ptr offsetImage(afwImage::Image const&, float, float, \ std::string const&, unsigned int); \ template afwImage::MaskedImage::Ptr offsetImage(afwImage::MaskedImage const&, float, float, \ std::string const&, unsigned int); INSTANTIATE(double) INSTANTIATE(float) INSTANTIATE(int) /// \endcond }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f58b9679

    commit f58b9679bbf64c12cfb6238c438a620c5598a851
    Author: Russell Owen 
    Date:   Tue Jan 8 11:54:47 2013 -0800
    
        Modify offsetImage to more transparently compute origin shift and fractional shift
        (it had been misusing positionToIndex function) and documented the behavior in more detail.
        Updated the unit test to mimic offsetImage at the edge cases.
    

    0255edbe

    commit 0255edbea300dfc2146f4b2c3b57dca994abbd37
    Author: rhl 
    Date:   Wed Jul 14 11:25:00 2010 +0000
    
        Throw an exception if the image is smaller than the shifting kernel
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/formatters/ExposureFormatter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    /** @file
                     * @brief Implementation of ExposureFormatter class
                     *
                     * @author $Author: ktlim $
                     * @version $Revision: 2151 $
                     * @date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * @ingroup afw
                     */
                    
                    #ifndef __GNUC__
                    #  define __attribute__(x) /*NOTHING*/
                    #endif
                    static char const* SVNid __attribute__((unused)) =
                        "$Id$";
                    
                    #include "boost/serialization/shared_ptr.hpp"
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/daf/persistence/PropertySetFormatter.h"
                    #include "lsst/afw/formatters/ExposureFormatter.h"
                    #include "lsst/afw/formatters/TanWcsFormatter.h"
                    #include "lsst/afw/formatters/Utils.h"
                    #include "lsst/afw/formatters/WcsFormatter.h"
                    #include "lsst/afw/image/Exposure.h"
                    #include "lsst/afw/image/Wcs.h"
                    
                    #include 
                    
                    // #include "lsst/afw/image/LSSTFitsResource.h"
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.ExposureFormatter", level, s);
                    }
                    
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwForm = lsst::afw::formatters;
                    namespace afwImg = lsst::afw::image;
                    namespace dafBase = lsst::daf::base;
                    namespace dafPersist = lsst::daf::persistence;
                    
                    template 
                    class ExposureFormatterTraits {
                    public:
                        static std::string name();
                    };
                    
                    template<>
                    std::string ExposureFormatterTraits::name() {
                        static std::string name = "ExposureU";
                        return name;
                    }
                    template<>
                    std::string ExposureFormatterTraits::name() {
                        static std::string name = "ExposureI";
                        return name;
                    }
                    template<>
                    std::string ExposureFormatterTraits::name() {
                        static std::string name = "ExposureF";
                        return name;
                    }
                    template<>
                    std::string ExposureFormatterTraits::name() {
                        static std::string name = "ExposureD";
                        return name;
                    }
                    template<>
                    std::string ExposureFormatterTraits::name() {
                        static std::string name = "ExposureL";
                        return name;
                    }
                    
                    template 
                    lsst::daf::persistence::FormatterRegistration afwForm::ExposureFormatter::registration(
                        ExposureFormatterTraits::name(),
                        typeid(afwImg::Exposure),
                        createInstance);
                    
                    template 
                    afwForm::ExposureFormatter::ExposureFormatter(
                        lsst::pex::policy::Policy::Ptr policy) :
                        lsst::daf::persistence::Formatter(typeid(this)), _policy(policy) {
                    }
                    
                    template 
                    afwForm::ExposureFormatter::~ExposureFormatter(void) {
                    }
                    
                    /** Lookup a filter number in the database to find a filter name.
                     */
                    static std::string lookupFilterName(
                        dafPersist::DbStorage* db,  //!< Database to look in
                        int filterId    //!< Number of filter to lookup
                        ) {
                        db->setTableForQuery("Filter");
                        db->outColumn("filterName");
                        db->condParam("id", filterId);
                        db->setQueryWhere("filterId = :id");
                        db->query();
                        if (!db->next() || db->columnIsNull(0)) {
    
    139 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    139 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Unable to get name for filter id: %d") % filterId).str()); } std::string filterName = db->getColumnByPos(0); if (db->next()) {
    144 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    144 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    (boost::format("Multiple names for filter id: %d") % filterId).str()); } db->finishQuery(); return filterName; } /** Set an output column's value from a PropertySet, setting it to NULL if * the desired property does not exist. */ template static void setColumn( dafPersist::DbStorage* db, //!< Destination database std::string const& colName, //!< Output column name lsst::daf::base::PropertySet::Ptr source, //!< Source PropertySet std::string const& propName //!< Property name ) { if (!source->exists(propName)) { db->setColumnToNull(colName); } else { db->setColumn(colName, source->get(propName)); } } /** Set an output column's value from a PropertySet, setting it to NULL if * the desired property does not exist. Casts from PropertySet type to * database field type. */ template static void setColumn( dafPersist::DbStorage* db, //!< Destination database std::string const& colName, //!< Output column name lsst::daf::base::PropertySet::Ptr source, //!< Source PropertySet std::string const& propName //!< Property name ) { if (!source->exists(propName)) { db->setColumnToNull(colName); } else { db->setColumn(colName, static_cast(source->get(propName))); } } template void afwForm::ExposureFormatter::write( dafBase::Persistable const* persistable, dafPersist::Storage::Ptr storage, lsst::daf::base::PropertySet::Ptr additionalData) { execTrace("ExposureFormatter write start"); afwImg::Exposure const* ip = dynamic_cast const*>(persistable); if (ip == 0) {
    197 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Persisting non-Exposure");
    ? ---------
    197 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Persisting non-Exposure");
    } if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { execTrace("ExposureFormatter write BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & *ip; execTrace("ExposureFormatter write end"); return; } else if (typeid(*storage) == typeid(dafPersist::FitsStorage)) { execTrace("ExposureFormatter write FitsStorage"); dafPersist::FitsStorage* fits = dynamic_cast(storage.get()); ip->writeFits(fits->getPath()); execTrace("ExposureFormatter write end"); return; } else if (typeid(*storage) == typeid(dafPersist::DbStorage)) { execTrace("ExposureFormatter write DbStorage"); dafPersist::DbStorage* db = dynamic_cast(storage.get()); // Get the Wcs headers. lsst::daf::base::PropertySet::Ptr wcsProps = ip->getWcs()->getFitsMetadata(); // Get the image headers. lsst::daf::base::PropertySet::Ptr dp = ip->getMetadata(); if (!dp) {
    224 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    224 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Unable to retrieve metadata from MaskedImage's Image"); } // Select a table to insert into based on the itemName. std::string itemName = additionalData->get("itemName"); std::string tableName = itemName; if (_policy->exists(itemName)) { lsst::pex::policy::Policy::Ptr itemPolicy = _policy->getPolicy(itemName); if (itemPolicy->exists("TableName")) { tableName = itemPolicy->getString("TableName"); } } if (tableName != "Raw_Amp_Exposure" && tableName != "Science_Amp_Exposure") {
    239 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    239 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Unknown table name for persisting Exposure to DbStorage: " + tableName + "for item " + itemName); } db->setTableForInsert(tableName); // Set the identifier columns. int ampId = extractAmpId(additionalData); // int ccdId = extractCcdId(additionalData); int64_t fpaExposureId = extractFpaExposureId(dp); int64_t ccdExposureId = extractCcdExposureId(dp); int64_t ampExposureId = extractAmpExposureId(dp); if (tableName == "Raw_Amp_Exposure") { db->setColumn("rawAmpExposureId", ampExposureId); db->setColumn("rawCCDExposureId", ccdExposureId); db->setColumn("rawFPAExposureId", fpaExposureId); } else { // Science_Amp_Exposure db->setColumn("scienceAmpExposureId", ampExposureId); db->setColumn("scienceCCDExposureId", ccdExposureId); db->setColumn("scienceFPAExposureId", fpaExposureId); db->setColumn("rawAmpExposureId", ampExposureId); /// \todo Check that rawCCDExposureId == scienceCCDExposureId -- /// KTL -- 2008-01-25 } db->setColumn("ampId", ampId); // Set the URL column with the location of the FITS file. setColumn(db, "url", additionalData, "StorageLocation.FitsStorage"); // Set the Wcs information columns. setColumn(db, "ctype1", wcsProps, "CTYPE1"); setColumn(db, "ctype2", wcsProps, "CTYPE2"); setColumn(db, "crpix1", wcsProps, "CRPIX1"); setColumn(db, "crpix2", wcsProps, "CRPIX2"); setColumn(db, "crval1", wcsProps, "CRVAL1"); setColumn(db, "crval2", wcsProps, "CRVAL2"); if (tableName == "Raw_Amp_Exposure") { setColumn(db, "cd11", wcsProps, "CD1_1"); setColumn(db, "cd21", wcsProps, "CD2_1"); setColumn(db, "cd12", wcsProps, "CD1_2"); setColumn(db, "cd22", wcsProps, "CD2_2"); } else { setColumn(db, "cd1_1", wcsProps, "CD1_1"); setColumn(db, "cd2_1", wcsProps, "CD2_1"); setColumn(db, "cd1_2", wcsProps, "CD1_2"); setColumn(db, "cd2_2", wcsProps, "CD2_2"); } if (tableName == "Science_Amp_Exposure") { // Set calibration data columns. setColumn(db, "photoFlam", dp, "PHOTFLAM"); setColumn(db, "photoZP", dp, "PHOTZP"); } // Phew! Insert the row now. db->insertRow(); execTrace("ExposureFormatter write end"); return; }
    307 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Exposure");
    ? ---------
    307 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Exposure");
    } template dafBase::Persistable* afwForm::ExposureFormatter::read( dafPersist::Storage::Ptr storage, lsst::daf::base::PropertySet::Ptr additionalData) { execTrace("ExposureFormatter read start"); if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { execTrace("ExposureFormatter read BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); afwImg::Exposure* ip = new afwImg::Exposure; boost->getIArchive() & *ip; execTrace("ExposureFormatter read end"); return ip; } else if (typeid(*storage) == typeid(dafPersist::FitsStorage)) { execTrace("ExposureFormatter read FitsStorage"); dafPersist::FitsStorage* fits = dynamic_cast(storage.get()); afwGeom::Box2I box; if (additionalData->exists("llcX")) { int llcX = additionalData->get("llcX"); int llcY = additionalData->get("llcY"); int width = additionalData->get("width"); int height = additionalData->get("height"); box = afwGeom::Box2I(afwGeom::Point2I(llcX, llcY), afwGeom::Extent2I(width, height)); }
    334 3263f939 - afwImg::ImageOrigin origin = afwImg::LOCAL;
    ? ^^^ ^
    334 93994d54 + afwImg::ImageOrigin origin = afwImg::PARENT;
    ? ^ ^^^^ if(additionalData->exists("imageOrigin")){ std::string originStr = additionalData->get("imageOrigin"); if(originStr == "LOCAL") { origin = afwImg::LOCAL; } else if (originStr == "PARENT") { origin = afwImg::PARENT; } else { throw LSST_EXCEPT(
    343 3263f939 - lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    343 21597d88 + lsst::pex::exceptions::RuntimeError,
    (boost::format("Unknown ImageOrigin type %s specified in additional" "data for retrieving Exposure from fits")%originStr ).str() ); } } afwImg::Exposure* ip = new afwImg::Exposure( fits->getPath(), box, origin); execTrace("ExposureFormatter read end"); return ip; } else if (typeid(*storage) == typeid(dafPersist::DbStorage)) { execTrace("ExposureFormatter read DbStorage"); dafPersist::DbStorage* db = dynamic_cast(storage.get()); // Select a table to retrieve from based on the itemName. std::string itemName = additionalData->get("itemName"); std::string tableName = itemName; if (_policy->exists(itemName)) { lsst::pex::policy::Policy::Ptr itemPolicy = _policy->getPolicy(itemName); if (itemPolicy->exists("TableName")) { tableName = itemPolicy->getString("TableName"); } } if (tableName != "Raw_Amp_Exposure" && tableName != "Science_Amp_Exposure") {
    372 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    372 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Unknown table name for retrieving Exposure from DbStorage: " + tableName + " for item " + itemName); } db->setTableForQuery(tableName); // Set the identifier column tests. db->condParam("id", additionalData->getAsInt64("ampExposureId")); if (tableName == "Raw_Amp_Exposure") { db->setQueryWhere("rawAmpExposureId = :id"); } else { // Science_Amp_Exposure db->setQueryWhere("scienceAmpExposureId = :id"); } db->outColumn("url"); if (tableName == "Science_Amp_Exposure") { // Set the Wcs information columns. db->outColumn("ctype1"); db->outColumn("ctype2"); db->outColumn("crpix1"); db->outColumn("crpix2"); db->outColumn("crval1"); db->outColumn("crval2"); db->outColumn("cd11"); db->outColumn("cd21"); db->outColumn("cd12"); db->outColumn("cd22"); // Set calibration data columns. db->outColumn("photoFlam"); db->outColumn("photoZP"); } // Phew! Run the query. db->query(); if (!db->next()) {
    410 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unable to retrieve row");
    ? ---------
    410 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unable to retrieve row");
    } // ... if (db->next()) {
    414 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Non-unique Exposure retrieved");
    ? ---------
    414 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Non-unique Exposure retrieved");
    } db->finishQuery(); //! \todo Should really have FITS be a separate Storage. // - KTL - 2007-11-29 // Restore image from FITS... afwImg::Exposure* ip = new afwImg::Exposure(db->getColumnByPos(0)); lsst::daf::base::PropertySet::Ptr dp = ip->getMetadata(); // Look up the filter name given the ID. int filterId = db->getColumnByPos(1); std::string filterName = lookupFilterName(db, filterId); dp->set("FILTER", filterName); // Set the image headers. // Set the Wcs headers in ip->_wcs. //! \todo Need to implement overwriting of FITS metadata PropertySet // with values from database. - KTL - 2007-12-18 execTrace("ExposureFormatter read end"); return ip; }
    440 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Exposure");
    ? ---------
    440 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Exposure");
    } template void afwForm::ExposureFormatter::update( dafBase::Persistable*, dafPersist::Storage::Ptr, lsst::daf::base::PropertySet::Ptr ) { //! \todo Implement update from FitsStorage, keeping DB-provided headers. // - KTL - 2007-11-29
    452 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unexpected call to update for Exposure");
    ? ---------
    452 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unexpected call to update for Exposure");
    } template template void afwForm::ExposureFormatter::delegateSerialize( Archive& ar, unsigned int const, dafBase::Persistable* persistable ) { execTrace("ExposureFormatter delegateSerialize start"); afwImg::Exposure* ip = dynamic_cast*>(persistable); if (ip == 0) {
    464 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Serializing non-Exposure");
    ? ---------
    464 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Serializing non-Exposure");
    } PTR(afwImg::Wcs) wcs = ip->getWcs(); ar & *ip->getMetadata() & ip->_maskedImage & wcs; execTrace("ExposureFormatter delegateSerialize end"); } template lsst::daf::persistence::Formatter::Ptr afwForm::ExposureFormatter::createInstance( lsst::pex::policy::Policy::Ptr policy) { typedef typename lsst::daf::persistence::Formatter::Ptr FormPtr; return FormPtr(new afwForm::ExposureFormatter(policy)); } /// \cond #define INSTANTIATE(I, M, V) \ template class afwForm::ExposureFormatter; \ template void afwForm::ExposureFormatter::delegateSerialize( \ boost::archive::text_oarchive &, unsigned int const, dafBase::Persistable *); \ template void afwForm::ExposureFormatter::delegateSerialize( \ boost::archive::text_iarchive &, unsigned int const, dafBase::Persistable *); \ template void afwForm::ExposureFormatter::delegateSerialize( \ boost::archive::binary_oarchive &, unsigned int const, dafBase::Persistable *); \ template void afwForm::ExposureFormatter::delegateSerialize( \ boost::archive::binary_iarchive &, unsigned int const, dafBase::Persistable *); INSTANTIATE(uint16_t, afwImg::MaskPixel, afwImg::VariancePixel) INSTANTIATE(int, afwImg::MaskPixel, afwImg::VariancePixel) INSTANTIATE(float, afwImg::MaskPixel, afwImg::VariancePixel) INSTANTIATE(double, afwImg::MaskPixel, afwImg::VariancePixel) INSTANTIATE(uint64_t, afwImg::MaskPixel, afwImg::VariancePixel) /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    tests/interpolate.py

    Diff:

    1 ff0c8fc4 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Interpolate Run with: ./Interpolate.py or python >>> import Interpolate; Interpolate.run() """ import unittest import numpy as np import lsst.utils.tests as utilsTests import lsst.afw.math as afwMath import lsst.pex.exceptions as pexExcept #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class InterpolateTestCase(unittest.TestCase):
    46 3de3339a - """A test case for Interpolate Linear"""
    ? -
    47 ff0c8fc4 + """A test case for Interpolate Lienar"""
    ? + def setUp(self): self.n = 10
    49 3de3339a - self.x = np.zeros(self.n, dtype=float)
    50 3de3339a - self.y1 = np.zeros(self.n, dtype=float)
    51 3de3339a - self.y2 = np.zeros(self.n, dtype=float)
    50 2f5e179c + self.x = afwMath.vectorD(self.n)
    51 2f5e179c + self.y1 = afwMath.vectorD(self.n)
    52 2f5e179c + self.y2 = afwMath.vectorD(self.n)
    self.y0 = 1.0 self.dydx = 1.0 self.d2ydx2 = 0.5 for i in range(0, self.n, 1): self.x[i] = i self.y1[i] = self.dydx*self.x[i] + self.y0 self.y2[i] = self.d2ydx2*self.x[i]*self.x[i] + self.dydx*self.x[i] + self.y0 self.xtest = 4.5 self.y1test = self.dydx*self.xtest + self.y0 self.y2test = self.d2ydx2*self.xtest*self.xtest + self.dydx*self.xtest + self.y0 def tearDown(self): del self.x del self.y1 del self.y2 def testLinearRamp(self): # === test the Linear Interpolator ============================ # default is akima spline yinterpL = afwMath.makeInterpolate(self.x, self.y1) youtL = yinterpL.interpolate(self.xtest) self.assertEqual(youtL, self.y1test) def testNaturalSplineRamp(self): # === test the Spline interpolator ======================= # specify interp type with the string interface yinterpS = afwMath.makeInterpolate(self.x, self.y1, afwMath.Interpolate.NATURAL_SPLINE) youtS = yinterpS.interpolate(self.xtest) self.assertEqual(youtS, self.y1test) def testAkimaSplineParabola(self): """test the Spline interpolator""" # specify interp type with the enum style interface yinterpS = afwMath.makeInterpolate(self.x, self.y2, afwMath.Interpolate.AKIMA_SPLINE) youtS = yinterpS.interpolate(self.xtest) self.assertEqual(youtS, self.y2test) def testConstant(self): """test the constant interpolator""" # [xy]vec: point samples # [xy]vec_c: centered values xvec = np.array([ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) xvec_c = np.array([-0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]) yvec = np.array([ 1.0, 2.4, 5.0, 8.4, 13.0, 18.4, 25.0, 32.6, 41.0, 50.6]) yvec_c = np.array([ 1.0, 1.7, 3.7, 6.7, 10.7, 15.7, 21.7, 28.8, 36.8, 45.8, 50.6]) interp = afwMath.makeInterpolate(xvec, yvec, afwMath.Interpolate.CONSTANT) for x, y in zip(xvec_c, yvec_c): self.assertAlmostEqual(interp.interpolate(x + 0.1), y) self.assertAlmostEqual(interp.interpolate(x), y) self.assertEqual(interp.interpolate(xvec[0] - 10), yvec[0]) n = len(yvec) self.assertEqual(interp.interpolate(xvec[n - 1] + 10), yvec[n - 1]) for x, y in reversed(zip(xvec_c, yvec_c)): # test caching as we go backwards self.assertAlmostEqual(interp.interpolate(x + 0.1), y) self.assertAlmostEqual(interp.interpolate(x), y) i = 2 for x in np.arange(xvec_c[i], xvec_c[i + 1], 10): self.assertEqual(interp.interpolate(x), yvec_c[i]) def testInvalidInputs(self): """Test that invalid inputs cause an abort"""
    129 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    130 cfb35bf1 + lambda : afwMath.makeInterpolate([], [],
    128 3de3339a - utilsTests.assertRaisesLsstCpp(
    129 3de3339a - self, pexExcept.InvalidParameterException,
    130 3de3339a - lambda : afwMath.makeInterpolate(np.array([], dtype=float), np.array([], dtype=float),
    131 3de3339a - afwMath.Interpolate.CONSTANT)
    131 cfb35bf1 + afwMath.Interpolate.CONSTANT))
    ? +++++++++++++++++++++++++++ +
    132 3de3339a - )
    133 cfb35bf1 + interp = afwMath.makeInterpolate([0], [1], afwMath.Interpolate.CONSTANT)
    134 3de3339a - interp = afwMath.makeInterpolate(np.array([0], dtype=float), np.array([1], dtype=float),
    135 3de3339a - afwMath.Interpolate.CONSTANT)
    135 6fc1c3d1 + self.assertRaises(pexExcept.OutOfRangeError,
    136 cfb35bf1 + lambda : afwMath.makeInterpolate([0], [1],
    137 3de3339a - utilsTests.assertRaisesLsstCpp(
    138 3de3339a - self, pexExcept.OutOfRangeException,
    139 3de3339a - lambda : afwMath.makeInterpolate(np.array([0], dtype=float), np.array([1], dtype=float),
    140 3de3339a - afwMath.Interpolate.LINEAR)
    137 cfb35bf1 + afwMath.Interpolate.LINEAR))
    ? +++++++++++++++++++++++++++ +
    141 3de3339a - )
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(InterpolateTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ff0c8fc4

    commit ff0c8fc4d3fb8d3e18c90ccf5d5efac743619b4a
    Author: bick 
    Date:   Wed Jan 14 16:50:33 2009 +0000
    
        Merging ticket 395 (image statistics and background estimation) on to trunk.
    

    3de3339a

    commit 3de3339aa075f869d73a5bc66fc65dbee8ae3d16
    Author: Jim Bosch 
    Date:   Wed Mar 12 16:54:33 2014 -1000
    
        Fix unit test fallout from Interpolate std::vector change
    

    Commits in /Users/nate/repos_lsst/afw/

    cfb35bf1

    commit cfb35bf123952e7c9d8a70ad362511a74ee6ef8b
    Author: Robert Lupton the Good 
    Date:   Thu Oct 18 16:49:25 2012 -0400
    
        Add an InterpolateConstant subclass to handle Interpolate::CONSTANT
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    ff0c8fc4

    commit ff0c8fc4d3fb8d3e18c90ccf5d5efac743619b4a
    Author: bick 
    Date:   Wed Jan 14 16:50:33 2009 +0000
    
        Merging ticket 395 (image statistics and background estimation) on to trunk.
    

    2f5e179c

    commit 2f5e179ca9f56a84d41cd5a8f8dbabc3f7141d46
    Merge: dfdd78a deba9f6
    Author: bick 
    Date:   Wed Oct 7 16:41:35 2009 +0000
    
        #955 Updated against afw/trunk.
    

    Return to list

    examples/statistics.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/Statistics.h"
                    
                    using namespace std;
                    namespace image = lsst::afw::image;
                    namespace math = lsst::afw::math;
                    namespace geom = lsst::afw::geom;
                    
                    typedef image::Image ImageF;
                    
                    int main() {
                    
                        // First we'll try a regular image
                        ImageF img(geom::Extent2I(10, 40));
                        img = 100000.0;
                        
                        {
                            math::Statistics stats = math::makeStatistics(img, math::NPOINT | math::MEAN | math::STDEV);
                            cout << "Npixel: " << stats.getValue(math::NPOINT) << endl;
                            cout << "Mean: " << stats.getValue(math::MEAN) << endl;
                            cout << "Error in mean: " << stats.getError(math::MEAN) << " (expect NaN)" << endl;
                            cout << "Standard Deviation: " << stats.getValue(math::STDEV) << endl << endl;
                        }
                    
                        {
                            math::Statistics stats = math::makeStatistics(img, math::STDEV | math::MEAN | math::ERRORS);
                            std::pair mean = stats.getResult(math::MEAN);
                    
                            cout << "Mean: " << mean.first << " error in mean: " << mean.second << endl << endl;
                        }
                    
                        {
                            math::Statistics stats = math::makeStatistics(img, math::NPOINT);
                            try {
                                stats.getValue(math::MEAN);
    
    64 3771b5eb - } catch (lsst::pex::exceptions::InvalidParameterException &e) {
    ? ^^^^^^ ^
    64 21597d88 + } catch (lsst::pex::exceptions::InvalidParameterError &e) {
    ? ^^ ^ cout << "You didn't ask for the mean, so we caught an exception: " << e.what() << endl; } } return 0; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/table/Schema.cc

    Diff:

                    #include 
                    #include 
                    
                    #include "boost/make_shared.hpp"
                    #include "boost/type_traits/is_same.hpp"
                    #include "boost/mpl/and.hpp"
                    #include "boost/mpl/bool.hpp"
                    #include "boost/scoped_ptr.hpp"
                    #include "boost/iterator/transform_iterator.hpp"
                    #include "boost/iterator/filter_iterator.hpp"
                    #include "boost/preprocessor/seq/for_each.hpp"
                    #include "boost/preprocessor/tuple/to_seq.hpp"
                    
                    #include "lsst/afw/table/Schema.h"
                    #include "lsst/afw/table/detail/Access.h"
                    #include "lsst/afw/table/io/FitsReader.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    //-----------------------------------------------------------------------------------------------------------
                    //----- Miscellaneous Utilities -----------------------------------------------------------------------------
                    //-----------------------------------------------------------------------------------------------------------
                    
                    namespace {
                    
    
    26 1ad0851f + inline char getDelimiter(int version) { return (version > 0) ? '_' : '.'; }
    27 1ad0851f +
    26 d6480e01 - // Concatenate two strings with a period between them.
    ? ^ ^^ -
    28 1ad0851f + // Concatenate two strings with a single-character delimiter between them
    ? ^^^^^^^^^^^^^^ ++++ ^^^^^
    27 adb41ee9 - std::string join(std::string const & a, std::string const & b) {
    29 1ad0851f + std::string join(std::string const & a, std::string const & b, char delimiter) {
    ? ++++++++++++++++ std::string full; full.reserve(a.size() + b.size() + 1); full += a;
    31 adb41ee9 - full.push_back('.');
    ? ^^^
    33 1ad0851f + full.push_back(delimiter);
    ? ^^^^^^^^^ full += b; return full; } // Functor to compare two ItemVariants for Key equality. class ItemFunctors { typedef detail::SchemaImpl::ItemVariant ItemVariant; // Compares keys - must be initialized with one ItemVariant and passed the other. struct KeyHelper : public boost::static_visitor {
    45 35ba793d +
    46 76213222 + explicit KeyHelper(ItemVariant const * other_) : other(other_) {}
    template bool operator()(SchemaItem const & a) const { SchemaItem const * b = boost::get< SchemaItem >(other); return (b) && a.key == b->key; }
    49 5a8a1997 -
    50 1c147ab4 - explicit KeyHelper(ItemVariant const * other_) : other(other_) {}
    ItemVariant const * other; }; // Extracts field name from an ItemVariant struct NameHelper : public boost::static_visitor { template std::string const & operator()(SchemaItem const & a) const { return a.field.getName(); } }; // Extracts field doc from an ItemVariant struct DocHelper : public boost::static_visitor { template std::string const & operator()(SchemaItem const & a) const { return a.field.getDoc(); } }; // Extracts field units from an ItemVariant struct UnitsHelper : public boost::static_visitor { template std::string const & operator()(SchemaItem const & a) const { return a.field.getUnits(); } }; public: static bool compareKeys(ItemVariant const & a, ItemVariant const & b) { return boost::apply_visitor(KeyHelper(&b), a); } static bool compareNames(ItemVariant const & a, ItemVariant const & b) { return boost::apply_visitor(NameHelper(), a) == boost::apply_visitor(NameHelper(), b); } static bool compareDocs(ItemVariant const & a, ItemVariant const & b) { return boost::apply_visitor(DocHelper(), a) == boost::apply_visitor(DocHelper(), b); } static bool compareUnits(ItemVariant const & a, ItemVariant const & b) { return boost::apply_visitor(UnitsHelper(), a) == boost::apply_visitor(UnitsHelper(), b); } }; } // anonymous //----------------------------------------------------------------------------------------------------------- //----- SchemaImpl implementation --------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------- namespace detail { //----- Finding a SchemaItem by field name ------------------------------------------------------------------ // This is easier to understand if you start reading from the bottom of this section, with // SchemaImpl::find(std::string const &), then work your way up. namespace { // Given a SchemaItem for a regular field, look for a subfield with the given name. // Return the index of the subfield (>= 0) on success, -1 on failure. template inline int findNamedSubfield( SchemaItem const & item, std::string const & name,
    116 1ad0851f + char delimiter,
    boost::mpl::true_ * // whether a match is possible based on the type of T; computed by caller ) { if (name.size() <= item.field.getName().size()) return -1; if ( // compare invocation is equivalent to "name.startswith(item.field.getName())" in Python name.compare(0, item.field.getName().size(), item.field.getName()) == 0
    120 d6480e01 - && name[item.field.getName().size()] == '.'
    ? ^^^
    123 1ad0851f + && name[item.field.getName().size()] == delimiter
    ? ^^^^^^^^^ ) { int const position = item.field.getName().size() + 1; int const size = name.size() - position; int const nElements = item.field.getElementCount(); for (int i = 0; i < nElements; ++i) { if (name.compare(position, size, Key::subfields[i]) == 0) { return i; } } } return -1; } // This is an overload of findNamedSubfield that always fails; it's called when we // know from the type of the field and subfield that they're incompatible. template inline int findNamedSubfield( SchemaItem const & item, std::string const & name,
    143 1ad0851f + char delimiter,
    boost::mpl::false_ * // whether a match is possible based on the type of T; computed by caller ) { return -1; } // Given a SchemaItem and a subfield index, make a new SchemaItem that corresponds to that // subfield and put it in the result smart pointer. template inline void makeSubfieldItem(
    149 35ba793d - SchemaItem const & item, int index,
    153 1ad0851f + SchemaItem const & item, int index, char delimiter,
    ? ++++++++++++++++ boost::scoped_ptr< SchemaItem > & result, boost::mpl::true_ * // whether a match is possible based on the types of T and U; computed by caller ) { result.reset( new SchemaItem( detail::Access::extractElement(item.key, index), Field(
    157 d6480e01 - join(item.field.getName(), Key::subfields[index]),
    161 1ad0851f + join(item.field.getName(), Key::subfields[index], delimiter),
    ? +++++++++++ item.field.getDoc(), item.field.getUnits() ) ) ); } // An overload of makeSubfieldItem that always fails because we know T and U aren't compatible. template inline void makeSubfieldItem(
    168 35ba793d - SchemaItem const & item, int index,
    172 1ad0851f + SchemaItem const & item, int index, char delimiter,
    ? ++++++++++++++++ boost::scoped_ptr< SchemaItem > & result, boost::mpl::false_ * // whether a match is possible based on the types of T and U; computed by caller ) {} // This is a Variant visitation functor used to extract subfield items by name. // For example, if we have a Point field "a", if we search the Schema for "a.x", // we want to return a SchemaItem that makes it look like "a.x" is a full-fledged // field in its own right. template struct ExtractItemByName : public boost::static_visitor<> {
    183 35ba793d +
    184 76213222 + explicit ExtractItemByName(std::string const & name_, char delimiter_) :
    185 76213222 + delimiter(delimiter_), name(name_) {}
    template void operator()(SchemaItem const & item) const { // We want to find out if 'item' has a subfield whose fully-qualified name matches our // name data member. But we also know that the subfield needs to have type U, and that // the field needs to have named subfields. // This typedef is boost::mpl::true_ if all the above is true, and boost::mpl::false_ otherwise. typedef typename boost::mpl::and_< boost::is_same::Element>, boost::mpl::bool_::HAS_NAMED_SUBFIELDS> >::type IsMatchPossible; // We use that type to dispatch one of the two overloads of findNamedSubfield.
    191 d6480e01 - int n = findNamedSubfield(item, name, (IsMatchPossible*)0);
    198 1ad0851f + int n = findNamedSubfield(item, name, delimiter, (IsMatchPossible*)0);
    ? +++++++++++ // If we have a match, we call another overloaded template to make the subfield.
    193 d6480e01 - if (n >= 0) makeSubfieldItem(item, n, result, (IsMatchPossible*)0);
    200 1ad0851f + if (n >= 0) makeSubfieldItem(item, n, delimiter, result, (IsMatchPossible*)0);
    ? +++++++++++ }
    203 1ad0851f + char delimiter;
    196 4909a663 - explicit ExtractItemByName(std::string const & name_) : name(name_) {}
    197 78a55502 -
    std::string name; // name we're looking for mutable boost::scoped_ptr< SchemaItem > result; // where we put the result to signal that we're done }; } // anonymous // Here's the driver for the find-by-name algorithm. template SchemaItem SchemaImpl::find(std::string const & name) const { NameMap::const_iterator i = _names.lower_bound(name); if (i != _names.end()) { if (i->first == name) { // got an exact match; we're done if it has the right type, and dead if it doesn't. try { return boost::get< SchemaItem const >(_items[i->second]); } catch (boost::bad_get & err) { throw LSST_EXCEPT(
    215 2fd496f2 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^^^^ ----- ------- ^
    221 55b692d5 + lsst::pex::exceptions::TypeError,
    ? ^^^^^ ^ (boost::format("Field '%s' does not have the given type.") % name).str() ); } } }
    221 d6480e01 - // We didn't get an exact match, but we might be searching for "a.x" and "a" might be a point field.
    227 1ad0851f + // We didn't get an exact match, but we might be searching for "a.x/a_x" and "a" might be a point field.
    ? ++++ // Because the names are sorted, we know we overshot it, so we work backwards.
    223 4909a663 - ExtractItemByName extractor(name);
    229 1ad0851f + ExtractItemByName extractor(name, getDelimiter(_version));
    ? ++++++++++++++++++++++++ while (i != _names.begin()) { --i; boost::apply_visitor(extractor, _items[i->second]); // see if the current item is a match if (extractor.result) return *extractor.result; } throw LSST_EXCEPT(
    230 adb41ee9 - lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    236 21597d88 + lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("Field or subfield withname '%s' not found with type '%s'.") % name % Field::getTypeString()).str() ); } //----- Finding a SchemaItem by key ------------------------------------------------------------------------- // This is easier to understand if you start reading from the bottom of this section, with // SchemaImpl::find(Key const &), then work your way up. namespace { // Given a SchemaItem for a regular field, look for a subfield with the given Key // Return the index of the subfield (>= 0) on success, -1 on failure. template inline int findKeySubfield( SchemaItem const & item, Key const & key, boost::mpl::true_ * // whether a match is possible based on the types of T and U; computed by caller ) { int n = (key.getOffset() - item.key.getOffset()) / sizeof(U); if (n >= 0 && n < item.key.getElementCount()) { return n; } return -1; } // This is an overload of findKeySubfield that always fails; it's called when we // know from the type of the field and subfield that they're incompatible. template inline int findKeySubfield( SchemaItem const & item, Key const & key, boost::mpl::false_ * // whether a match is possible based on the types of T and U; computed by caller ) { return -1; } // This is a Variant visitation functor used to extract subfield items by key. template struct ExtractItemByKey : public boost::static_visitor<> {
    278 35ba793d +
    279 76213222 + explicit ExtractItemByKey(Key const & key_, char delimiter_) : delimiter(delimiter_), key(key_) {}
    template void operator()(SchemaItem const & item) const { // We want to find out if 'item' has a subfield whose matches our key data member. // But we also know that the subfield needs to have type U. // This typedef is boost::mpl::true_ if the above is true, and boost::mpl::false_ otherwise. typedef typename boost::mpl::and_< boost::is_same::Element>, boost::mpl::bool_::HAS_NAMED_SUBFIELDS> >::type IsMatchPossible; // We use that type to dispatch one of the two overloads of findKeySubfield. int n = findKeySubfield(item, key, (IsMatchPossible*)0); // If we have a match, we call another overloaded template to make the subfield. // (this is the same makeSubfieldItem used in ExtractItemByName, so it's defined up there)
    286 d6480e01 - if (n >= 0) makeSubfieldItem(item, n, result, (IsMatchPossible*)0);
    294 1ad0851f + if (n >= 0) makeSubfieldItem(item, n, delimiter, result, (IsMatchPossible*)0);
    ? +++++++++++ }
    297 1ad0851f + char delimiter;
    289 d6480e01 - explicit ExtractItemByKey(Key const & key_) : key(key_) {}
    290 d6480e01 -
    Key key; mutable boost::scoped_ptr< SchemaItem > result; }; } // anonymous. // Here's the driver for the find-by-key algorithm. It's pretty similar to the find-by-name algorithm. template SchemaItem SchemaImpl::find(Key const & key) const { OffsetMap::const_iterator i = _offsets.lower_bound(key.getOffset());
    308 40bacb3d + if (i != _offsets.end()) {
    301 d6480e01 - if (i->first == key.getOffset()) {
    309 40bacb3d + if (i->first == key.getOffset()) {
    ? ++++
    302 4909a663 - try {
    310 40bacb3d + try {
    ? ++++
    303 d6480e01 - return boost::get< SchemaItem const >(_items[i->second]);
    311 40bacb3d + return boost::get< SchemaItem const >(_items[i->second]);
    ? ++++
    304 4909a663 - } catch (boost::bad_get & err) {
    312 40bacb3d + } catch (boost::bad_get & err) {
    ? ++++
    305 d6480e01 - // just swallow the exception; this might be a subfield key that points to the beginning.
    313 40bacb3d + // just swallow the exception; this might be a subfield key that points to the beginning.
    ? ++++
    306 4909a663 - }
    314 40bacb3d + }
    ? ++++
    307 4909a663 - }
    315 40bacb3d + }
    ? ++++
    308 d6480e01 - // We didn't get an exact match, but we might be searching for a subfield.
    316 40bacb3d + // We didn't get an exact match, but we might be searching for a subfield.
    ? ++++
    309 d6480e01 - // Because the offsets are sorted, we know we overshot it, so we work backwards.
    317 40bacb3d + // Because the offsets are sorted, we know we overshot it, so we work backwards.
    ? ++++
    310 d6480e01 - ExtractItemByKey extractor(key);
    318 1ad0851f + ExtractItemByKey extractor(key, getDelimiter(_version));
    311 d6480e01 - while (i != _offsets.begin()) {
    319 40bacb3d + while (i != _offsets.begin()) {
    ? ++++
    312 4909a663 - --i;
    320 40bacb3d + --i;
    ? ++++
    313 d6480e01 - boost::apply_visitor(extractor, _items[i->second]);
    321 40bacb3d + boost::apply_visitor(extractor, _items[i->second]);
    ? ++++
    314 4909a663 - if (extractor.result) return *extractor.result;
    322 40bacb3d + if (extractor.result) return *extractor.result;
    ? ++++
    323 4909a663 + }
    } throw LSST_EXCEPT(
    317 4909a663 - lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    326 21597d88 + lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("Field or subfield with offset %d not found with type '%s'.") % key.getOffset() % Field::getTypeString()).str() ); } // We handle Flag fields separately when searching for keys, because their keys aren't like the others. SchemaItem SchemaImpl::find(Key const & key) const { FlagMap::const_iterator i = _flags.lower_bound(std::make_pair(key.getOffset(), key.getBit()));
    335 40bacb3d + if (i != _flags.end()) {
    326 d6480e01 - if (i->first.first == key.getOffset() && i->first.second == key.getBit()) {
    336 40bacb3d + if (i->first.first == key.getOffset() && i->first.second == key.getBit()) {
    ? ++++
    327 d6480e01 - try {
    337 40bacb3d + try {
    ? ++++
    328 d6480e01 - return boost::get< SchemaItem const >(_items[i->second]);
    338 40bacb3d + return boost::get< SchemaItem const >(_items[i->second]);
    ? ++++
    329 d6480e01 - } catch (boost::bad_get & err) {
    339 40bacb3d + } catch (boost::bad_get & err) {
    ? ++++
    330 d6480e01 - throw LSST_EXCEPT(
    340 40bacb3d + throw LSST_EXCEPT(
    ? ++++
    331 d6480e01 - lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    341 21597d88 + lsst::pex::exceptions::NotFoundError,
    ? ++++ ^^ ^
    332 35ba793d - (boost::format("Flag field with offset %d and bit %d not found.")
    342 40bacb3d + (boost::format("Flag field with offset %d and bit %d not found.")
    ? ++++
    333 d6480e01 - % key.getOffset() % key.getBit()).str()
    343 40bacb3d + % key.getOffset() % key.getBit()).str()
    ? ++++
    344 40bacb3d + );
    334 d6480e01 - );
    ? ^^
    345 40bacb3d + }
    ? ^ } } // Flag keys are never subfields, so we require an exact match. throw LSST_EXCEPT(
    339 d6480e01 - lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    350 21597d88 + lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("Flag field with offset %d and bit %d not found.") % key.getOffset() % key.getBit()).str() ); } //----- Replacing an existing SchemaItem -------------------------------------------------------------------- // This is easier to understand if you start reading from the bottom of this section, with // SchemaImpl::replaceField, then work your way up. namespace { // Find an exact SchemaItem by key ('exact' means no subfields, unlike the find member function above) // Return the index into the item container. template inline int findKey( SchemaImpl::OffsetMap const & offsets, SchemaImpl::FlagMap const & flags, Key const & key, bool throwIfMissing = true ) { SchemaImpl::OffsetMap::const_iterator i = offsets.find(key.getOffset()); if (i == offsets.end()) { if (throwIfMissing) { throw LSST_EXCEPT(
    365 35ba793d - pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    376 21597d88 + pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("Key of type %s with offset %d not found in Schema") % Field::getTypeString() % key.getOffset()).str() ); } else { return -1; } } return i->second; } // Like the above, but special-cased for Flag inline int findKey( SchemaImpl::OffsetMap const & offsets, SchemaImpl::FlagMap const & flags, Key const & key, bool throwIfMissing = true ) { SchemaImpl::FlagMap::const_iterator i = flags.find(std::make_pair(key.getOffset(), key.getBit())); if (i == flags.end()) { if (throwIfMissing) { throw LSST_EXCEPT(
    387 35ba793d - pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    398 21597d88 + pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("Key of type Flag with offset %d and bit %d not found in Schema") % key.getOffset() % key.getBit()).str() ); } else { return -1; } } return i->second; } } // anonymous template void SchemaImpl::replaceField(Key const & key, Field const & field) { NameMap::iterator j = _names.find(field.getName()); SchemaItem * item = 0; if (j != _names.end()) { // The field name is already present in the Schema; see if it's the one we're replacing. // If we can get the old item with this, we don't need to update the name map at all. item = boost::get< SchemaItem >(&_items[j->second]); if (!item || key != item->key) { throw LSST_EXCEPT(
    410 d6480e01 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    421 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Field with name '%s' already present in schema with a different key.") % field.getName()).str() ); } } if (!item) { // Need to find the original item by key, since it's a new name. int index = findKey(_offsets, _flags, key); item = boost::get< SchemaItem >(&_items[index]); if (!item) { throw LSST_EXCEPT(
    421 d6480e01 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^^^^ ----- ------- ^
    432 55b692d5 + lsst::pex::exceptions::TypeError,
    ? ^^^^^ ^ (boost::format("Incorrect key type '%s'.") % key).str() ); } j = _names.find(item->field.getName()); _names.insert(j, std::pair(field.getName(), j->second)); _names.erase(j); } item->field = field; } //----- Other SchemaImpl things ----------------------------------------------------------------------------- template int SchemaImpl::contains(SchemaItem const & item, int flags) const { if (!(flags & Schema::EQUAL_KEYS)) { throw LSST_EXCEPT(
    438 35ba793d - pex::exceptions::LogicErrorException,
    ? ---------
    449 21597d88 + pex::exceptions::LogicError,
    "Can only check whether item is in schema if flags & EQUAL_KEYS" ); } SchemaItem const * cmpItem = 0; int index = findKey(_offsets, _flags, item.key, false); if (index >= 0) { cmpItem = boost::get< SchemaItem >(&_items[index]); if (!cmpItem) { if ((flags & Schema::EQUAL_NAMES) && cmpItem->field.getName() != item.field.getName()) { flags &= ~Schema::EQUAL_NAMES; } if ((flags & Schema::EQUAL_DOCS) && cmpItem->field.getDoc() != item.field.getDoc()) { flags &= ~Schema::EQUAL_DOCS; } if ((flags & Schema::EQUAL_UNITS) && cmpItem->field.getUnits() != item.field.getUnits()) { flags &= ~Schema::EQUAL_UNITS; } } } else { flags = 0; } return flags; } std::set SchemaImpl::getNames(bool topOnly) const { std::set result;
    476 a25b9eb2 + // set the separator for table ('.' if getVersion() is 0 or nan, else '_')
    477 a25b9eb2 + char separator = (getVersion() > 0) ? '_' : '.';
    if (topOnly) { for (NameMap::const_iterator i = _names.begin(); i != _names.end(); ++i) {
    467 4909a663 - std::size_t dot = i->first.find('.');
    ? ^^^ ^^^
    480 a25b9eb2 + std::size_t sep = i->first.find(separator);
    ? ^^^ ^^^^^^^^^
    468 4909a663 - if (dot == std::string::npos) {
    ? ^^^
    481 a25b9eb2 + if (sep == std::string::npos) {
    ? ^^^ result.insert(result.end(), i->first); } else {
    471 4909a663 - result.insert(result.end(), i->first.substr(0, dot));
    ? ^^^
    484 a25b9eb2 + result.insert(result.end(), i->first.substr(0, sep));
    ? ^^^ } } } else { for (NameMap::const_iterator i = _names.begin(); i != _names.end(); ++i) { result.insert(result.end(), i->first); } } return result; } std::set SchemaImpl::getNames(bool topOnly, std::string const & prefix) const { std::set result;
    497 a25b9eb2 + // set the separator for table ('.' if getVersion() is 0 or nan, else '_')
    498 a25b9eb2 + char separator = (getVersion() > 0) ? '_' : '.';
    if (topOnly) { for (NameMap::const_iterator i = _names.lower_bound(prefix); i != _names.end(); ++i) { if (i->first.compare(0, prefix.size(), prefix) != 0) break;
    487 4909a663 - std::size_t dot = i->first.find('.', prefix.size() + 1);
    ? ^^^ ^^^
    502 a25b9eb2 + std::size_t sep = i->first.find(separator, prefix.size() + 1);
    ? ^^^ ^^^^^^^^^
    488 4909a663 - if (dot == std::string::npos) {
    ? ^^^
    503 a25b9eb2 + if (sep == std::string::npos) {
    ? ^^^ result.insert( result.end(), i->first.substr(prefix.size() + 1, i->first.size() - prefix.size()) ); } else { result.insert( result.end(),
    496 4909a663 - i->first.substr(prefix.size() + 1, dot - prefix.size() - 1)
    ? ^^^
    511 a25b9eb2 + i->first.substr(prefix.size() + 1, sep - prefix.size() - 1)
    ? ^^^ ); } } } else { for (NameMap::const_iterator i = _names.lower_bound(prefix); i != _names.end(); ++i) { if (i->first.compare(0, prefix.size(), prefix) != 0) break; result.insert( result.end(), i->first.substr(prefix.size() + 1, i->first.size() - prefix.size() - 1) ); } } return result; } template Key< Array > SchemaImpl::addField(Field< Array > const & field, bool doReplace) { if (field.isVariableLength()) { return addFieldImpl(sizeof(ndarray::Array), 1, field, doReplace); } return addFieldImpl(sizeof(typename Field::Element), field.getElementCount(), field, doReplace); } template Key SchemaImpl::addField(Field const & field, bool doReplace) { return addFieldImpl(sizeof(typename Field::Element), field.getElementCount(), field, doReplace); } Key SchemaImpl::addField(Field const & field, bool doReplace) { static int const ELEMENT_SIZE = sizeof(Field::Element); std::pair result = _names.insert(std::pair(field.getName(), _items.size())); if (!result.second) { if (doReplace) { SchemaItem * item = boost::get< SchemaItem >(&_items[result.first->second]); if (!item) { throw LSST_EXCEPT(
    534 7e5c4d23 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^^^^ ----- ------- ^
    549 55b692d5 + lsst::pex::exceptions::TypeError,
    ? ^^^^^ ^ (boost::format("Cannot replace field with name '%s' because types differ.")
    551 7e5c4d23 + % field.getName()).str()
    552 7e5c4d23 + );
    553 7e5c4d23 + }
    554 1d7de6d9 + if (item->field.getElementCount() != field.getElementCount()) {
    555 1d7de6d9 + throw LSST_EXCEPT(
    556 55b692d5 + lsst::pex::exceptions::TypeError,
    557 1d7de6d9 + (boost::format("Cannot replace field with name '%s' because sizes differ.")
    % field.getName()).str() ); } item->field = field; return item->key; } else { throw LSST_EXCEPT(
    543 7e5c4d23 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    565 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Field with name '%s' already present in schema.") % field.getName()).str() ); } } else { if (_lastFlagField < 0 || _lastFlagBit >= ELEMENT_SIZE * 8) { int padding = ELEMENT_SIZE - _recordSize % ELEMENT_SIZE; if (padding != ELEMENT_SIZE) { _recordSize += padding; } _lastFlagField = _recordSize; _lastFlagBit = 0; _recordSize += field.getElementCount() * ELEMENT_SIZE; } SchemaItem item(detail::Access::makeKey(_lastFlagField, _lastFlagBit), field); ++_lastFlagBit; _flags.insert( std::pair,int>( std::make_pair(item.key.getOffset(), item.key.getBit()), _items.size() ) ); _items.push_back(item); return item.key; } } template Key SchemaImpl::addFieldImpl(int elementSize, int elementCount, Field const & field, bool doReplace) { std::pair result = _names.insert(std::pair(field.getName(), _items.size())); if (!result.second) { if (doReplace) { SchemaItem * item = boost::get< SchemaItem >(&_items[result.first->second]); if (!item) { throw LSST_EXCEPT(
    579 7e5c4d23 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^^^^ ----- ------- ^
    601 55b692d5 + lsst::pex::exceptions::TypeError,
    ? ^^^^^ ^ (boost::format("Cannot replace field with name '%s' because types differ.") % field.getName()).str() ); } // n.b. we don't use elementCount here because we *do* want variable length arrays (for // which we set elementCount == 1, but field->getElementCount() == -1) to compare as different // from fixed-length arrays with a single element. if (item->field.getElementCount() != field.getElementCount()) { throw LSST_EXCEPT(
    589 0b745ec6 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^^^^ ----- ------- ^
    611 2d6be90c + lsst::pex::exceptions::TypeError,
    ? ^^^^^ ^ (boost::format("Cannot replace field with name '%s' because sizes differ.") % field.getName()).str() ); } item->field = field; return item->key; } else { throw LSST_EXCEPT(
    598 7e5c4d23 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    620 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Field with name '%s' already present in schema.") % field.getName()).str() ); } } else { int padding = elementSize - _recordSize % elementSize; if (padding != elementSize) { _recordSize += padding; } SchemaItem item(detail::Access::makeKey(field, _recordSize), field); _recordSize += elementCount * elementSize; _offsets.insert(std::pair(item.key.getOffset(), _items.size())); _items.push_back(item); return item.key; } } } // namespace detail //----------------------------------------------------------------------------------------------------------- //----- Schema implementation ------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------
    621 03ea6486 - Schema::Schema() : _impl(boost::make_shared()) {};
    643 56df42d2 + int const Schema::DEFAULT_VERSION;
    645 56df42d2 + Schema::Schema() : _impl(boost::make_shared()), _aliases(boost::make_shared()) {
    646 56df42d2 + _impl->setVersion(DEFAULT_VERSION);
    647 56df42d2 + }
    648 56df42d2 +
    649 56df42d2 + Schema::Schema(int version) : _impl(boost::make_shared()), _aliases(boost::make_shared()) {
    650 56df42d2 + _impl->setVersion(version);
    651 56df42d2 + }
    652 03ea6486 +
    653 5a8fd800 + Schema::Schema(Schema const & other) :
    654 5a8fd800 + _impl(other._impl),
    655 5a8fd800 + _aliases(other._aliases)
    656 5a8fd800 + {}
    657 5a8fd800 +
    623 a676c4d1 - Schema::Schema(daf::base::PropertyList & metadata, bool stripMetadata) : _impl(boost::make_shared()) {
    ? ------------------------------------
    658 02e44d9b + Schema::Schema(daf::base::PropertyList & metadata, bool stripMetadata) :
    659 02e44d9b + _impl(boost::make_shared()), _aliases(boost::make_shared())
    660 02e44d9b + {
    io::FitsReader::_readSchema(*this, metadata, stripMetadata); }
    627 a676c4d1 - Schema::Schema(daf::base::PropertyList const & metadata) : _impl(boost::make_shared()) {
    ? ------------------------------------
    664 5a8fd800 + Schema::Schema(daf::base::PropertyList const & metadata) :
    665 5a8fd800 + _impl(boost::make_shared()),
    666 5a8fd800 + _aliases(boost::make_shared())
    667 5a8fd800 + {
    io::FitsReader::_readSchema(*this, const_cast(metadata), false);
    669 a676c4d1 + }
    670 a676c4d1 +
    671 4899a4da + std::string Schema::join(std::string const & a, std::string const & b) const {
    672 4899a4da + // delegate to utility funcs at top of this file
    673 4899a4da + return afw::table::join(a, b, getDelimiter(getVersion()));
    } void Schema::_edit() { if (!_impl.unique()) { boost::shared_ptr data(boost::make_shared(*_impl)); _impl.swap(data); } } std::set Schema::getNames(bool topOnly) const { return _impl->getNames(topOnly); } template SchemaItem Schema::find(std::string const & name) const {
    689 1f4ec8d4 + std::string tmp(name);
    690 1f4ec8d4 + _aliases->_apply(tmp);
    644 4909a663 - return _impl->find(name);
    ? ^^ ^
    691 1f4ec8d4 + return _impl->find(tmp);
    ? ^ ^ } template SchemaItem Schema::find(Key const & key) const { return _impl->find(key); } template Key Schema::addField(Field const & field, bool doReplace) { _edit(); return _impl->addField(field, doReplace); } template void Schema::replaceField(Key const & key, Field const & field) { _edit(); _impl->replaceField(key, field); } int Schema::contains(Schema const & other, int flags) const { if (_impl == other._impl) return flags; if (_impl->getItems().size() < other._impl->getItems().size()) return 0; int result = flags;
    715 1cdc3abd + if (result & EQUAL_FIELDS) {
    668 1c147ab4 - for (
    716 1cdc3abd + for (
    ? ++++
    669 1c147ab4 - Impl::ItemContainer::const_iterator i1 = _impl->getItems().begin(),
    717 1cdc3abd + Impl::ItemContainer::const_iterator i1 = _impl->getItems().begin(),
    ? ++++
    670 1c147ab4 - i2 = other._impl->getItems().begin();
    718 1cdc3abd + i2 = other._impl->getItems().begin();
    ? ++++
    671 1c147ab4 - i2 != other._impl->getItems().end();
    719 1cdc3abd + i2 != other._impl->getItems().end();
    ? ++++
    672 1c147ab4 - ++i1, ++i2
    720 1cdc3abd + ++i1, ++i2
    ? ++++
    673 1c147ab4 - ) {
    721 1cdc3abd + ) {
    ? ++++
    674 1c147ab4 - if ((result & EQUAL_KEYS) && !ItemFunctors::compareKeys(*i1, *i2)) result &= ~EQUAL_KEYS;
    722 1cdc3abd + if ((result & EQUAL_KEYS) && !ItemFunctors::compareKeys(*i1, *i2)) result &= ~EQUAL_KEYS;
    ? ++++
    675 1c147ab4 - if ((result & EQUAL_NAMES) && !ItemFunctors::compareNames(*i1, *i2)) result &= ~EQUAL_NAMES;
    723 1cdc3abd + if ((result & EQUAL_NAMES) && !ItemFunctors::compareNames(*i1, *i2)) result &= ~EQUAL_NAMES;
    ? ++++
    676 1c147ab4 - if ((result & EQUAL_DOCS) && !ItemFunctors::compareDocs(*i1, *i2)) result &= ~EQUAL_DOCS;
    724 1cdc3abd + if ((result & EQUAL_DOCS) && !ItemFunctors::compareDocs(*i1, *i2)) result &= ~EQUAL_DOCS;
    ? ++++
    677 1c147ab4 - if ((result & EQUAL_UNITS) && !ItemFunctors::compareUnits(*i1, *i2)) result &= ~EQUAL_UNITS;
    725 1cdc3abd + if ((result & EQUAL_UNITS) && !ItemFunctors::compareUnits(*i1, *i2)) result &= ~EQUAL_UNITS;
    ? ++++
    678 1c147ab4 - if (!result) break;
    726 1cdc3abd + if (!result) break;
    ? ++++
    679 1c147ab4 - }
    727 1cdc3abd + }
    ? ++++
    680 35ba793d -
    728 1c147ab4 + }
    729 1cdc3abd + if ((result & EQUAL_ALIASES) && !getAliasMap()->contains(*other.getAliasMap())) result &= ~EQUAL_ALIASES;
    return result; } int Schema::compare(Schema const & other, int flags) const {
    734 1cdc3abd + int result = contains(other, flags);
    685 1c147ab4 - return _impl->getItems().size() == other._impl->getItems().size() ? contains(other, flags) : 0;
    ? ^^^^^^^ - ------------------------ ^^^^
    735 1cdc3abd + if (_impl->getItems().size() != other._impl->getItems().size()) {
    ? ^^^^ + ^
    736 1cdc3abd + result &= ~EQUAL_FIELDS;
    737 1cdc3abd + }
    738 1cdc3abd + if (getAliasMap()->size() != other.getAliasMap()->size()) {
    739 1cdc3abd + result &= ~EQUAL_ALIASES;
    740 1cdc3abd + }
    741 1cdc3abd + return result;
    } template int Schema::contains(SchemaItem const & item, int flags) const { return _impl->contains(item, flags);
    747 35ba793d + }
    748 35ba793d +
    749 a7452ce2 + void Schema::setAliasMap(PTR(AliasMap) aliases) {
    750 5a8fd800 + if (!aliases) {
    751 5a8fd800 + aliases = boost::make_shared();
    752 5a8fd800 + }
    753 5a8fd800 + _aliases = aliases;
    754 02e44d9b + }
    755 02e44d9b +
    756 5a8fd800 + void Schema::disconnectAliases() {
    757 5a8fd800 + _aliases = boost::make_shared(*_aliases);
    } //----- Stringification ------------------------------------------------------------------------------------- namespace { // Schema::forEach functor used for stringificationx struct Stream { typedef void result_type; template void operator()(SchemaItem const & item) const { *os << " (" << item.field << ", " << item.key << "),\n"; } explicit Stream(std::ostream * os_) : os(os_) {} std::ostream * os; }; } // anonymous std::ostream & operator<<(std::ostream & os, Schema const & schema) { os << "Schema(\n"; schema.forEach(Stream(&os));
    784 88ebe97c + for (auto iter = schema.getAliasMap()->begin(); iter != schema.getAliasMap()->end(); ++iter) {
    785 88ebe97c + os << " '" << iter->first << "'->'" << iter->second << "'\n";
    786 5abbdeac + }
    return os << ")\n"; } //----------------------------------------------------------------------------------------------------------- //----- SubSchema implementation ---------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------
    794 5a8fd800 + SubSchema::SubSchema(PTR(Impl) impl, PTR(AliasMap) aliases, std::string const & name) :
    795 5a8fd800 + _impl(impl), _aliases(aliases), _name(name)
    796 5a8fd800 + {}
    797 5a8fd800 +
    template SchemaItem SubSchema::find(std::string const & name) const {
    726 4909a663 - return _impl->find(join(_name, name));
    800 1ad0851f + return _impl->find(_aliases->apply(join(_name, name, getDelimiter(_impl->getVersion()))));
    } SubSchema SubSchema::operator[](std::string const & name) const {
    730 4909a663 - return SubSchema(_impl, join(_name, name));
    804 1ad0851f + return SubSchema(_impl, _aliases, join(_name, name, getDelimiter(_impl->getVersion())));
    } std::set SubSchema::getNames(bool topOnly) const { return _impl->getNames(topOnly, _name); } //----------------------------------------------------------------------------------------------------------- //----- Explicit instantiation ------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------- // Note: by instantiating the public functions below, we also instantiate a lot of the private // implementation functions. If you move some of those to a different source file, you'll need // more explicit instantiation. #define INSTANTIATE_LAYOUT(r, data, elem) \ template Key< elem > Schema::addField(Field< elem > const &, bool); \
    747 5f166755 - template SchemaItem< elem > Schema::find(std::string const & ) const; \
    ? -
    821 1f4ec8d4 + template SchemaItem< elem > Schema::find(std::string const &) const; \
    748 5f166755 - template SchemaItem< elem > Schema::find(Key< elem > const & ) const; \
    ? -
    822 1f4ec8d4 + template SchemaItem< elem > Schema::find(Key< elem > const &) const; \
    template SchemaItem< elem > detail::SchemaImpl::find(std::string const & name ) const; \ template int Schema::contains(SchemaItem< elem > const &, int) const; \ template void Schema::replaceField(Key< elem > const &, Field< elem > const &); \ template SchemaItem< elem > SubSchema::find(std::string const & ) const; \ BOOST_PP_SEQ_FOR_EACH( INSTANTIATE_LAYOUT, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_FIELD_TYPE_N, AFW_TABLE_FIELD_TYPE_TUPLE) ) }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7e5c4d23

    commit 7e5c4d2338fe4fb88e187860a49a42c8fc2c50f4
    Author: Jim Bosch 
    Date:   Wed Nov 20 16:08:46 2013 -0500
    
        Add support for replacing fields in Schema.addField (#3066)
    

    d6480e01

    commit d6480e01cf98ec6e6ebea9b7f58d2d9dcef6beef
    Author: Jim Bosch 
    Date:   Sun Feb 5 23:11:25 2012 -0500
    
        lots of documentation, and a little refactoring to improve readability
    

    78a55502

    commit 78a55502451f2f1e1643dfe0bbf218df12979503
    Author: Jim Bosch 
    Date:   Fri Dec 2 17:20:19 2011 -0500
    
        switched Layout from Boost.Fusion to Boost.Variant implementation
    

    1c147ab4

    commit 1c147ab469f93e95cbfe5c535622199cf683536f
    Author: Jim Bosch 
    Date:   Mon Dec 10 12:51:20 2012 -0500
    
        More detailed comparisons for Schema.
    

    0b745ec6

    commit 0b745ec681de903b911691c49f07f3ebc52c692f
    Author: Jim Bosch 
    Date:   Mon Dec 1 13:46:03 2014 -0500
    
        Add variable-length array fields to afw::table
        
        We use Array with a size of zero to indicate variable-length fields.
        It'd probably be better to use a completely different tag type, but
        Boost.Variant puts an upper limit on how many tags we have, so until
        we rewrite afw::table to avoid it, we need to limit how many we use.
    

    5f166755

    commit 5f1667553d7a49c4f19089c57f6c06cd0e4fa58c
    Author: Jim Bosch 
    Date:   Mon Dec 12 16:45:43 2011 -0500
    
        renamed Layout to Schema
    

    03ea6486

    commit 03ea6486684bf284f7428c2f7cec0fc15b7c6172
    Author: Jim Bosch 
    Date:   Thu Jan 26 18:11:15 2012 -0500
    
        afw now building successfully, but with limited SWIG for table and corresponding unit test failures
    

    5a8a1997

    commit 5a8a19977ac3dfacf009e4c3b95b48287ce57fea
    Author: Jim Bosch 
    Date:   Wed Dec 14 16:59:32 2011 -0500
    
        added equality comparison to Schema
    

    2fd496f2

    commit 2fd496f29270b47eda99d38c3ee0c0423279568b
    Author: Jim Bosch 
    Date:   Wed Dec 14 00:47:50 2011 -0500
    
        implemented SubSchema, some syntactic sugar for Schema lookups
    

    35ba793d

    commit 35ba793db845ad818cf7cdb8d83b2b0354413371
    Author: Jim Bosch 
    Date:   Fri Jan 4 20:17:42 2013 -0500
    
        Add generally-used SchemaMapper features that we'll want for ExposureCatalog persistence.
    

    4909a663

    commit 4909a663c907e0bd31fe4a48200b47ead26d6292
    Author: Jim Bosch 
    Date:   Wed Dec 14 13:36:28 2011 -0500
    
        renamed SchemaData -> SchemaImpl and made it more encapsulated, more support for subfield access with Schema::find
    

    adb41ee9

    commit adb41ee9be684c9913cef33b6479aa5488ce1e1a
    Author: Jim Bosch 
    Date:   Tue Dec 13 18:54:04 2011 -0500
    
        started adding dotted namespace support for fields - stubby SchemaProxy and subfield lookup by name in Schema::find
    

    a676c4d1

    commit a676c4d10960abbf48f5d9a114940753f5cddefd
    Author: Jim Bosch 
    Date:   Wed Feb 8 19:28:55 2012 -0500
    
        Added Schema-from-PropertyList constructor, started using it for FITS reading
    

    Commits in /Users/nate/repos_lsst/afw/

    56df42d2

    commit 56df42d2bb5dd4ebec2e5c67b0d16a137bb1dee2
    Author: Jim Bosch 
    Date:   Wed Aug 20 13:27:23 2014 -0400
    
        Add constructors to Schema and SchemaMapper to set version immediately.
    

    88ebe97c

    commit 88ebe97c14c6e9e1f84e71d2c39ac8782c4e574e
    Author: Jim Bosch 
    Date:   Fri Feb 6 18:53:44 2015 -0600
    
        Revert premature usage of range-based for-loop
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    a7452ce2

    commit a7452ce222551998eaff639f457528a35a31dd54
    Author: Jim Bosch 
    Date:   Thu Jul 10 11:36:08 2014 -0400
    
        Rename AliasMap accessors
    

    02e44d9b

    commit 02e44d9b44fd74662b230dc5858419ca24d10788
    Author: Jim Bosch 
    Date:   Mon Oct 1 18:50:43 2012 -0400
    
        first implementation of aliases for Schemas; no persistence yet
    

    03ea6486

    commit 03ea6486684bf284f7428c2f7cec0fc15b7c6172
    Author: Jim Bosch 
    Date:   Thu Jan 26 18:11:15 2012 -0500
    
        afw now building successfully, but with limited SWIG for table and corresponding unit test failures
    

    a25b9eb2

    commit a25b9eb2df1c00b862411068c0447f4391bb12f4
    Author: pgee 
    Date:   Wed Mar 4 17:06:38 2015 -0800
    
        DM-1076, remove need of unit tests to setVersion(0), and move tests to default version.
        
        Note that there are several version tests in the unit tests which should not be changed.
        Also needed to change Schema::getNames to use the '_' separator for version > 0.
        Also included responses to review comments
    

    a676c4d1

    commit a676c4d10960abbf48f5d9a114940753f5cddefd
    Author: Jim Bosch 
    Date:   Wed Feb 8 19:28:55 2012 -0500
    
        Added Schema-from-PropertyList constructor, started using it for FITS reading
    

    1cdc3abd

    commit 1cdc3abd3e98c1e71e2a76754e02ece73b08230c
    Author: Jim Bosch 
    Date:   Wed Jan 21 16:56:28 2015 -0500
    
        Include aliases in Schema comparison methods.
    

    1c147ab4

    commit 1c147ab469f93e95cbfe5c535622199cf683536f
    Author: Jim Bosch 
    Date:   Mon Dec 10 12:51:20 2012 -0500
    
        More detailed comparisons for Schema.
    

    1f4ec8d4

    commit 1f4ec8d43083ba12f4896c8e05727435de82247b
    Author: Jim Bosch 
    Date:   Fri Jul 11 18:26:39 2014 -0400
    
        Minor tweaks to AliasMap for review of DM-417
    

    76213222

    commit 762132227095196d35b49a0fc111b05eaa4f9c5b
    Author: Jim Bosch 
    Date:   Mon Aug 25 15:49:15 2014 -0400
    
        Reorder methods in Schema implementation to improve readability
    

    1ad0851f

    commit 1ad0851fe7f9b4642f701986230d1e96fa456644
    Author: Jim Bosch 
    Date:   Wed Aug 20 16:39:01 2014 -0400
    
        Switch between '.' and '_' separators in Schema, depending on version.
    

    4899a4da

    commit 4899a4dafc36ff465cca197db1051b2525209af7
    Author: Jim Bosch 
    Date:   Wed Oct 1 14:41:45 2014 -0400
    
        Add Schema methods to join strings using appropriate delimiter.
        
        The appropriate delimiter for field names depends on the schema version, making it
        difficult to write version-independent code without something like these
        convenience methods.
    

    55b692d5

    commit 55b692d5d02e72b84aa9efe49e1d212f0a807db5
    Author: Jim Bosch 
    Date:   Mon Oct 6 12:51:46 2014 -0400
    
        Be more consistent about exceptions thrown/caught in Schema::find
        
        The Python-level code, which loops over all the C++ template instantiations until it
        finds one that doesn't throw, was catching all Exceptions, not just those that meant
        the field couldn't be found with the given type.
    

    40bacb3d

    commit 40bacb3d7713576c1cfe6cc5b49fb7e3563035ba
    Author: Jim Bosch 
    Date:   Sun Mar 23 12:48:42 2014 -0400
    
        Check for past-the-end in Schema::find(key)
    

    5abbdeac

    commit 5abbdeac756100cd9cc25be24b90122256d7565d
    Author: Jim Bosch 
    Date:   Wed Jan 21 15:50:36 2015 -0500
    
        Include aliases in Schema stringification.
        
        We just print the aliases as-is after we print the regular fields.
    

    7e5c4d23

    commit 7e5c4d2338fe4fb88e187860a49a42c8fc2c50f4
    Author: Jim Bosch 
    Date:   Wed Nov 20 16:08:46 2013 -0500
    
        Add support for replacing fields in Schema.addField (#3066)
    

    1d7de6d9

    commit 1d7de6d9468eaa44b004815bd1c60755fa7a6a5d
    Author: Jim Bosch 
    Date:   Fri Jan 10 17:08:47 2014 -0500
    
        When replacing fields in Schemas, need to ensure the size doesn't change.
    

    2d6be90c

    commit 2d6be90c6e14ab8fa2803a84a45106345037f1f5
    Author: Lauren MacArthur 
    Date:   Thu Apr 2 13:50:52 2015 -0400
    
        Remove trailing Exception in exception names
    

    35ba793d

    commit 35ba793db845ad818cf7cdb8d83b2b0354413371
    Author: Jim Bosch 
    Date:   Fri Jan 4 20:17:42 2013 -0500
    
        Add generally-used SchemaMapper features that we'll want for ExposureCatalog persistence.
    

    4909a663

    commit 4909a663c907e0bd31fe4a48200b47ead26d6292
    Author: Jim Bosch 
    Date:   Wed Dec 14 13:36:28 2011 -0500
    
        renamed SchemaData -> SchemaImpl and made it more encapsulated, more support for subfield access with Schema::find
    

    5a8fd800

    commit 5a8fd8002be06d2b85139d4b81685f725b266f84
    Author: Jim Bosch 
    Date:   Wed Jul 9 15:52:43 2014 -0400
    
        Move Schema aliases into their own object
        
        Aliases are now used by SubSchema as well, and are shared
        by Schemas when Schemas are copied; disconnecting them
        is explicit (this may be a little confusing, but it matches what
        we want 99% of the time, and we'd need a bigger refactor to
        get an unconfusing solution).
    

    Return to list

    python/lsst/afw/fits/fitsLib.i

    Diff:

                    %define fitsLib_DOCSTRING
                    "
                    Python interface to lsst::afw::fits exception classes
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.fits", docstring=fitsLib_DOCSTRING) fitsLib
                    
                    %{
                    #include "lsst/afw/fits.h"
                    #include "lsst/pex/exceptions.h"
                    %}
                    
                    %include "cdata.i"
                    
                    %include "lsst/p_lsstSwig.i"
                    
                    %lsst_exceptions();
                    
                    %pythonnondynamic;
                    %naturalvar;  // use const reference typemaps
                    
                    %import "lsst/pex/exceptions/exceptionsLib.i"
                    
                    %include "lsst/afw/fits.h"
                    
    
    28 adb78502 - %types(lsst::afw::fits::FitsError *);
    29 adb78502 - %types(lsst::afw::fits::FitsTypeError *);
    28 6fc1c3d1 + %declareException(FitsError, lsst.pex.exceptions.IoError, lsst::afw::fits::FitsError)
    29 6fc1c3d1 + %declareException(FitsTypeError, FitsError, lsst::afw::fits::FitsTypeError)
    namespace lsst { namespace afw { namespace fits { struct MemFileManager { MemFileManager(); MemFileManager(std::size_t len); void* getData() const; std::size_t getLength() const; }; }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    adb78502

    commit adb7850213df954a184cdcf53ee2b778e5d8699c
    Author: Jim Bosch 
    Date:   Mon Nov 19 13:43:47 2012 -0500
    
        Make afw::fits exceptions visible in Python.
    

    Commits in /Users/nate/repos_lsst/afw/

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    python/lsst/afw/cameraGeom/cameraGeomLib.i

    Diff:

                    // -*- lsst-++ -*-
                    
    
    3 a6d55f08 - /*
    ? -
    3 324024fb + /*
    * LSST Data Management System * Copyright 2008, 2009, 2010 LSST Corporation.
    6 a6d55f08 - *
    ? -
    6 324024fb + *
    * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
    14 a6d55f08 - *
    ? -
    14 324024fb + *
    * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
    19 a6d55f08 - *
    ? -
    19 324024fb + *
    20 a6d55f08 - * You should have received a copy of the LSST License Statement and
    ? -
    20 324024fb + * You should have received a copy of the LSST License Statement and
    21 a6d55f08 - * the GNU General Public License along with this program. If not,
    ? -
    21 324024fb + * the GNU General Public License along with this program. If not,
    * see . */
    24 a6d55f08 -
    24 324024fb +
    25 292866b7 + // used by lsst/afw/image/imageLib.i to avoid circular import
    26 292866b7 + // can be removed if and when this file does not need imageLib.i
    #define CAMERA_GEOM_LIB_I %define cameraGeomLib_DOCSTRING " Python bindings for classes describing the the geometry of a mosaic camera " %enddef %feature("autodoc", "1"); %module(package="lsst.afw.cameraGeom", docstring=cameraGeomLib_DOCSTRING) cameraGeomLib %{
    39 7b9f89c5 + #include
    40 7b9f89c5 + #include
    41 f9f7ab1f + #include
    #include "boost/shared_ptr.hpp"
    38 d95640da - #include "lsst/afw/geom.h"
    39 80f5979b - #include "lsst/afw/geom/ellipses.h"
    #include "lsst/pex/logging.h"
    41 4563d0f0 - #include "lsst/afw/image.h"
    44 6f5ea58d + #include "lsst/afw/geom/TransformMap.h"
    #include "lsst/afw/cameraGeom.h" %} %include "lsst/p_lsstSwig.i"
    46 eaf3b304 - %include "lsst/afw/utils.i"
    ? -
    49 324024fb + %include "lsst/afw/utils.i"
    50 f9f7ab1f + %include "std_map.i"
    %import "lsst/afw/geom/geomLib.i"
    53 18439e6c + %import "lsst/afw/table/AmpInfo.i"
    55 853c5734 + %initializeNumPy(afw_cameraGeom)
    50 f5604129 - #if defined(IMPORT_IMAGE_I)
    51 868729ec - %import "lsst/afw/image/imageLib.i"
    52 868729ec - %import "lsst/afw/geom/ellipses/ellipsesLib.i"
    53 dead4225 - #endif
    54 60edffcc -
    %lsst_exceptions(); %shared_ptr(lsst::afw::cameraGeom::Detector);
    58 4563d0f0 - %shared_ptr(lsst::afw::cameraGeom::Amp);
    59 4563d0f0 - %shared_ptr(lsst::afw::cameraGeom::ElectronicParams);
    60 4563d0f0 - %shared_ptr(lsst::afw::cameraGeom::DetectorMosaic);
    61 4563d0f0 - %shared_ptr(lsst::afw::cameraGeom::Ccd);
    62 4563d0f0 - %shared_ptr(lsst::afw::cameraGeom::Raft);
    63 4563d0f0 - %shared_ptr(lsst::afw::cameraGeom::Camera);
    64 80f5979b - %shared_ptr(lsst::afw::cameraGeom::Distortion);
    65 80f5979b - %shared_ptr(lsst::afw::cameraGeom::NullDistortion);
    66 80f5979b - %shared_ptr(lsst::afw::cameraGeom::RadialPolyDistortion);
    68 85c4c76e - %template(AmpSet) std::vector >;
    60 3d477d32 + %template(CameraSysList) std::vector;
    61 6f5ea58d + // I would prefer to use lsst::afw::geom::TransformMap::Transforms
    62 6f5ea58d + // in the following, but SIG complains of a syntax error
    63 324024fb + %template(CameraTransforms)
    64 3d477d32 + std::map;
    65 6f5ea58d + %template(CameraTransformMap) lsst::afw::geom::TransformMap;
    69 4b6acf34 - %template(DetectorSet) std::vector >;
    ? ^^ ^^^^^^^^^^^^^ ^^^^ ^^
    66 3d477d32 + %template(DetectorList) std::vector;
    ? ^^^ ^^^^^ ^^^^ ^
    71 60edffcc - %include "lsst/afw/cameraGeom/Id.h"
    68 53103713 + %rename(__getitem__) lsst::afw::cameraGeom::Detector::operator[];
    69 e6a90084 + %rename(__len__) lsst::afw::cameraGeom::Detector::size;
    70 e6a90084 + %ignore lsst::afw::cameraGeom::Detector::begin;
    71 e6a90084 + %ignore lsst::afw::cameraGeom::Detector::end;
    73 4b6acf34 - %extend lsst::afw::cameraGeom::Id {
    74 4b6acf34 - %pythoncode {
    75 4b6acf34 - def __str__(self):
    76 61a76714 - return "%d, %s" % (self.getSerial(), self.getName())
    73 292866b7 + %include "lsst/afw/cameraGeom/CameraSys.h"
    74 292866b7 + %include "lsst/afw/cameraGeom/CameraPoint.h"
    75 78652121 + %include "lsst/afw/cameraGeom/Orientation.h"
    76 1ac3f936 + %include "lsst/afw/cameraGeom/Detector.h"
    78 f0efcab9 + # macros from p_lsstSWig.i
    79 f0efcab9 + %addStreamRepr(lsst::afw::cameraGeom::CameraSysPrefix)
    80 f0efcab9 + %useValueEquality(lsst::afw::cameraGeom::CameraSysPrefix)
    81 f0efcab9 + %addStreamRepr(lsst::afw::cameraGeom::CameraSys)
    82 f0efcab9 + %useValueEquality(lsst::afw::cameraGeom::CameraSys)
    83 6ef62d51 + %addStreamRepr(lsst::afw::cameraGeom::CameraPoint)
    84 6ef62d51 + %useValueEquality(lsst::afw::cameraGeom::CameraPoint)
    85 f9f7ab1f +
    86 9cb20169 + %extend lsst::afw::cameraGeom::CameraSys {
    87 324024fb + %pythoncode %{
    78 61a76714 - def __repr__(self):
    ? ^^^^
    88 9cb20169 + def __hash__(self):
    ? ^^^^
    79 61a76714 - return "Id(%s)" % (str(self))
    89 9cb20169 + return hash(repr(self))
    80 4b6acf34 - }
    90 81c3bd10 + %}
    ? +
    81 4b6acf34 - }
    82 df438a72 - %pythoncode {
    83 0efdb5e2 - # See comment in Orientation.h
    84 df438a72 - import lsst.afw.geom # needed for initialising Orientation
    85 df438a72 - radians = lsst.afw.geom.radians
    }
    93 f9f7ab1f + %extend lsst::afw::cameraGeom::Detector {
    94 81c3bd10 + %pythoncode %{
    95 f9f7ab1f + def __iter__(self):
    96 f9f7ab1f + for i in xrange(len(self)):
    97 f9f7ab1f + yield self[i]
    88 d95640da - %shared_ptr(lsst::afw::cameraGeom::DetectorXYTransform);
    89 d95640da -
    90 e88ff0cd - %include "lsst/afw/cameraGeom/FpPoint.h"
    91 78652121 - %include "lsst/afw/cameraGeom/Orientation.h"
    92 1ac3f936 - %include "lsst/afw/cameraGeom/Detector.h"
    93 2ebad60d - %include "lsst/afw/cameraGeom/Amp.h"
    94 fcffe104 - %include "lsst/afw/cameraGeom/DetectorMosaic.h"
    95 60edffcc - %include "lsst/afw/cameraGeom/Ccd.h"
    96 1ac3f936 - %include "lsst/afw/cameraGeom/Raft.h"
    97 12fe8a71 - %include "lsst/afw/cameraGeom/Camera.h"
    98 9a0b3ed0 - %include "lsst/afw/cameraGeom/Distortion.h"
    99 60edffcc -
    100 38481def - %define DistortInstantiate(PIXEL)
    101 9cee260a - %template(distort) lsst::afw::cameraGeom::Distortion::distort >;
    102 9cee260a - %template(distort) lsst::afw::cameraGeom::Distortion::distort >;
    103 9cee260a - %template(undistort) lsst::afw::cameraGeom::Distortion::undistort >;
    104 9cee260a - %template(undistort) lsst::afw::cameraGeom::Distortion::undistort >;
    105 38481def - %enddef
    106 38481def -
    107 38481def - DistortInstantiate(float);
    108 38481def - DistortInstantiate(double);
    109 38481def -
    110 60edffcc -
    111 85c4c76e - %inline %{
    112 87609d92 - lsst::afw::cameraGeom::DetectorMosaic::Ptr
    113 87609d92 - cast_DetectorMosaic(lsst::afw::cameraGeom::Detector::Ptr detector) {
    114 df24c4ab - return boost::dynamic_pointer_cast(detector);
    115 87609d92 - }
    98 81c3bd10 + %}
    ? +
    116 87609d92 -
    117 b59df3c7 - lsst::afw::cameraGeom::Amp::Ptr
    118 b59df3c7 - cast_Amp(lsst::afw::cameraGeom::Detector::Ptr detector) {
    119 df24c4ab - return boost::dynamic_pointer_cast(detector);
    120 b59df3c7 - }
    121 b59df3c7 -
    122 644806bf - lsst::afw::cameraGeom::Ccd::Ptr
    123 644806bf - cast_Ccd(lsst::afw::cameraGeom::Detector::Ptr detector) {
    124 df24c4ab - return boost::dynamic_pointer_cast(detector);
    125 85c4c76e - }
    126 f846bf5f -
    127 644806bf - lsst::afw::cameraGeom::Raft::Ptr
    128 644806bf - cast_Raft(lsst::afw::cameraGeom::Detector::Ptr detector) {
    129 df24c4ab - return boost::dynamic_pointer_cast(detector);
    130 f846bf5f - }
    131 4563d0f0 -
    132 85c4c76e - %}
    133 7ffd25c1 -
    134 7ffd25c1 - %define Instantiate(PIXEL_TYPE...)
    135 7ffd25c1 - %template(prepareAmpData)
    136 7ffd25c1 - lsst::afw::cameraGeom::Amp::prepareAmpData >;
    137 3396129a - %template(prepareAmpData)
    138 3396129a - lsst::afw::cameraGeom::Amp::prepareAmpData >;
    139 7ffd25c1 - %enddef
    140 7ffd25c1 -
    141 7ffd25c1 - Instantiate(boost::uint16_t);
    142 7ffd25c1 - Instantiate(float);
    143 6a69940a - Instantiate(double);
    144 6a69940a - %template(prepareAmpData)
    145 6a69940a - lsst::afw::cameraGeom::Amp::prepareAmpData >;
    146 7ffd25c1 -
    147 fcffe104 - %definePythonIterator(lsst::afw::cameraGeom::Ccd);
    148 fcffe104 - %definePythonIterator(lsst::afw::cameraGeom::DetectorMosaic);
    149 61a76714 -
    150 61a76714 - %pythoncode {
    151 61a76714 - class ReadoutCorner(object):
    152 61a76714 - """A python object corresponding to Amp::ReadoutCorner"""
    153 61a76714 - def __init__(self, value):
    154 61a76714 - self.value = value
    155 61a76714 -
    156 61a76714 - def __repr__(self):
    157 61a76714 - return ["LLC", "LRC", "URC", "ULC"][self.value]
    }
    159 d95640da -

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9a0b3ed0

    commit 9a0b3ed09fa81b663487c75696e7198af0cf257d
    Author: bick 
    Date:   Fri Aug 26 23:03:09 2011 +0000
    
        #1753 (not yet working) distortion stuff initial check-in.
    

    7ffd25c1

    commit 7ffd25c1b6fa71ec4641f4718d6eddc839f7a758
    Author: rhl 
    Date:   Sun Apr 4 15:59:56 2010 +0000
    
        Added support for amps being stored on disk in separate files
    

    4563d0f0

    commit 4563d0f054173793ca51c25afdac392dc16bdb19
    Author: smm 
    Date:   Wed Nov 9 02:57:43 2011 +0000
    
        afw Winter2012b: upgrade to swig 2.x
    

    12fe8a71

    commit 12fe8a71ecd4720374bcfabd70c42c7108607f97
    Author: rhl 
    Date:   Fri Jan 8 00:33:43 2010 +0000
    
        Made Camera a real C++ object, not just a python alias for Raft
    

    87609d92

    commit 87609d92d9b7cea0e8266f9fb47969cb78358935
    Merge: b1f3d4b 354c9f4
    Author: rhl 
    Date:   Thu Mar 3 12:08:33 2011 +0000
    
        Merged from trunk
    

    f5604129

    commit f5604129cee1649678d7592756433f288ed781d8
    Author: rhl 
    Date:   Wed Apr 7 22:24:32 2010 +0000
    
        Really fix that circular dependency
    

    1ac3f936

    commit 1ac3f9368c1453487cfea8334ba310c339552ede
    Author: rhl 
    Date:   Wed Jan 6 19:59:28 2010 +0000
    
        Initial version of Raft code
    

    38481def

    commit 38481defbecadf0f2bc013d517379a00f78332fd
    Author: Steven Bickerton 
    Date:   Mon Dec 19 10:27:25 2011 -0600
    
        basic working design, but needs cleanup.
    

    644806bf

    commit 644806bfe333cc769f072ba40c33474b52db5093
    Author: rhl 
    Date:   Thu Jan 21 08:14:22 2010 +0000
    
        We must return shared pointers from casts as the parent object can evaporate under us
    

    868729ec

    commit 868729ecbe0d584bdca43d5a0965a4722ebe5cc7
    Author: Steven Bickerton 
    Date:   Fri Dec 9 13:45:30 2011 -0600
    
        switched out the Moment class and now use ellipses/Quadrupole
    

    fcffe104

    commit fcffe104d0facbb57b73c22ba5d2ee6cd6e1e29d
    Author: rhl 
    Date:   Thu Jan 7 15:33:24 2010 +0000
    
        Move Raft implementation into DetectorMosaic
    

    4b6acf34

    commit 4b6acf347c723a61081eb7211584ce7712372ddb
    Author: rhl 
    Date:   Wed Jan 13 06:32:59 2010 +0000
    
        Got rotation of detectors by 90n degrees (and non-square dataSecs) working
    

    e88ff0cd

    commit e88ff0cd6d8b7e3b4173c8fd71f33e78b407c782
    Author: Steven Bickerton 
    Date:   Tue Jan 31 10:02:20 2012 -0600
    
        split FpPosition to FpPoint/Extent.
    

    85c4c76e

    commit 85c4c76e09060f18e330cc23ba9f59d214b844d7
    Author: rhl 
    Date:   Wed Jan 6 23:40:06 2010 +0000
    
        Added DetectorLayout; misc
    

    78652121

    commit 78652121c24a3aeaddbbbeecdbced15c38140e08
    Author: rhl 
    Date:   Fri Jan 8 19:08:35 2010 +0000
    
        Get detector centres right
    

    9cee260a

    commit 9cee260ab479f59cf80910271f615464bbe66e5c
    Author: Steven Bickerton 
    Date:   Thu Dec 22 19:18:55 2011 -0500
    
        additional work for 1753
    

    b59df3c7

    commit b59df3c79a2ade62aa501aba74b396720a335eeb
    Author: rhl 
    Date:   Fri Apr 9 16:16:46 2010 +0000
    
        Add dynamic_cast to Amp
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    df24c4ab

    commit df24c4abb58e5a26fb96390d4fa47b5e6bc47c0f
    Author: Paul Price 
    Date:   Tue Nov 19 21:00:24 2013 -0600
    
        replace deprecated boost::shared_dynamic_cast (#3063)
        
        Required to up-rev to boost 1.55.0.
    

    eaf3b304

    commit eaf3b304012319a76db97dfeaf32d0dcc0fb717e
    Author: jbosch 
    Date:   Fri Oct 14 22:11:46 2011 +0000
    
        afw #1780 - now building with new sconsUtils and third-party packages (aside from gsl+interpolation issues and tests currently also failing on trunk).
    

    60edffcc

    commit 60edffccd7fc85402e9e6f1c0e5fa0021f9af237
    Author: rhl 
    Date:   Tue Jan 5 22:24:46 2010 +0000
    
        Initial implementation of cameraGeom up to Ccd/Detector
    

    d95640da

    commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
    Author: Kendrick Smith 
    Date:   Tue Feb 19 23:44:14 2013 -0500
    
        move afw::image::XYTransform -> afw::geom::XYTransform
             afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
             afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
        
        wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom
    

    61a76714

    commit 61a767146003c7e685e721336eb99940dec4baf3
    Author: rhl 
    Date:   Thu Jan 14 04:25:43 2010 +0000
    
        Got showCamera working with SuPrimeCam, misc cleanup
    

    2ebad60d

    commit 2ebad60ddfd2a217aa139655a0e6e7e578da48d2
    Author: rhl 
    Date:   Fri Jan 15 07:57:27 2010 +0000
    
        Started adding Defect support;  make Amp inherit from Detector
    

    f846bf5f

    commit f846bf5f70d586fbc1d57759baddd6182dbf4c6a
    Author: rhl 
    Date:   Thu Jan 7 14:14:46 2010 +0000
    
        Worked on camera geometry and building a Camera as an Raft of Rafts
    

    3396129a

    commit 3396129a94ac065d8ea106ae023d6b4a65520e50
    Author: Robert Lupton the Good 
    Date:   Sat Feb 23 09:04:07 2013 +0900
    
        prepareAmpData needs to be able to handle a MaskedImage (#2685)
        
        This avoids ugly work-arounds in e.g. ip_isr
    

    80f5979b

    commit 80f5979bbac2803a4e4bdf73fdd2d6a009c2470b
    Merge: 237cd55 ecd1171
    Author: Steven Bickerton 
    Date:   Wed Feb 1 10:21:06 2012 -0600
    
        merged master into tickets/1753.  all tests pass.
    

    df438a72

    commit df438a724651ee2a107de2df8b27094d34d050b8
    Author: Robert Lupton the Good 
    Date:   Wed Feb 1 12:29:57 2012 -0500
    
        Use Angle for cameraGeom::Orientation; #1879
    

    6a69940a

    commit 6a69940a55ff1ea529b6683e670f80d1296d2a15
    Author: krughoff 
    Date:   Fri Apr 23 22:36:42 2010 +0000
    
        Added templates for MaskU to preapareAmpData, rotateby90 and flipImage
    

    dead4225

    commit dead42255c0f4ae358eac37be99c441cfba698fe
    Author: rhl 
    Date:   Wed Apr 7 21:25:31 2010 +0000
    
        Correctly resolve circular cameraGeom <--> image dependencies
    

    0efdb5e2

    commit 0efdb5e243515f4627c69f2a7f0a9234112d3b7c
    Author: Robert Lupton the Good 
    Date:   Tue Jun 5 10:50:51 2012 -0400
    
        Clarified the necessity for the AFW_GEOM_RADIANS define
    

    Commits in /Users/nate/repos_lsst/afw/

    292866b7

    commit 292866b7fef0dae7645940247f3207aa1d7d41ff
    Author: Russell Owen 
    Date:   Mon Jan 27 12:48:51 2014 -0800
    
        Added RawAmplifier and Amplifier and a first cut at cameraGeomLib.i.
    

    6f5ea58d

    commit 6f5ea58df69e1713505a44d25dbbd0e121bd6aff
    Author: Russell Owen 
    Date:   Tue Feb 18 11:25:54 2014 -0800
    
        Rename TransformRegistry to TransformMap and TransformMap to TransformMap::Transforms
    

    7b9f89c5

    commit 7b9f89c5d3a8bdedaf50793abaf4d5322716b892
    Author: Russell Owen 
    Date:   Mon Jan 27 16:31:54 2014 -0800
    
        Switch TransformRegistry to unordered_map.
        It all builds but the swig wrapper for cameraGeom isn't working due to a missing symbol.
    

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    78652121

    commit 78652121c24a3aeaddbbbeecdbced15c38140e08
    Author: rhl 
    Date:   Fri Jan 8 19:08:35 2010 +0000
    
        Get detector centres right
    

    18439e6c

    commit 18439e6c1fd05dc7d44b17a6178ef0de5c1b7e38
    Author: Russell Owen 
    Date:   Fri Feb 14 09:30:39 2014 -0800
    
        Detector tests pass.
    

    9cb20169

    commit 9cb20169f0639305b7d26eaa5c67d3038d503b8d
    Author: Russell Owen 
    Date:   Wed Jan 29 16:28:33 2014 -0800
    
        Renamed DetectorSysPrefix to BaseCameraSys and removed its detector name. This makes it more type safe.
        Fixed a bug this exposed in how Detector constructs its transform registry.
    

    f9f7ab1f

    commit f9f7ab1f2b42457bfc4281097a2d1499db0eecfd
    Author: Russell Owen 
    Date:   Wed Jan 29 13:14:57 2014 -0800
    
        Vastly improved SWIG interface files. Better unit tests.
    

    e6a90084

    commit e6a90084e77396fe175f998cf9c3dd13a175ff4f
    Author: Russell Owen 
    Date:   Fri Jan 31 11:11:19 2014 -0800
    
        Fixed Detector.convert's handling of CameraSysPrefix.
        Improved SWIG files, getting rename and ignore to work in most cases
        (TransformRegistry still needs %extend to handle operator[] for reasons I don't understand).
        Finished detector unit test.
    

    3d477d32

    commit 3d477d32c28c5b73a3b31aa42c9794a7fdcfcc68
    Author: Russell Owen 
    Date:   Thu Jan 30 17:14:39 2014 -0800
    
        Add CameraSys(CameraSysPrefix, detectorName) constructor to simplify constructing transform maps for Detector.
        Added a very preliminary unit test for Detector.
    

    6ef62d51

    commit 6ef62d51cc5fcf3ac04bcbadc5843615f224eb11
    Author: Russell Owen 
    Date:   Fri Nov 14 12:21:37 2014 -0800
    
        Add operators ==, != and stream << to CameraPoint
    

    853c5734

    commit 853c5734ee13f55fd35e9e18ed5ac69a0073b97f
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:18:28 2015 -0400
    
        Utilize new numeric scalar typemaps and NumPy import macro.
    

    f0efcab9

    commit f0efcab96e3f0bd7bee50dffc26f9f55f065d375
    Author: Russell Owen 
    Date:   Mon Mar 10 08:45:27 2014 -0700
    
        Tweak cameraGeomLib.i as per Jim's suggestions.
    

    53103713

    commit 531037134e2536729ffb184757d1f710dc4aa2f5
    Author: Russell Owen 
    Date:   Wed Jan 29 14:07:51 2014 -0800
    
        Refine doc strings, method names and SWIG files.
    

    1ac3f936

    commit 1ac3f9368c1453487cfea8334ba310c339552ede
    Author: rhl 
    Date:   Wed Jan 6 19:59:28 2010 +0000
    
        Initial version of Raft code
    

    324024fb

    commit 324024fbcd5691b826a1d24a2ed80ab1bf8721af
    Author: Russell Owen 
    Date:   Mon Mar 16 16:30:21 2015 -0700
    
        Remove trailing whitespace in cameraGeomLib.i
    

    Return to list

    include/lsst/afw/geom/AffineTransform.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008-2014 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #ifndef LSST_AFW_MATH_AFFINE_TRANSFORM_H
                    #define LSST_AFW_MATH_AFFINE_TRANSFORM_H
                    
                    #include 
                    #include "Eigen/Core"
                    #include 
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/geom/Extent.h"
                    #include "lsst/afw/geom/LinearTransform.h"
                    #include "lsst/afw/geom/Angle.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace geom {
                    
                    /**
                     *  \brief An affine coordinate transformation consisting of a linear transformation and an offset.
                     *
                     *  The transform is represented by a matrix \f$ \mathbf{M} \f$ such that
                     *  \f[
                     *     \left[\begin{array}{ c }
                     *     x_f \\
                     *     y_f \\
                     *     1
                     *     \end{array}\right]
                     *     =
                     *     \mathbf{M}
                     *     \left[\begin{array}{ c }
                     *     x_i \\
                     *     y_i \\
                     *     1
                     *     \end{array}\right]
                     *  \f]
                     *  where \f$(x_i,y_i)\f$ are the input coordinates and \f$(x_f,y_f)\f$ are the output coordinates.
                     *
                     *  If \f$ x_f(x_i,y_i) \f$ and \f$ y_f(x_i,y_i) \f$ are continuous differentiable functions, then
                     *  \f[
                     *     \mathbf{M} = \left[\begin{array}{ c c c }
                     *     \displaystyle\frac{\partial x_f}{\partial x_i} &
                     *     \displaystyle\frac{\partial x_f}{\partial y_i} &
                     *     x_f \\
                     *     \displaystyle\frac{\partial y_f}{\partial x_i} &
                     *     \displaystyle\frac{\partial y_f}{\partial y_i} &
                     *     y_f \\
                     *     \displaystyle 0 & \displaystyle 0 & \displaystyle 1
                     *     \end{array}\right]
                     *  \f]
                     *  evaluated at \f$(x_i,y_i)\f$.
                     *
                     *  The 2x2 upper left corner of \f$ \mathbf{M} \f$ is the linear part of the transform is simply the
                     *  Jacobian of the mapping between \f$(x_i,y_i)\f$ and \f$(x_f,y_f)\f$.
                     */
                    class AffineTransform {
                    public:
                        typedef boost::shared_ptr Ptr;
                        typedef boost::shared_ptr ConstPtr;
                    
                        enum Parameters {XX=0,YX=1,XY=2,YY=3,X=4,Y=5};
                    
                        typedef Eigen::Matrix3d Matrix;
                        typedef Eigen::Matrix ParameterVector;
                        typedef Eigen::Matrix TransformDerivativeMatrix;
                    
                    
                        /** Construct an empty (identity) AffineTransform. */
                        AffineTransform() : _linear(), _translation() {}
                    
                        /** Construct an AffineTransform from a 3x3 matrix. */
                        explicit AffineTransform(Eigen::Matrix3d const & matrix) 
                          : _linear(matrix.block<2,2>(0,0)), 
                            _translation(matrix.block<2,1>(0,2)) 
                        {}
                    
                        /** Construct an AffineTransform with no translation from a 2x2 matrix. */
                        explicit AffineTransform(Eigen::Matrix2d const & linear) 
                          : _linear(linear), _translation() {}
                    
                        /** Construct a translation-only AffineTransform from a vector. */
                        explicit AffineTransform(Eigen::Vector2d const & translation) 
                          : _linear(), _translation(translation) {}
                    
                        /** Construct an AffineTransform from a 2x2 matrix and vector. */
                        explicit AffineTransform(
                            Eigen::Matrix2d const & linear, Eigen::Vector2d const & translation
                        ) : _linear(linear), _translation(translation) {}
                        
                        /** Construct an AffineTransform from a LinearTransform. */
                        explicit AffineTransform(LinearTransform const & linear) 
                          : _linear(linear), _translation() {}
                    
                        /** Construct a translation-only AffineTransform from an Extent2D. */
                        explicit AffineTransform(Extent2D const & translation) 
                          : _linear(), _translation(translation) {}
                    
                        /** Construct an AffineTransform from a LinearTransform and Extent2D. */
                        explicit AffineTransform(
                            LinearTransform const & linear, Extent2D const & translation
                        ) : _linear(linear), _translation(translation) {}
                    
                    
                        AffineTransform const invert() const;
                    
                        /** Whether the transform is a no-op. */
                        bool isIdentity() const { return getMatrix().isIdentity(); }
                    
                    
                        /** 
                         * Transform a Point object. 
                         *
                         * The result is affected by the translation parameters of the transform
                         */
                        Point2D operator()(Point2D const &p) const {         
                            return Point2D(_linear(p) + _translation);
                        }
                    
                        /**
                         * Transform an Extent object. 
                         *
                         * The result is unaffected by the translation parameters of the transform
                         */
                        Extent2D operator()(Extent2D const &p) const {         
                            return Extent2D(_linear(p));
                        }
                    
                        Extent2D const & getTranslation() const {return _translation;}
                        Extent2D & getTranslation() {return _translation;}
                    
                        LinearTransform const & getLinear() const {return _linear;}
                        LinearTransform & getLinear() {return _linear;}
                    
                        Matrix const getMatrix() const;
                        
                        ParameterVector const getParameterVector() const;
                        void setParameterVector(ParameterVector const & vector);
                    
                        double & operator[](int i) { 
                            return (i < 4) ? _linear[i] : _translation[i - 4]; 
                        }
                        double operator[](int i) const { 
                            return (i < 4) ? _linear[i] : _translation[i - 4]; 
                        }
                    
    
    167 a8afb4cc + /**
    168 a8afb4cc + * Construct a new AffineTransform from two others: (B * A)(p) = B(A(p))
    169 a8afb4cc + */
    AffineTransform operator*(AffineTransform const & other) const { return AffineTransform( getLinear()*other.getLinear(), getLinear()(other.getTranslation()) + getTranslation() ); } AffineTransform & operator =(AffineTransform const & other) { _linear = other._linear; _translation = other._translation; return *this; } /** * \brief Construct a new AffineTransform that represents a uniform scaling. * * \return An AffineTransform with matrix * \f$ * \left[\begin{array}{ c c c } * s & 0 & 0 \\ * 0 & s & 0 \\ * 0 & 0 & 1 \\ * \end{array}\right] * \f$ */ static AffineTransform makeScaling(double s) { return AffineTransform(LinearTransform::makeScaling(s)); } /** * \brief Construct a new AffineTransform that represents a non-uniform * scaling. * * \return An AffineTransform with matrix * \f$ * \left[\begin{array}{ c c c } * s & 0 & 0 \\ * 0 & t & 0 \\ * 0 & 0 & 1 \\ * \end{array}\right] * \f$ */ static AffineTransform makeScaling(double s, double t) { return AffineTransform(LinearTransform::makeScaling(s, t)); } /** * \brief Construct a new AffineTransform that represents a CCW rotation in radians. * * \return An AffineTransform with matrix * \f$ * \left[\begin{array}{ c c c } * \cos t & -\sin t & 0 \\ * \sin t & \cos t & 0 \\ * 0 & 0 & 1 \\ * \end{array}\right] * \f$ */ static AffineTransform makeRotation(Angle t) { return AffineTransform(LinearTransform::makeRotation(t)); } /** * \brief Construct a new AffineTransform that represents a pure translation. * * \return An AffineTransform with matrix * \f$ * \left[\begin{array}{ c c c } * 0 & 0 & translation.getX() \\ * 0 & 0 & translation.getY() \\ * 0 & 0 & 1 \\ * \end{array}\right] * \f$ */ static AffineTransform makeTranslation(Extent2D translation) { return AffineTransform(translation); } TransformDerivativeMatrix dTransform(Point2D const & input) const; TransformDerivativeMatrix dTransform(Extent2D const & input) const; private: LinearTransform _linear; Extent2D _translation; }; std::ostream & operator<<(std::ostream & os, lsst::afw::geom::AffineTransform const & transform); // // Returns the unique AffineTransform A such that A(p_i)=q_i for i=1,2,3 // AffineTransform makeAffineTransformFromTriple(Point2D const &p1, Point2D const &p2, Point2D const &p3, Point2D const &q1, Point2D const &q2, Point2D const &q3); }}} #endif // !LSST_AFW_MATH_AFFINE_TRANSFORM_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    a8afb4cc

    commit a8afb4cc71b25f8e140c7864ae94dd4d381e908e
    Author: Russell Owen 
    Date:   Fri Feb 28 15:29:33 2014 -0800
    
        Add MultiXYTransform, but something has gone wrong.
    

    Return to list

    examples/image.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/afw/image/Image.h"
                    
                    namespace afwImage = lsst::afw::image;
                    namespace afwGeom = lsst::afw::geom;
                    
                    template 
                    void print(afwImage::Image& src, const std::string& title = "") {
                        typedef typename afwImage::Image::x_iterator XIter;
                        if (title.size() > 0) {
                            printf("%s:\n", title.c_str());
                        }
                    
                        printf("%3s ", "");
                        for (int x = 0; x != src.getWidth(); ++x) {
                            printf("%4d ", x);
                        }
                        printf("\n");
                    
                        for (int y = src.getHeight() - 1; y >= 0; --y) {
                            printf("%3d ", y);
                            for (XIter src_it = src.row_begin(y), src_end = src.row_end(y); src_it != src_end; ++src_it) {
                                printf("%4g ", static_cast((*src_it)[0]));
                            }
                            printf("\n");
                        }
                    }
                    
                    template 
                    void printT(afwImage::Image& src, const std::string& _title = "") {
                        std::string title =_title;
                        if (title.size() > 0) {
                            title += " ";
                        }
                        title += "transposed";
                        printf("%s:\n", title.c_str());
                    
                        printf("%3s ", "");
                        for (int r = 0; r != src.getHeight(); ++r) {
                            printf("%4d ", r);
                        }
                        printf("\n");
                    
                        for (int c = 0; c != src.getWidth(); ++c) {
                            printf("%3d ", c);
                    
                    #if 1   // print the column from the top (there's no reverse iterator)
                            typename afwImage::Image::y_iterator src_it = src.col_begin(c);
                            for (int r = src.getHeight() - 1; r >= 0; --r) {
                                printf("%4g ", static_cast(src_it[r][0]));
                            }
                    #else  // print the column from the bottom (i.e. upside down)
                            for (typename afwImage::Image::y_iterator src_it = src.col_begin(c); src_it != src.col_end(c);
                                ++src_it) {
                                printf("%4g ", static_cast((*src_it)[0]));
                            }
                    #endif
                            
                            printf("\n");
                        }
                    }
                    
                    /************************************************************************************************************/
                    
                    template 
                    void y_gradient(const afwImage::Image& src, const afwImage::Image& dst) {
                        assert(src.getDimensions() == dst.getDimensions());
                    
                        typedef typename afwImage::Image::const_xy_locator xy_loc;
                        xy_loc src_loc = src.xy_at(0, 1);
                    
                    #define USE_CACHE_LOCATION 1
                    #if USE_CACHE_LOCATION
                        typename xy_loc::cached_location_t above = src_loc.cache_location(0,  1);
                        typename xy_loc::cached_location_t below = src_loc.cache_location(0, -1);
                    #endif
                    
                        for (int r = 1; r < src.getHeight() - 1; ++r) {
                            for (typename afwImage::Image::x_iterator dst_it = dst.row_begin(r);
                                dst_it != dst.row_end(r); ++dst_it, ++src_loc.x()) {            
                    #if USE_CACHE_LOCATION                  // this version is faster
                                *dst_it = (src_loc[above] - src_loc[below])/2;
                    #else  // but this is possible too, and more general (but slower)
                                *dst_it = (src_loc(0, 1) - src_loc(0, -1))/2;
                    #endif
                            }
                            
                            src_loc += afwImage::detail::difference_type(-src.getWidth(), 1);
                        }
                    }
                    
                    /************************************************************************************************************/
                    
                    int main() {
                        afwImage::Image img(afwGeom::Extent2I(10, 6));
                        // This is equivalent to img = 100:
                        for (afwImage::Image::iterator ptr = img.begin(); ptr != img.end(); ++ptr) {
                            (*ptr)[0] = 100;
                        }
                        // so is this, but fills backwards
                        for (afwImage::Image::reverse_iterator ptr = img.rbegin(); ptr != img.rend(); ++ptr) {
                            (*ptr)[0] = 100;
                        }
                        // so is this, but tests a different way of choosing begin()
                        for (afwImage::Image::iterator ptr = img.at(0, 0); ptr != img.end(); ++ptr) {
                            (*ptr)[0] = 100;
                        }
                    
                        afwImage::Image jmg = img;
                    
                        printf("%dx%d\n", img.getWidth(), img.getHeight());
                    
                        *img.y_at(7, 2) = 999;
                        *img.x_at(0, 0) = 0;
                        img(img.getWidth() - 1, img.getHeight() - 1) = -100;
                    
                        print(img, "img");
                        printT(img, "img");
                        print(jmg, "jmg");
                    
                        afwImage::Image kmg = jmg;
                        kmg(0,0) = 111;
                        kmg += 222;
                        kmg -= 222;
                        kmg += jmg;
                        kmg *= 10;
                        {
                            afwImage::Image tmp(kmg.getDimensions());
                            tmp = 10;
                            print(tmp, "tmp");
                            kmg /= tmp;
                        }
                        print(kmg, "kmg");
                    
                        afwImage::Image lmg(img);
                        print(lmg, "lmg");
                    
                        afwImage::Image mmg(img, true);
                        mmg = -1;                           // shouldn't modify img
                        
                        printf("sub images\n");
                    
                        // img will be modified
                        afwImage::Image simg1(
                            img, afwGeom::Box2I(
                                afwGeom::Point2I(1, 1), 
                                afwGeom::Extent2I(7, 3)
                            ),
                            afwImage::LOCAL
                        );
                        afwImage::Image simg(
                            simg1, afwGeom::Box2I(
                                afwGeom::Point2I(0, 0), 
                                afwGeom::Extent2I(5, 2)
                            ),
                            afwImage::LOCAL
                        );
                    
                    
                        {
                            afwImage::Image nimg(afwGeom::Extent2I(5, 2));
                            nimg = 1;
                            simg <<= nimg;
                        }
                    
                        print(simg, "simg");
                        print(img, "img");
                    
                        printf("\n");
                        for (int r = 0; r != img.getHeight(); ++r) {
                            std::fill(img.row_begin(r), img.row_end(r), 100*(1 + r));
                        }
                        print(img, "ramp img");
                        
                        afwImage::Image grad_y(img.getDimensions());
                        grad_y = 0;
                        y_gradient(img, grad_y);
                    
                        print(grad_y, "grad_y");
                        
                        afwImage::Image u16(img.getDimensions());
                        u16 = 100;
                        afwImage::Image fl32(u16, true); // must be true as all type conversions are deep
                        print(fl32, "Float from U16");
                    
                        try {
                            afwImage::Image fl32(u16, false);  // will throw
    
    213 3771b5eb - } catch(lsst::pex::exceptions::InvalidParameterException &e) {
    ? ^^^^^^ ^
    213 21597d88 + } catch(lsst::pex::exceptions::InvalidParameterError &e) {
    ? ^^ ^ printf("Correctly threw exception: %s\n", e.what()); } return 0; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/testExposureTable.py

    Diff:

    1 ad63680a - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for lsst.afw.table.ExposureTable Run with: ./testExposureTable.py or python >>> import testExposureTable; testExposureTable.run() """
    35 ad63680a - import sys
    36 ad63680a - import os
    import unittest import numpy import lsst.utils.tests import lsst.pex.exceptions import lsst.daf.base import lsst.afw.table import lsst.afw.geom import lsst.afw.coord import lsst.afw.image import lsst.afw.detection from testTableArchivesLib import DummyPsf
    48 ad63680a +
    49 4bae7ca1 + numpy.random.seed(1)
    try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ExposureTableTestCase(unittest.TestCase): @staticmethod def createWcs(): metadata = lsst.daf.base.PropertySet() metadata.set("SIMPLE", "T") metadata.set("BITPIX", -32) metadata.set("NAXIS", 2) metadata.set("NAXIS1", 1024) metadata.set("NAXIS2", 1153) metadata.set("RADECSYS", 'FK5') metadata.set("EQUINOX", 2000.) metadata.setDouble("CRVAL1", 215.604025685476) metadata.setDouble("CRVAL2", 53.1595451514076) metadata.setDouble("CRPIX1", 1109.99981456774) metadata.setDouble("CRPIX2", 560.018167811613) metadata.set("CTYPE1", 'RA---SIN') metadata.set("CTYPE2", 'DEC--SIN') metadata.setDouble("CD1_1", 5.10808596133527E-05) metadata.setDouble("CD1_2", 1.85579539217196E-07) metadata.setDouble("CD2_2", -5.10281493481982E-05) metadata.setDouble("CD2_1", -8.27440751733828E-07) return lsst.afw.image.makeWcs(metadata) def comparePsfs(self, psf1, psf2): psf1 = DummyPsf.swigConvert(psf1) psf2 = DummyPsf.swigConvert(psf2) self.assert_(psf1 is not None) self.assert_(psf2 is not None) self.assertEqual(psf1.getValue(), psf2.getValue()) def setUp(self): schema = lsst.afw.table.ExposureTable.makeMinimalSchema() self.ka = schema.addField("a", type=float, doc="doc for a") self.kb = schema.addField("b", type=int, doc="doc for b") self.cat = lsst.afw.table.ExposureCatalog(schema) self.wcs = self.createWcs() self.psf = DummyPsf(2.0) self.bbox0 = lsst.afw.geom.Box2I( lsst.afw.geom.Box2D( self.wcs.getPixelOrigin() - lsst.afw.geom.Extent2D( 5.0, 4.0), self.wcs.getPixelOrigin() + lsst.afw.geom.Extent2D(20.0, 30.0) ) ) self.bbox1 = lsst.afw.geom.Box2I( lsst.afw.geom.Box2D( self.wcs.getPixelOrigin() - lsst.afw.geom.Extent2D(15.0, 40.0), self.wcs.getPixelOrigin() + lsst.afw.geom.Extent2D( 3.0, 6.0) ) ) self.calib = lsst.afw.image.Calib() self.calib.setFluxMag0(56.0, 2.2) self.calib.setExptime(50.0) self.calib.setMidTime(lsst.daf.base.DateTime.now()) record0 = self.cat.addNew() record0.setId(1) record0.set(self.ka, numpy.pi) record0.set(self.kb, 4) record0.setBBox(self.bbox0) record0.setPsf(self.psf) record0.setWcs(self.wcs) record0.setCalib(self.calib) record1 = self.cat.addNew() record1.setId(2) record1.set(self.ka, 2.5) record1.set(self.kb, 2) record1.setWcs(self.wcs) record1.setBBox(self.bbox1) def tearDown(self): del self.cat del self.psf del self.wcs del self.calib def testAccessors(self): record0 = self.cat[0] record1 = self.cat[1] self.assertEqual(record0.getId(), 1) self.assertEqual(record1.getId(), 2) self.assertEqual(record0.getWcs(), self.wcs) self.assertEqual(record1.getWcs(), self.wcs) self.assertEqual(record0.getBBox(), self.bbox0) self.assertEqual(record1.getBBox(), self.bbox1) self.comparePsfs(record0.getPsf(), self.psf) self.assertEqual(record1.getPsf(), None) self.assertEqual(record0.getCalib(), self.calib) self.assertTrue(record1.getCalib() is None) def testPersistence(self):
    147 ad63680a - filename1 = "ExposureTable1.fits"
    148 c605dfcd + with lsst.utils.tests.getTempFilePath(".fits") as tmpFile:
    148 ad63680a - self.cat.writeFits(filename1)
    ? ^ -----
    149 c605dfcd + self.cat.writeFits(tmpFile)
    ? ++++ ^^^^
    149 ad63680a - cat1 = lsst.afw.table.ExposureCatalog.readFits(filename1)
    ? ^ -----
    150 c605dfcd + cat1 = lsst.afw.table.ExposureCatalog.readFits(tmpFile)
    ? ++++ ^^^^
    150 ad63680a - os.remove(filename1)
    151 ad63680a - self.assertEqual(self.cat[0].get(self.ka), cat1[0].get(self.ka))
    151 c605dfcd + self.assertEqual(self.cat[0].get(self.ka), cat1[0].get(self.ka))
    ? ++++
    152 ad63680a - self.assertEqual(self.cat[0].get(self.kb), cat1[0].get(self.kb))
    152 c605dfcd + self.assertEqual(self.cat[0].get(self.kb), cat1[0].get(self.kb))
    ? ++++
    153 ad63680a - self.comparePsfs(self.cat[0].getPsf(), cat1[0].getPsf())
    153 c605dfcd + self.comparePsfs(self.cat[0].getPsf(), cat1[0].getPsf())
    ? ++++
    154 ad63680a - self.assertEqual(self.cat[0].getWcs(), cat1[0].getWcs())
    154 c605dfcd + self.assertEqual(self.cat[0].getWcs(), cat1[0].getWcs())
    ? ++++
    155 ad63680a - self.assertEqual(self.cat[1].get(self.ka), cat1[1].get(self.ka))
    155 c605dfcd + self.assertEqual(self.cat[1].get(self.ka), cat1[1].get(self.ka))
    ? ++++
    156 ad63680a - self.assertEqual(self.cat[1].get(self.kb), cat1[1].get(self.kb))
    156 c605dfcd + self.assertEqual(self.cat[1].get(self.kb), cat1[1].get(self.kb))
    ? ++++
    157 ad63680a - self.assertEqual(self.cat[1].getWcs(), cat1[1].getWcs())
    157 c605dfcd + self.assertEqual(self.cat[1].getWcs(), cat1[1].getWcs())
    ? ++++
    158 ad63680a - self.assertTrue(self.cat[1].getPsf() is None)
    158 c605dfcd + self.assertTrue(self.cat[1].getPsf() is None)
    ? ++++
    159 ad63680a - self.assertTrue(self.cat[1].getCalib() is None)
    159 c605dfcd + self.assertTrue(self.cat[1].getCalib() is None)
    ? ++++
    160 ad63680a - self.assertEqual(self.cat[0].getWcs().getId(), self.cat[1].getWcs().getId()) # compare citizen IDs
    160 c605dfcd + self.assertEqual(self.cat[0].getWcs().getId(), self.cat[1].getWcs().getId()) # compare citizen IDs
    ? ++++
    161 ad63680a - self.assertEqual(self.cat[0].getCalib(), cat1[0].getCalib())
    161 c605dfcd + self.assertEqual(self.cat[0].getCalib(), cat1[0].getCalib())
    ? ++++ def testGeometry(self): bigBox = lsst.afw.geom.Box2D(lsst.afw.geom.Box2I(self.bbox0)) bigBox.include(lsst.afw.geom.Box2D(self.bbox1)) points = (numpy.random.rand(100, 2) * numpy.array([bigBox.getWidth(), bigBox.getHeight()]) + numpy.array([bigBox.getMinX(), bigBox.getMinY()])) # make a very slightly perturbed wcs so the celestial transform isn't a no-op crval2 = self.wcs.getSkyOrigin() crval2.reset(crval2.getLongitude() + 5 * lsst.afw.geom.arcseconds, crval2.getLatitude() - 5 * lsst.afw.geom.arcseconds) wcs2 = lsst.afw.image.Wcs( crval2.getPosition(), self.wcs.getPixelOrigin() + lsst.afw.geom.Extent2D(30.0, -50.0), self.wcs.getCDMatrix() * 1.1 ) for x1, y1 in points: p1 = lsst.afw.geom.Point2D(x1, y1) c = self.wcs.pixelToSky(x1, y1) p2 = wcs2.skyToPixel(c) subset1 = self.cat.subsetContaining(c) subset2 = self.cat.subsetContaining(p2, wcs2) for record in self.cat: inside = lsst.afw.geom.Box2D(record.getBBox()).contains(p1) self.assertEqual(inside, record.contains(c)) self.assertEqual(inside, record.contains(p2, wcs2)) self.assertEqual(inside, record.contains(p1, self.wcs)) self.assertEqual(inside, record in subset1) self.assertEqual(inside, record in subset2) crazyPoint = lsst.afw.coord.IcrsCoord(crval2.getLongitude() + numpy.pi * lsst.afw.geom.radians, crval2.getLatitude()) subset3 = self.cat.subsetContaining(crazyPoint) self.assertEqual(len(subset3), 0) def testCoaddInputs(self): coaddInputs = lsst.afw.image.CoaddInputs( lsst.afw.table.ExposureTable.makeMinimalSchema(), lsst.afw.table.ExposureTable.makeMinimalSchema() ) coaddInputs.visits.addNew().setId(2) coaddInputs.ccds.addNew().setId(3) coaddInputs.ccds.addNew().setId(4) exposureIn = lsst.afw.image.ExposureF(10, 10) exposureIn.getInfo().setCoaddInputs(coaddInputs)
    206 63c82a97 - filename = "Exposure2.fits"
    206 c605dfcd + with lsst.utils.tests.getTempFilePath(".fits") as filename:
    207 63c82a97 - exposureIn.writeFits(filename)
    207 c605dfcd + exposureIn.writeFits(filename)
    ? ++++
    208 63c82a97 - exposureOut = lsst.afw.image.ExposureF(filename)
    208 c605dfcd + exposureOut = lsst.afw.image.ExposureF(filename)
    ? ++++
    209 63c82a97 - os.remove(filename)
    210 63c82a97 - coaddInputsOut = exposureOut.getInfo().getCoaddInputs()
    209 c605dfcd + coaddInputsOut = exposureOut.getInfo().getCoaddInputs()
    ? ++++
    211 63c82a97 - self.assertEqual(len(coaddInputsOut.visits), 1)
    210 c605dfcd + self.assertEqual(len(coaddInputsOut.visits), 1)
    ? ++++
    212 63c82a97 - self.assertEqual(len(coaddInputsOut.ccds), 2)
    211 c605dfcd + self.assertEqual(len(coaddInputsOut.ccds), 2)
    ? ++++
    213 63c82a97 - self.assertEqual(coaddInputsOut.visits[0].getId(), 2)
    212 c605dfcd + self.assertEqual(coaddInputsOut.visits[0].getId(), 2)
    ? ++++
    214 63c82a97 - self.assertEqual(coaddInputsOut.ccds[0].getId(), 3)
    213 c605dfcd + self.assertEqual(coaddInputsOut.ccds[0].getId(), 3)
    ? ++++
    215 63c82a97 - self.assertEqual(coaddInputsOut.ccds[1].getId(), 4)
    214 c605dfcd + self.assertEqual(coaddInputsOut.ccds[1].getId(), 4)
    ? ++++ #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" lsst.utils.tests.init() suites = [] suites += unittest.makeSuite(ExposureTableTestCase) suites += unittest.makeSuite(lsst.utils.tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" lsst.utils.tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ad63680a

    commit ad63680a28ce16e98b156f40c8c0e3474ac65410
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:50:27 2013 -0500
    
        Add ExposureTable/Record/Catalog.
    

    63c82a97

    commit 63c82a97434dd501874cb8805049c822bf0573fe
    Author: Jim Bosch 
    Date:   Thu Jan 31 21:02:42 2013 -0500
    
        Swig and unit tests for CoaddInputs.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    4bae7ca1

    commit 4bae7ca131d04a3f68e47748b0423617ffd33000
    Author: Paul Price 
    Date:   Wed Aug 6 16:40:49 2014 -0400
    
        tests: seed random number generator to make tests deterministic
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    ad63680a

    commit ad63680a28ce16e98b156f40c8c0e3474ac65410
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:50:27 2013 -0500
    
        Add ExposureTable/Record/Catalog.
    

    Return to list

    lib/libafw.dylib-gdb.py

    Diff:

                    import os, os.path, sys
    
    2 ed95653a + import lsst.utils
    import gdb # # Adjust the load path to include lsst.gdb, bypassing the regular lsstimport mechanism as # the version of python running within gdb may not be the same as we are using for lsst processing #
    8 ed95653a + try:
    9 ed95653a + afwDir = lsst.utils.getPackageDir('afw')
    10 ed95653a + except Exception:
    11 ed95653a + pass
    12 ed95653a + else:
    7 9d75da31 - printerDir = os.path.join(os.environ["AFW_DIR"], "python", "lsst", "gdb")
    ? ^^^^^^ -------------
    13 ed95653a + printerDir = os.path.join(afwDir, "python", "lsst", "gdb")
    ? ++++ ^^^^
    8 9d75da31 - if printerDir not in sys.path:
    14 ed95653a + if printerDir not in sys.path:
    ? ++++
    9 9d75da31 - sys.path.append(printerDir)
    15 ed95653a + sys.path.append(printerDir)
    ? ++++ import afw.printers afw.printers.register(gdb.current_objfile())

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9d75da31

    commit 9d75da31a13fb65f7130388d428819a7df7bef0d
    Author: rhl 
    Date:   Sun May 22 21:25:50 2011 +0000
    
        Redid the gdb+python plumbing in a way that should permit the system/gdb and lsst pythons to be different
    

    Commits in /Users/nate/repos_lsst/afw/

    ed95653a

    commit ed95653aae0db5c64fec82321af822db861c9e9c
    Author: Joshua Hoblitt 
    Date:   Thu May 21 14:38:34 2015 -0700
    
        replace eups.productDir() calls with lsst.utils.getPackageDir()
    

    Return to list

    examples/timeConvolveGpu.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                    * @file
                    *
                    * @brief Times the speedup of GPU accelerated convolution
                    *
                    * @author Kresimir Cosic
                    *
                    * @ingroup afw
                    */
                    
                    
                    #include 
                    #include 
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
    
    45 a9aec7fc + #include "lsst/utils/Utils.h"
    #include "lsst/utils/ieee.h" #include "lsst/daf/base.h" #include "lsst/pex/exceptions.h" #include "lsst/pex/logging/Trace.h" #include "lsst/afw/image.h" #include "lsst/afw/geom.h" #include "lsst/afw/math.h" #include "lsst/afw/gpu/IsGpuBuild.h" //Just for PrintCudaDeviceInfo #include "lsst/afw/gpu/detail/CudaQueryDevice.h" using namespace std; using lsst::pex::logging::Trace; namespace pexEx = lsst::pex::exceptions; namespace afwImage = lsst::afw::image; namespace afwMath = lsst::afw::math; namespace afwGeom = lsst::afw::geom; typedef int TestResult; typedef afwMath::Kernel::Pixel KerPixel; typedef afwImage::VariancePixel VarPixel; typedef afwImage::MaskPixel MskPixel; // returns time difference in seconds double DiffTime(clock_t start, clock_t end) { double tm; tm = (double)difftime(end, start); tm = abs(tm); tm /= CLOCKS_PER_SEC; return tm; } //Calculates relative RMSD (coefficient of variation of the root-mean-square deviation) template double CvRmsd(afwImage::Image& imgA, afwImage::Image& imgB) { const int dimX = imgA.getWidth(); const int dimY = imgA.getHeight(); if (dimX != imgB.getWidth() || dimY != imgB.getHeight()) return NAN; double sqSum = 0; double avgSum = 0; int cnt = 0; for (int x = 0; x < dimX; x++) { for (int y = 0; y < dimY; y++) { const double valA = imgA(x, y); const double valB = imgB(x, y); if (lsst::utils::isnan(valA) && lsst::utils::isnan(valB)) continue; if (lsst::utils::isinf(valA) && lsst::utils::isinf(valB)) continue; cnt++; avgSum += (valA + valB) / 2; const double diff = valA - valB; sqSum += diff * diff; } } double rmsd = sqrt(sqSum / cnt); double avg = avgSum / cnt; return rmsd / avg; } //Returns number of different values template double DiffCnt(afwImage::Mask& imgA, afwImage::Mask& imgB) { typedef long long unsigned int Bitint; const int dimX = imgA.getWidth(); const int dimY = imgA.getHeight(); if (dimX != imgB.getWidth() || dimY != imgB.getHeight()) return NAN; int cnt = 0; for (int x = 0; x < dimX; x++) { for (int y = 0; y < dimY; y++) { const T valA = imgA(x, y); const T valB = imgB(x, y); if (valA != valB) cnt++; } } return cnt; } void PrintSeparator() { for (int i = 0; i < 79; i++) cout << "="; cout << endl; } typedef afwMath::LinearCombinationKernel LinearCombinationKernel; afwMath::LinearCombinationKernel::Ptr ConstructLinearCombinationKernel( const unsigned kernelW, const unsigned kernelH, const int basisKernelN, const int order, int sizeX, int sizeY, const bool isPolynomial = false ) { double const MinSigma = 1.5; double const MaxSigma = 4.5; // construct basis kernels const int kernelN = basisKernelN; afwMath::KernelList kernelList; for (int ii = 0; ii < kernelN; ++ii) { double majorSigma = (ii == 1) ? MaxSigma : MinSigma; double minorSigma = (ii == 2) ? MinSigma : MaxSigma; double angle = 0.0; if (ii > 2) angle = ii / 10; afwMath::GaussianFunction2 gaussFunc(majorSigma, minorSigma, angle); afwMath::Kernel::Ptr basisKernelPtr( new afwMath::AnalyticKernel(kernelW, kernelH, gaussFunc) ); kernelList.push_back(basisKernelPtr); } // construct spatially varying linear combination kernel afwMath::LinearCombinationKernel::Ptr kernelPtr; if (isPolynomial) { afwMath::PolynomialFunction2 polyFunc(order); kernelPtr = afwMath::LinearCombinationKernel::Ptr( new LinearCombinationKernel(kernelList, polyFunc) ); } else { afwMath::Chebyshev1Function2 chebyFunc(order, lsst::afw::geom::Box2D( lsst::afw::geom::Point2D(-sizeX / 3.0, -sizeY / 4.0), lsst::afw::geom::Point2D( sizeX + 100.0, sizeY + 200.0) ) ); kernelPtr = afwMath::LinearCombinationKernel::Ptr( new LinearCombinationKernel(kernelList, chebyFunc) ); } LinearCombinationKernel& kernel = *kernelPtr; // Get copy of spatial parameters (all zeros), set and feed back to the kernel
    195 0930ac63 - vector > polyParams = kernel.getSpatialParameters();
    ? -----
    196 a9aec7fc + vector > polyParams = kernel.getSpatialParameters();
    // Set spatial parameters for basis kernel 0 polyParams[0][0] = 1.0; polyParams[0][1] = -0.5 / 100; polyParams[0][2] = -0.5 / 100; if (order > 1 ) { polyParams[0][3] = -0.1 / sizeX; polyParams[0][4] = -0.2 / sizeY; polyParams[0][5] = 0.4 / sizeX; } for (int i = 1; i < kernelN; i++) { // Set spatial function parameters of other basis kernels polyParams[i][0] = polyParams[0][0] - i * 0.2; polyParams[i][1] = polyParams[0][1] + i * 0.1; polyParams[i][2] = polyParams[0][2] + i * 0.1; for (int jj = 3; jj < (order + 1)*(order + 2) / 2; jj++) { polyParams[i][jj] = i * jj * 0.1 / 600; } } kernel.setSpatialParameters(polyParams); return kernelPtr; }
    221 0930ac63 - string GetInputFileName(int argc, char **argv)
    ? ^^^ ^ ^^
    222 a9aec7fc + string GetInputImagePath(int argc, char **argv)
    ? ^^^^ ^ ^^ {
    223 0930ac63 - string imgBaseFileName;
    224 a9aec7fc + string inImagePath;
    if (argc < 2) {
    225 0930ac63 - string afwdata = getenv("AFWDATA_DIR");
    226 0930ac63 - if (afwdata.empty()) {
    226 a9aec7fc + try {
    227 7cbb2bb9 + string dataDir = lsst::utils::getPackageDir("afwdata");
    228 a9aec7fc + inImagePath = dataDir + "/data/med.fits";
    229 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    227 0930ac63 - std::cerr << "Usage: convolveGPU fitsFile" << endl;
    ? -----
    230 a9aec7fc + cerr << "Usage: convolveGPU [fitsFile]" << endl;
    ? + +
    231 a9aec7fc + cerr << "fitsFile is the path to a masked image" << endl;
    232 a9aec7fc + cerr << "\nError: setup afwdata or specify fitsFile.\n" << endl;
    228 0930ac63 - std::cerr << "fitsFile excludes the \"_img.fits\" suffix" << endl;
    229 0930ac63 - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << endl;
    230 0930ac63 - std::cerr << "Is afwdata set up?\n" << endl;
    exit(EXIT_FAILURE); }
    233 0930ac63 - else {
    234 fbfcd257 - imgBaseFileName = afwdata + "/data/med";
    235 fbfcd257 - //imgBaseFileName = afwdata + "/data/medsub";
    236 fbfcd257 - //imgBaseFileName = afwdata + "/data/871034p_1_MI";
    237 0930ac63 - cout << "Using image: " << imgBaseFileName << endl;
    238 0930ac63 - }
    } else {
    241 0930ac63 - imgBaseFileName = string(argv[1]);
    ? ^ ^^^^^^^^^^
    237 a9aec7fc + inImagePath = string(argv[1]);
    ? ++ + ^^ ^^ }
    243 0930ac63 - return imgBaseFileName;
    239 a9aec7fc + return inImagePath;
    } afwMath::FixedKernel::Ptr ConstructKernel( const double kernelCols, const double kernelRows, const double majorSigma = 2.5, const double minorSigma = 2.0, const double angle = 0.5, const double denormalizationFactor = 47.3 ) { afwMath::GaussianFunction2 gaussFunc(majorSigma, minorSigma, angle); afwMath::AnalyticKernel analyticKernel(kernelCols, kernelRows, gaussFunc); lsst::afw::image::Image analyticImage(analyticKernel.getDimensions()); (void)analyticKernel.computeImage(analyticImage, true); analyticImage *= denormalizationFactor; afwMath::FixedKernel::Ptr fixedKernel(new afwMath::FixedKernel(analyticImage)); return fixedKernel; } string Sel(bool b, const char* onTrue, const char* onFalse) { return b ? string(onTrue) : string(onFalse); } string DecimalPlaces(int places, double val) { stringstream ss; ss << fixed << showpoint << setprecision(places) << val; return ss.str(); } template void TimeOneKernelMI( const afwImage::MaskedImage inImg, afwMath::Kernel::Ptr kernel, bool doNormalizeKernel = true ) { const int kernelSizeX = kernel->getWidth(); const int kernelSizeY = kernel->getHeight(); const afwImage::MaskedImage inMI = inImg; afwMath::ConvolutionControl cctrlXGpu (doNormalizeKernel, false, 0, lsst::afw::gpu::AUTO); afwMath::ConvolutionControl cctrlXCpu (doNormalizeKernel, false, 0, lsst::afw::gpu::USE_CPU); afwImage::MaskedImage resMI (inMI.getDimensions()); afwImage::MaskedImage resMIGpu(inMI.getDimensions()); const int GPUrep = 4; const int sizeRepMax = 2; int repCpu = sizeRepMax * 18 / kernelSizeX; int repGpu = GPUrep * sizeRepMax * 18 / kernelSizeX; // convolve masked image time_t maskedImgCpuStart = clock(); for (int i = 0; i < repCpu; i++) afwMath::convolve(resMI , inMI, *kernel, cctrlXCpu); double maskedImgCpuTime = DiffTime(maskedImgCpuStart, clock()) / repCpu; time_t maskedImgGpuStart = clock(); for (int i = 0; i < repGpu; i++) afwMath::convolve(resMIGpu, inMI, *kernel, cctrlXGpu); double maskedImgGpuTime = DiffTime(maskedImgGpuStart, clock()) / repGpu; double diffMIImg = CvRmsd(*resMI.getImage() , *resMIGpu.getImage()); double diffMIVar = CvRmsd(*resMI.getVariance(), *resMIGpu.getVariance()); double diffMIMsk = DiffCnt(*resMI.getMask() , *resMIGpu.getMask()); cout << setw(2) << setfill('0') << kernelSizeX << "x" << setw(2) << kernelSizeY << setfill(' ') << setw(8) << DecimalPlaces(3, maskedImgCpuTime) << " s " << setw(8) << DecimalPlaces(4, maskedImgGpuTime) << " s " << setw(6) << DecimalPlaces(1, maskedImgCpuTime / maskedImgGpuTime) << "x " << setw(16) << diffMIImg << setw(16) << diffMIVar << setw(9) << diffMIMsk << endl; } template void TimeOneKernelPI( const afwImage::MaskedImage inImg, afwMath::Kernel::Ptr kernel, const int sizeRepMax, bool doNormalizeKernel = false ) { const int kernelSizeX = kernel->getWidth(); const int kernelSizeY = kernel->getHeight(); const afwImage::MaskedImage inMI = inImg; const afwImage::Image inPI = *inMI.getImage(); afwMath::ConvolutionControl cctrlXGpu (doNormalizeKernel, false, 0, lsst::afw::gpu::AUTO); afwMath::ConvolutionControl cctrlXCpu (doNormalizeKernel, false, 0, lsst::afw::gpu::USE_CPU); afwImage::Image resPI (inMI.getDimensions()); afwImage::Image resPIGpu(inMI.getDimensions()); const int GPUrep = 4; int repCpu = sizeRepMax * 18 / kernelSizeX; int repGpu = GPUrep * sizeRepMax * 18 / kernelSizeX; // convolve plain image time_t plainImgCpuStart = clock(); for (int i = 0; i < repCpu; i++) afwMath::convolve(resPI , inPI, *kernel, cctrlXCpu); double plainImgCpuTime = DiffTime(plainImgCpuStart, clock()) / repCpu; time_t plainImgGpuStart = clock(); for (int i = 0; i < repGpu; i++) afwMath::convolve(resPIGpu, inPI, *kernel, cctrlXGpu); double plainImgGpuTime = DiffTime(plainImgGpuStart, clock()) / repGpu; double diffPI = CvRmsd(resPI, resPIGpu); cout << setw(2) << setfill('0') << kernelSizeX << "x" << setw(2) << kernelSizeY << setfill(' '); cout << setw(8) << DecimalPlaces(3, plainImgCpuTime) << " s " ; cout << setw(8) << DecimalPlaces(4, plainImgGpuTime) << " s " ; cout << setw(6) << DecimalPlaces(1, plainImgCpuTime / plainImgGpuTime) << "x " ; cout << setw(16) << diffPI ; cout << endl; } template < typename T> void TestLCChebKernel(const afwImage::MaskedImage inImg, const int order, const int basisKernelCount, const int skipSize = 2, const int gpuRep = 1 ) { const int sizeX = inImg.getWidth(); const int sizeY = inImg.getHeight(); const afwImage::Image inPIDbl = *inImg.getImage(); cout << endl; string typeStr = sizeof(T) == sizeof(float) ? string("float") : string("double"); cout << " Plain Image<" << typeStr << ">, LC kernel with Chebyshev spatial function" << endl; cout << " Number of basis kernels: " << basisKernelCount << endl; cout << " Spatial order: " << order << endl; cout << " Size CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 6; i < 19; i += skipSize) { LinearCombinationKernel::Ptr linCoKernelCheb = ConstructLinearCombinationKernel( i, i, //size basisKernelCount, //basis kernel count order, //order sizeX, sizeY, //image size false //chebyshev ); TimeOneKernelPI(inImg, linCoKernelCheb, gpuRep * 2); } cout << endl; cout << " Masked Image<" << typeStr << ">, LC kernel with Chebyshev spatial function" << endl; cout << " Number of basis kernels: " << basisKernelCount << endl; cout << " Spatial order: " << order << endl; cout << " Size CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 6; i < 19; i += skipSize) { LinearCombinationKernel::Ptr linCoKernelCheb = ConstructLinearCombinationKernel( i, i, //size basisKernelCount, //basis kernel count order, //order sizeX, sizeY, //image size false //chebyshev ); TimeOneKernelMI(inImg, linCoKernelCheb, gpuRep); } } void TestConvGpu( const afwImage::MaskedImage inImgDbl, const afwImage::MaskedImage inImgFlt ) { const afwImage::MaskedImage inMIDbl = inImgDbl; const afwImage::MaskedImage inMIFlt = inImgFlt; const int sizeX = inMIDbl.getWidth(); const int sizeY = inMIDbl.getHeight(); { // do one convolution and discard the result // because first convolution has to initialize GPU, thus using aditional time afwMath::FixedKernel::Ptr fixedKernel = ConstructKernel(7, 7); afwMath::ConvolutionControl cctrlXGpu (false, false, 0, lsst::afw::gpu::AUTO); afwImage::MaskedImage resMI (inMIFlt.getDimensions()); afwMath::convolve(resMI, inMIFlt, *fixedKernel, cctrlXGpu); } const afwImage::Image inPIDbl = *inMIDbl.getImage(); const afwImage::Image inPIFlt = *inMIFlt.getImage(); cout << "Image size: " << sizeX << " x " << sizeY << endl; cout << endl; cout << " Plain Image, fixed kernel" << endl; cout << " Size CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 6; i < 19; i++) { afwMath::FixedKernel::Ptr fixedKernel = ConstructKernel(i, i); TimeOneKernelPI(inMIFlt, fixedKernel, 4); } cout << endl; cout << " Masked Image, fixed kernel" << endl; cout << " Size CPU time GPU time Speedup Image Dev Variance Dev Mask Diff" << endl; PrintSeparator(); for (int i = 6; i < 19; i++) { afwMath::FixedKernel::Ptr fixedKernel = ConstructKernel(i, i); TimeOneKernelMI(inMIFlt, fixedKernel, 4); } TestLCChebKernel(inMIFlt, 2, 1); TestLCChebKernel(inMIFlt, 2, 4); TestLCChebKernel(inMIFlt, 3, 4); TestLCChebKernel(inMIDbl, 3, 4); } void TimeGpu(int argc, char**argv) {
    481 0930ac63 - string baseFileName = GetInputFileName(argc, argv);
    477 a9aec7fc + string inImagePath = GetInputImagePath(argc, argv);
    483 0930ac63 - afwImage::MaskedImage inImgFlt(baseFileName);
    ? ^ ^ ^^^^^ ^^
    479 a9aec7fc + afwImage::MaskedImage inImgFlt(inImagePath);
    ? ^^^^ ^ ^ ^^
    484 0930ac63 - afwImage::MaskedImage inImgDbl(baseFileName);
    ? ^ ^ ^^^^^ ^^
    480 a9aec7fc + afwImage::MaskedImage inImgDbl(inImagePath);
    ? ^^^^ ^ ^ ^^ TestConvGpu(inImgDbl, inImgFlt); } int main(int argc, char **argv) { int status = EXIT_SUCCESS; if (lsst::afw::gpu::isGpuBuild()) { lsst::afw::gpu::detail::PrintCudaDeviceInfo(); } else { cout << "AFW not compiled with GPU support. Exiting." << endl; return EXIT_SUCCESS; } PrintSeparator(); cout << endl; cout << "Note: Dev = coefficient of variation of RMSD" << endl; cout << endl; TimeGpu(argc, argv); // Check for memory leaks if (lsst::daf::base::Citizen::census(0) == 0) { cerr << "No leaks detected" << endl; } else { cerr << "Leaked memory blocks:" << endl; lsst::daf::base::Citizen::census(cerr); status = EXIT_FAILURE; } return status; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0930ac63

    commit 0930ac63373c05e0d936dcb19795df4c8fc806b6
    Author: Kresimir Cosic 
    Date:   Thu Nov 24 05:28:27 2011 +0100
    
        Added a unit test and an example
        - example is timeConvolveGpu.cc, it displays speedup for various cases
        - unit test is convolveGpu.cc
        - also fixed a bug in nvcc command line
        - also made some additional functions visible to CPU-only build
    

    fbfcd257

    commit fbfcd257864824c15ce8d6888036e2523bb42ec9
    Author: Kresimir Cosic 
    Date:   Wed Dec 7 16:23:10 2011 +0100
    
        Fixed GPU test and example to point to correct file in afwdata directory
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    python/lsst/afw/detection/footprintset.i

    Diff:

                    
                    
                    %{
                    #include "lsst/afw/detection/FootprintSet.h"
                    #include "lsst/afw/table/Source.h"
                    %}
                    
                    %import "lsst/afw/table/Source.i"
                    
                    %shared_ptr(lsst::afw::detection::FootprintSet);
                    
                    %include "lsst/afw/detection/FootprintSet.h"
                    
                    %define %footprintSetOperations(PIXEL)
    
    15 ff27aae1 + // uncomment the following two lines and update FootprintSet.h accordingly
    16 ff27aae1 + // once https://github.com/swig/swig/issues/245 is fixed
    15 505b2e60 - %template(FootprintSet) FootprintSet;
    17 ff27aae1 + // %template(FootprintSet) FootprintSet;
    ? +++
    16 505b2e60 - %template(FootprintSet) FootprintSet;
    18 ff27aae1 + // %template(FootprintSet) FootprintSet;
    ? +++ %template(makeHeavy) makeHeavy; %template(setMask) setMask; %enddef %extend lsst::afw::detection::FootprintSet { %footprintSetOperations(boost::uint16_t) %footprintSetOperations(int) %footprintSetOperations(float) %footprintSetOperations(double) } namespace lsst { namespace afw { namespace table { typedef VectorT< lsst::afw::table::SourceRecord, lsst::afw::table::SourceTable > SourceVector; }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    505b2e60

    commit 505b2e607d572e4139e513363ec24a4e3c63abb4
    Author: Dustin Lang 
    Date:   Mon Apr 9 09:25:34 2012 -0500
    
        split out FootprintSet from footprints.i
    

    Commits in /Users/nate/repos_lsst/afw/

    ff27aae1

    commit ff27aae1e2414be9ca96bdc36703f28f02d52122
    Author: Russell Owen 
    Date:   Thu Oct 16 09:27:57 2014 -0700
    
        Added a rather ugly workaround for a SWIG 3 bug
    

    Return to list

    python/lsst/afw/fits/pickleFits.py

    Diff:

                    from lsst.afw.fits.fitsLib import MemFileManager, cdata, memmove
                    
                    def reduceToFits(obj):
                        """Pickle to FITS
                    
                        Intended to be used by the __reduce__ method of a class.
                    
                        Assumes the existence of a "writeFits" method on the object.
                        """
                        manager = MemFileManager()
                        obj.writeFits(manager)
                        size = manager.getLength()
                        data = cdata(manager.getData(), size);
                        return (unreduceFromFits, (obj.__class__, data, size))
                    
                    def unreduceFromFits(cls, data, size):
                        """Unpickle from FITS
                    
                        Unpacks data produced by reduceToFits.
                    
                        Assumes the existence of a "readFits" method on the object.
                        """
    
    23 543979fa - manager = MemFileManager(size + 1) # Allow an extra char for nul
    23 6751654c + manager = MemFileManager(size)
    memmove(manager.getData(), data) return cls.readFits(manager)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    543979fa

    commit 543979fa6a787780172e97c01eeae72598ff9ccd
    Author: Paul Price 
    Date:   Thu Sep 25 15:01:02 2014 -0400
    
        unreduceFromFits: allow extra char for nul
        
        Valgrind picked up an invalid write a single byte beyond the limit of the
        allocated memory.  It seems we need an extra byte to allow for a nul char.
    

    Commits in /Users/nate/repos_lsst/afw/

    6751654c

    commit 6751654c14e9ca1a453c1f4f9643335e9bda26a2
    Author: Paul Price 
    Date:   Fri Nov 1 22:16:50 2013 -0400
    
        image,fits: consolidate FITS pickling code, and use for image classes (#3035)
        
        Image pickling code didn't work on MaskedImage or Mask.  Stripped
        out use of boost_picklable for image classes in favour of FITS-based
        pickling (like Table; see #2344).  To do so, made the FITS-based
        pickling code generally accessible; now anything can use it so long as
        it can "writeFits" and "readFits".
        
        Picklable image classes are: Image, Mask, MaskedImage, Exposure.
        
        This adds new static "readFits" methods to the image classes that simply
        forward to the proper Constructor methods.  While this increases the number
        of interfaces, this parallels the operations in the Catalog classes (which
        don't have proper Constructors that can read a FITS file).
    

    Return to list

    python/lsst/afw/table/specializations.i

    Diff:

                    // This file contains workarounds for SWIG's lack of complete support
                    // for partial specialization of templates in C++, reported as SWIG
                    // bug #3465431.  If/when that bug is fixed, this should be simplifed
                    // by replacing many of the get/set implementations with %template lines.
                    
                    %define %specializeScalar(U, PYNAME)
                    %extend lsst::afw::table::KeyBase< U > {
                        %pythoncode %{
                            subfields = None
                            subkeys = None
                            HAS_NAMED_SUBFIELDS = False
                        %}
                    }
                    %extend lsst::afw::table::BaseRecord {
                        %template(get) get< U >;
                        %template(get##PYNAME) get< U >;
                        %template(set) set< U, U >;
                        %template(set##PYNAME) set< U, U >;
                        U __getitem__(lsst::afw::table::Key< U > const & key) const { return (*self)[key]; }
                        void __setitem__(lsst::afw::table::Key< U > const & key, U value) { (*self)[key] = value; }
                    }
                    %extend lsst::afw::table::BaseColumnView {
                        ndarray::Array __getitem__(Key const & key) const { return (*self)[key]; }
                        void __setitem__(Key const & key, ndarray::Array const & v) const { (*self)[key] = v; }
                    }
                    %enddef
                    
                    %define %specializePoint(U, PYNAME, VALUE...)
                    %extend lsst::afw::table::KeyBase< lsst::afw::table::Point< U > > {
                        lsst::afw::table::Key getX() const { return self->getX(); }
                        lsst::afw::table::Key getY() const { return self->getY(); }
                        %pythoncode %{
                            subfields = ("x", "y")
                            subkeys = property(lambda self: (self.getX(), self.getY()))
                            HAS_NAMED_SUBFIELDS = True
                        %}
                    }
                    %extend lsst::afw::table::BaseRecord {
                    
                        VALUE get(lsst::afw::table::Key< Point< U > > const & key) const
                        { return self->get(key); }
                    
                        VALUE getPoint##PYNAME(lsst::afw::table::Key< Point< U > > const & key) const
                        { return self->get(key); }
                    
                        void set(lsst::afw::table::Key< Point< U > > const & key, VALUE const & v)
                        { self->set(key, v); }
                    
                        void setPoint##PYNAME(lsst::afw::table::Key< Point< U > > const & key, VALUE const & v)
                        { self->set(key, v); }
                    
                    }
                    %extend lsst::afw::table::BaseColumnView {
                        void __getitem__(Key< Point > const & key) const {
                            throw LSST_EXCEPT(
    
    56 52166bd3 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    56 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot get column view to Point field." ); } } %enddef %define %specializeMoments(U, PYNAME, VALUE...) %extend lsst::afw::table::KeyBase< lsst::afw::table::Moments< U > > { lsst::afw::table::Key getIxx() const { return self->getIxx(); } lsst::afw::table::Key getIyy() const { return self->getIyy(); } lsst::afw::table::Key getIxy() const { return self->getIxy(); } %pythoncode %{ subfields = ("xx", "yy", "xy") subkeys = property(lambda self: (self.getIxx(), self.getIyy(), self.getIxy())) HAS_NAMED_SUBFIELDS = True %} } %extend lsst::afw::table::BaseRecord { VALUE get(lsst::afw::table::Key< Moments > const & key) const { return self->get(key); } VALUE getMoments##PYNAME(lsst::afw::table::Key< Moments > const & key) const { return self->get(key); } void set(lsst::afw::table::Key< Moments > const & key, VALUE const & v) { self->set(key, v); } void setMoments##PYNAME(lsst::afw::table::Key< Moments > const & key, VALUE const & v) { self->set(key, v); } } %extend lsst::afw::table::BaseColumnView { void __getitem__(Key< Moments > const & key) const { throw LSST_EXCEPT(
    92 52166bd3 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    92 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot get column view to Moments field." ); } } %enddef %define %specializeArray(U, PYNAME) %extend lsst::afw::table::KeyBase< lsst::afw::table::Array< U > > { lsst::afw::table::Key get(int n) const { return (*self)[n]; } lsst::afw::table::Key< lsst::afw::table::Array< U > > slice(int begin, int end) const { return self->slice(begin, end); } %pythoncode %{ subfields = property(lambda self: tuple(range(self.getSize()))) subkeys = property(lambda self: tuple(self[i] for i in range(self.getSize()))) HAS_NAMED_SUBFIELDS = False def __getitem__(self, k): if isinstance(k, slice): return self.slice(k.start, k.stop) else: return self.get(k) %} } %extend lsst::afw::table::FieldBase< lsst::afw::table::Array< U > > { int getSize() const { return self->getSize(); } bool isVariableLength() const { return self->isVariableLength(); } } %extend lsst::afw::table::BaseRecord { ndarray::Array get(lsst::afw::table::Key< Array< U > > const & key) const { return self->get(key); } ndarray::Array getArray##PYNAME(lsst::afw::table::Key< Array< U > > const & key) const { return self->get(key); } void set( lsst::afw::table::Key< Array< U > > const & key, ndarray::Array const & v ) { self->set(key, v); } void setArray##PYNAME( lsst::afw::table::Key< Array< U > > const & key, ndarray::Array const & v ) { self->set(key, v); } void set( lsst::afw::table::Key< Array< U > > const & key, ndarray::Array const & v ) { self->set(key, v); } void setArray##PYNAME( lsst::afw::table::Key< Array< U > > const & key, ndarray::Array const & v ) { self->set(key, v); } ndarray::Array __getitem__(lsst::afw::table::Key< Array< U > > const & key) { return (*self)[key]; } void __setitem__( lsst::afw::table::Key< Array< U > > const & key, ndarray::Array const & v ) { (*self)[key] = v; } } %extend lsst::afw::table::BaseColumnView { ndarray::Array __getitem__(Key< lsst::afw::table::Array > const & key) const { return (*self)[key]; } void __setitem__( Key< lsst::afw::table::Array > const & key, ndarray::Array const & v ) const { (*self)[key] = v; } } %enddef %define %specializeCovariance(U, PYNAME) %extend lsst::afw::table::KeyBase< lsst::afw::table::Covariance< U > > { lsst::afw::table::Key _getitem_impl(int i, int j) const { return (*self)(i, j); } %pythoncode %{ def __getitem__(self, args): return self._getitem_impl(*args) subfields = property(_syntax.KeyBaseCov_subfields) subkeys = property(_syntax.KeyBaseCov_subkeys) HAS_NAMED_SUBFIELDS = False %} } %extend lsst::afw::table::FieldBase< lsst::afw::table::Covariance< U > > { int getSize() const { return self->getSize(); } int getPackedSize() const { return self->getPackedSize(); } } %extend lsst::afw::table::BaseRecord { Eigen::Matrix get( lsst::afw::table::Key< lsst::afw::table::Covariance< U > > const & key ) const { return self->get(key); } Eigen::Matrix getCov##PYNAME( lsst::afw::table::Key< lsst::afw::table::Covariance< U > > const & key ) const { return self->get(key); } void set( lsst::afw::table::Key< lsst::afw::table::Covariance< U > > const & key, Eigen::Matrix const & v ) { self->set(key, v); } void setCov##PYNAME( lsst::afw::table::Key< lsst::afw::table::Covariance< U > > const & key, Eigen::Matrix const & v ) { self->set(key, v); } } %extend lsst::afw::table::BaseColumnView { void __getitem__(Key< lsst::afw::table::Covariance > const & key) const { throw LSST_EXCEPT(
    227 52166bd3 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    227 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot get column view to Covariance field." ); } } %extend lsst::afw::table::KeyBase< lsst::afw::table::Covariance< lsst::afw::table::Point< U > > > { lsst::afw::table::Key _getitem_impl(int i, int j) const { return (*self)(i, j); } %pythoncode %{ def __getitem__(self, args): return self._getitem_impl(*args) subfields = property(_syntax.KeyBaseCov_subfields) subkeys = property(_syntax.KeyBaseCov_subkeys) HAS_NAMED_SUBFIELDS = False %} } %extend lsst::afw::table::FieldBase< lsst::afw::table::Covariance< lsst::afw::table::Point< U > > > { int getSize() const { return self->getSize(); } int getPackedSize() const { return self->getPackedSize(); } } %extend lsst::afw::table::BaseRecord { Eigen::Matrix get( lsst::afw::table::Key< lsst::afw::table::Covariance< lsst::afw::table::Point > > const & key ) const { return self->get(key); } Eigen::Matrix getCovPoint##PYNAME( lsst::afw::table::Key< lsst::afw::table::Covariance< lsst::afw::table::Point > > const & key ) const { return self->get(key); } void set( lsst::afw::table::Key< lsst::afw::table::Covariance< lsst::afw::table::Point > > const & key, Eigen::Matrix const & v ) { self->set(key, v); } void setCovPoint##PYNAME( lsst::afw::table::Key< lsst::afw::table::Covariance< lsst::afw::table::Point > > const & key, Eigen::Matrix const & v ) { self->set(key, v); } } %extend lsst::afw::table::BaseColumnView { void __getitem__(Key< lsst::afw::table::Covariance< lsst::afw::table::Point > > const & key) const { throw LSST_EXCEPT(
    275 52166bd3 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    275 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot get column view to Covariance field." ); } } %extend lsst::afw::table::KeyBase< lsst::afw::table::Covariance< lsst::afw::table::Moments< U > > > { lsst::afw::table::Key _getitem_impl(int i, int j) const { return (*self)(i, j); } %pythoncode %{ def __getitem__(self, args): return self._getitem_impl(*args) subfields = property(_syntax.KeyBaseCov_subfields) subkeys = property(_syntax.KeyBaseCov_subkeys) HAS_NAMED_SUBFIELDS = False %} } %extend lsst::afw::table::FieldBase< lsst::afw::table::Covariance< lsst::afw::table::Moments< U > > > { int getSize() const { return self->getSize(); } int getPackedSize() const { return self->getPackedSize(); } } %extend lsst::afw::table::BaseRecord { Eigen::Matrix get( lsst::afw::table::Key< Covariance< Moments< U > > > const & key ) const { return self->get(key); } Eigen::Matrix getCovMoments##PYNAME( lsst::afw::table::Key< Covariance< Moments< U > > > const & key ) const { return self->get(key); } void set( lsst::afw::table::Key< Covariance< Moments< U > > > const & key, Eigen::Matrix const & v ) { self->set(key, v); } void setCovMoments##PYNAME( lsst::afw::table::Key< Covariance< Moments< U > > > const & key, Eigen::Matrix const & v ) { self->set(key, v); } } %extend lsst::afw::table::BaseColumnView { void __getitem__(Key< lsst::afw::table::Covariance< lsst::afw::table::Moments > > const & key) const { throw LSST_EXCEPT(
    323 52166bd3 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    323 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot get column view to Covariance field." ); } } %enddef %extend lsst::afw::table::BaseRecord { bool get(lsst::afw::table::Key< Flag > const & key) const { return self->get(key); } bool getFlag(lsst::afw::table::Key< Flag > const & key) const { return self->get(key); } void set(lsst::afw::table::Key< Flag > const & key, bool value) { self->set(key, value); } void setFlag(lsst::afw::table::Key< Flag > const & key, bool value) { self->set(key, value); } } %extend lsst::afw::table::KeyBase< Flag > { %pythoncode %{ subfields = None subkeys = None HAS_NAMED_SUBFIELDS = False %} } %extend lsst::afw::table::BaseColumnView { ndarray::Array __getitem__( lsst::afw::table::Key< lsst::afw::table::Flag > const & key ) const { return ndarray::copy((*self)[key]); } } %extend lsst::afw::table::KeyBase< lsst::afw::coord::Coord > { lsst::afw::table::Key getRa() const { return self->getRa(); } lsst::afw::table::Key getDec() const { return self->getDec(); } %pythoncode %{ subfields = ("ra", "dec") subkeys = property(lambda self: (self.getRa(), self.getDec())) HAS_NAMED_SUBFIELDS = True %} } %extend lsst::afw::table::BaseRecord { lsst::afw::coord::IcrsCoord get( lsst::afw::table::Key< lsst::afw::coord::Coord > const & key ) const { return self->get(key); } lsst::afw::coord::IcrsCoord getCoord( lsst::afw::table::Key< lsst::afw::coord::Coord > const & key ) const { return self->get(key); } void set( lsst::afw::table::Key< lsst::afw::coord::Coord > const & key, lsst::afw::coord::Coord const & v ) { self->set(key, v); } void setCoord( lsst::afw::table::Key< lsst::afw::coord::Coord > const & key, lsst::afw::coord::Coord const & v ) { self->set(key, v); } } %extend lsst::afw::table::BaseColumnView { void __getitem__(Key< lsst::afw::coord::Coord > const & key) const { throw LSST_EXCEPT(
    406 52166bd3 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    406 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot get column view to Coord field." ); } } %extend lsst::afw::table::BaseRecord { std::string get(lsst::afw::table::Key< std::string > const & key) const { return self->get(key); } std::string getString(lsst::afw::table::Key< std::string > const & key) const { return self->get(key); } std::string __getitem__(lsst::afw::table::Key< std::string > const & key) const { return self->get(key); } void set(lsst::afw::table::Key< std::string > const & key, std::string const & v) { self->set(key, v); } void setString(lsst::afw::table::Key< std::string > const & key, std::string const & v) { self->set(key, v); } void __setitem__(lsst::afw::table::Key< std::string > const & key, std::string const & v) { self->set(key, v); } } %extend lsst::afw::table::KeyBase< std::string > { %pythoncode %{ subfields = None subkeys = None HAS_NAMED_SUBFIELDS = False %} } %specializeScalar(boost::uint16_t, U) %specializeScalar(boost::int32_t, I) %specializeScalar(boost::int64_t, L) %specializeScalar(float, F) %specializeScalar(double, D) %specializeScalar(lsst::afw::geom::Angle, Angle) %specializePoint(boost::int32_t, I, lsst::afw::geom::Point) %specializePoint(double, D, lsst::afw::geom::Point) %specializeMoments(double, D, lsst::afw::geom::ellipses::Quadrupole) %specializeArray(boost::uint16_t, U) %specializeArray(int, I) %specializeArray(float, F) %specializeArray(double, D) %specializeCovariance(float, F)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    52166bd3

    commit 52166bd300c62b7dd934eac6112bf9ca696d878b
    Author: Jim Bosch 
    Date:   Wed Jun 13 17:50:49 2012 -0400
    
        Add overloads for unsupported column accessors in Python that just throw custom exceptions instead of generic SWIG ones.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/table/io/InputArchive.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    #include "boost/format.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/table/io/InputArchive.h"
                    #include "lsst/afw/table/io/Persistable.h"
                    #include "lsst/afw/table/io/ArchiveIndexSchema.h"
                    #include "lsst/afw/table/io/CatalogVector.h"
                    #include "lsst/afw/fits.h"
                    
                    namespace lsst { namespace afw { namespace table { namespace io {
                    
                    namespace {
                    
                    ArchiveIndexSchema const & indexKeys = ArchiveIndexSchema::get();
                    
                    // Functor to sort records by ID and then by catPersistable
                    struct IndexSortCompare {
                        bool operator()(BaseRecord const & a, BaseRecord const & b) const {
                            if (a.get(indexKeys.id) < b.get(indexKeys.id)) {
                                return true;
                            }
                            if (a.get(indexKeys.id) == b.get(indexKeys.id)) {
                                return a.get(indexKeys.catPersistable) < b.get(indexKeys.catPersistable);
                            }
                            return false;
                        }
                    };
                    
                    } // anonymous
                    
                    // ----- InputArchive::Impl ---------------------------------------------------------------------------------
                    
                    class InputArchive::Impl : private boost::noncopyable {
                    public:
                    
                        PTR(Persistable) get(int id, InputArchive const & self) {
                            PTR(Persistable) empty;
                            if (id == 0) return empty;
                            std::pair r = _map.insert(std::make_pair(id, empty));
                            if (r.second) {
                                // insertion successful means we haven't reassembled this object yet; do that now.
                                CatalogVector factoryArgs;
                                // iterate over records in index with this ID; we know they're sorted by ID and then
                                // by catPersistable, so we can just append to factoryArgs.
                                std::string name;
                                std::string module;
                                for (
                                    BaseCatalog::iterator indexIter = _index.find(id, indexKeys.id);
                                    indexIter != _index.end() && indexIter->get(indexKeys.id) == id; 
                                    ++indexIter
                                ) {
                                    if (name.empty()) {
                                        name = indexIter->get(indexKeys.name);
                                    } else if (name != indexIter->get(indexKeys.name)) {
                                        throw LSST_EXCEPT(
                                            MalformedArchiveError,
                                            (boost::format(
                                                "Inconsistent name in index for ID %d; got '%s', expected '%s'"
                                            ) % indexIter->get(indexKeys.id) % indexIter->get(indexKeys.name) % name).str()
                                        );
                                    }
                                    if (module.empty()) {
                                        module = indexIter->get(indexKeys.module);
                                    } else if (module != indexIter->get(indexKeys.module)) {
                                        throw LSST_EXCEPT(
                                            MalformedArchiveError,
                                            (boost::format(
                                                "Inconsistent module in index for ID %d; got '%s', expected '%s'"
                                            ) % indexIter->get(indexKeys.id) % indexIter->get(indexKeys.module) % module).str()
                                        );
                                    }
                                    std::size_t catN = indexIter->get(indexKeys.catArchive)-1;
                                    if (catN >= _catalogs.size()) {
                                        throw LSST_EXCEPT(
                                            MalformedArchiveError,
                                            (boost::format(
                                                "Invalid catalog number in index for ID %d; got '%d', max is '%d'"
                                            ) % indexIter->get(indexKeys.id) % catN % _catalogs.size()).str()
                                        );
                                    }
                                    BaseCatalog & fullCatalog = _catalogs[catN];
                                    std::size_t i1 = indexIter->get(indexKeys.row0);
                                    std::size_t i2 = i1 + indexIter->get(indexKeys.nRows);
                                    if (i2 > fullCatalog.size()) {
                                        throw LSST_EXCEPT(
                                            MalformedArchiveError,
                                            (boost::format(
                                                "Index and data catalogs do not agree for ID %d; catalog %d has %d rows, not %d"
                                            ) % indexIter->get(indexKeys.id)
                                             % indexIter->get(indexKeys.catArchive) % fullCatalog.size() % i2).str()
                                        );
                                    }
                                    factoryArgs.push_back(
                                        BaseCatalog(fullCatalog.getTable(), fullCatalog.begin() + i1, fullCatalog.begin() + i2)
                                    );
                                }
                                try {
                                    PersistableFactory const & factory = PersistableFactory::lookup(name, module);
                                    r.first->second = factory.read(self, factoryArgs);
                                } catch (pex::exceptions::Exception & err) {
                                    LSST_EXCEPT_ADD(
                                        err, (boost::format("loading object with id=%d, name='%s'") % id % name).str()
                                    );
                                    throw;
                                }
    
    108 4aaa02e3 - }
    108 6891c1fa + // If we're loading the object for the first time, and we've failed, we should have already
    109 6891c1fa + // thrown an exception, and we assert that here.
    109 4aaa02e3 - assert(r.first->second);
    110 6891c1fa + assert(r.first->second);
    ? ++++
    111 6891c1fa + } else if (!r.first->second) {
    112 6891c1fa + // If we'd already tried and failed to load this object before - but we'd caught the exception
    113 6891c1fa + // previously (because the calling code didn't consider that to be a fatal error) - we'll
    114 6891c1fa + // just throw an exception again. While we can't know exactly what was thrown before,
    115 6891c1fa + // it's most likely it was a NotFoundError because a needed extension package was not setup.
    116 6891c1fa + // And conveniently it's appropriate to throw that here too, since now the problem is that
    117 6891c1fa + // the object should have been loaded into the cache and it wasn't found there.
    118 6891c1fa + throw LSST_EXCEPT(
    119 6891c1fa + pex::exceptions::NotFoundError,
    120 6891c1fa + (boost::format(
    121 6891c1fa + "Not trying to reload object with id=%d; a previous attempt to load it already failed."
    122 6891c1fa + ) % id).str()
    123 6891c1fa + );
    124 4aaa02e3 + }
    return r.first->second; } Map const & getAll(InputArchive const & self) { int id = 0; for (BaseCatalog::iterator indexIter = _index.begin(); indexIter != _index.end(); ++indexIter) { if (indexIter->get(indexKeys.id) != id) { id = indexIter->get(indexKeys.id); get(id, self); } } return _map; } Impl() : _index(ArchiveIndexSchema::get().schema) {} Impl(BaseCatalog const & index, CatalogVector const & catalogs) : _index(index), _catalogs(catalogs) { if (index.getSchema() != indexKeys.schema) { throw LSST_EXCEPT(
    129 4aaa02e3 - pex::exceptions::RuntimeErrorException,
    ? ---------
    144 21597d88 + pex::exceptions::RuntimeError,
    "Incorrect schema for index catalog" ); } _map.insert(std::make_pair(0, PTR(Persistable)())); _index.sort(IndexSortCompare()); } Map _map; BaseCatalog _index; CatalogVector _catalogs; }; // ----- InputArchive --------------------------------------------------------------------------------------- InputArchive::InputArchive() : _impl(new Impl()) {} InputArchive::InputArchive(PTR(Impl) impl) : _impl(impl) {} InputArchive::InputArchive(BaseCatalog const & index, CatalogVector const & catalogs) : _impl(new Impl(index, catalogs)) {} InputArchive::InputArchive(InputArchive const & other) : _impl(other._impl) {} InputArchive & InputArchive::operator=(InputArchive const & other) { _impl = other._impl; return *this; } InputArchive::~InputArchive() {} PTR(Persistable) InputArchive::get(int id) const { return _impl->get(id, *this); } InputArchive::Map const & InputArchive::getAll() const { return _impl->getAll(*this); } InputArchive InputArchive::readFits(fits::Fits & fitsfile) { BaseCatalog index = BaseCatalog::readFits(fitsfile); PTR(daf::base::PropertyList) metadata = index.getTable()->popMetadata(); assert(metadata); // BaseCatalog::readFits should always read metadata, even if there's nothing there if (metadata->get("EXTTYPE") != "ARCHIVE_INDEX") { throw LSST_FITS_EXCEPT( fits::FitsError, fitsfile, boost::format("Wrong value for archive index EXTTYPE: '%s'") % metadata->get("EXTTYPE") ); } int nCatalogs = metadata->get("AR_NCAT"); CatalogVector catalogs; catalogs.reserve(nCatalogs); for (int n = 1; n < nCatalogs; ++n) { fitsfile.setHdu(1, true); // increment HDU by one catalogs.push_back(BaseCatalog::readFits(fitsfile)); metadata = catalogs.back().getTable()->popMetadata(); if (metadata->get("EXTTYPE") != "ARCHIVE_DATA") { throw LSST_FITS_EXCEPT( fits::FitsError, fitsfile, boost::format("Wrong value for archive data EXTTYPE: '%s'") % metadata->get("EXTTYPE") ); } if (metadata->get("AR_CATN") != n) { throw LSST_FITS_EXCEPT( fits::FitsError, fitsfile, boost::format("Incorrect order for archive catalogs: AR_CATN=%d found at position %d") % metadata->get("AR_CATN") % n ); } } PTR(Impl) impl(new Impl(index, catalogs)); return InputArchive(impl); } }}}} // namespace lsst::afw::table::io

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4aaa02e3

    commit 4aaa02e3e38d04136492c4fcaed39ee875d98edd
    Author: Jim Bosch 
    Date:   Thu Dec 6 19:41:40 2012 -0500
    
        New interface for table-based persistence.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    4aaa02e3

    commit 4aaa02e3e38d04136492c4fcaed39ee875d98edd
    Author: Jim Bosch 
    Date:   Thu Dec 6 19:41:40 2012 -0500
    
        New interface for table-based persistence.
    

    6891c1fa

    commit 6891c1fae697fcceca2dd3fc11c822a81fe87199
    Author: Jim Bosch 
    Date:   Wed Apr 29 16:33:47 2015 -0400
    
        Gracefully fail when a persisted object fails to load more than once
        
        Prior to this fix, the first failed load would throw an exception
        but leave the cache of loaded objects in a state that later loads
        would assume meant the object had loaded successfully, leading to
        an assertion failure.  Now, later loads will detect this cache
        state and just throw again.
    

    Return to list

    include/lsst/afw/geom/LinearTransform.h

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008-2014 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #ifndef LSST_AFW_GEOM_LINEAR_TRANSFORM_H 
                    #define LSST_AFW_GEOM_LINEAR_TRANSFORM_H
                    
                    #include "Eigen/Core"
                    #include "Eigen/Geometry"
                    #include "lsst/pex/exceptions/Runtime.h"
                    
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/geom/Angle.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace geom {
                    
    
    37 95d17565 - #ifndef SWIG
    38 ce01a540 - LSST_EXCEPTION_TYPE(SingularTransformException, lsst::pex::exceptions::RuntimeErrorException, lsst::afw::geom::SingularTransformException)
    ? ---- ---------
    37 6fc1c3d1 + LSST_EXCEPTION_TYPE(SingularTransformException, lsst::pex::exceptions::RuntimeError, lsst::afw::geom::SingularTransformException)
    39 95d17565 - #endif
    /** * \brief A 2D linear coordinate transformation. * * The transform is represented by a matrix \f$ \mathbf{M} \f$ such that * \f[ * \left[\begin{array}{ c } * x_f \\ * y_f * \end{array}\right] * = * \mathbf{M} * \left[\begin{array}{ c } * x_i \\ * y_i * \end{array}\right] * \f] * where \f$(x_i,y_i)\f$ are the input coordinates and \f$(x_f,y_f)\f$ are * the output coordinates. * * If \f$ x_f(x_i,y_i) \f$ and \f$ y_f(x_i,y_i) \f$ are continuous * differentiable functions, then * \f[ * \mathbf{M} = \left[\begin{array}{ c c } * \displaystyle\frac{\partial x_f}{\partial x_i} & * \displaystyle\frac{\partial x_f}{\partial y_i} \\ * \displaystyle\frac{\partial y_f}{\partial x_i} & * \displaystyle\frac{\partial y_f}{\partial y_i} * \end{array}\right] * \f] * evaluated at \f$(x_i,y_i)\f$. */ class LinearTransform { public: enum Parameters {XX=0,YX=1,XY=2,YY=3}; typedef Eigen::Matrix ParameterVector; typedef Eigen::Matrix TransformDerivativeMatrix; typedef Eigen::Matrix ProductDerivativeMatrix; typedef Eigen::Matrix Matrix; /** \brief Construct an empty (identity) LinearTransform. */ LinearTransform() : _matrix(Matrix::Identity()) {} /** \brief Construct an LinearTransform from an Eigen::Matrix. */ explicit LinearTransform(Matrix const & matrix) : _matrix(matrix) {} LinearTransform operator*(LinearTransform const & other) const { return LinearTransform(getMatrix() * other.getMatrix()); } static LinearTransform makeScaling(double s) { return LinearTransform((Matrix() << s, 0.0, 0.0, s).finished()); } static LinearTransform makeScaling(double s, double t) { return LinearTransform((Matrix() << s, 0.0, 0.0, t).finished()); } static LinearTransform makeRotation(Angle t) { return LinearTransform(Matrix(Eigen::Rotation2D(t.asRadians()))); } LinearTransform & operator=(LinearTransform const & other) { _matrix = other._matrix; return *this; } ParameterVector const getParameterVector() const; void setParameterVector(ParameterVector const & vector); Matrix const & getMatrix() const { return _matrix; } Matrix & getMatrix() { return _matrix; } double & operator[](int i) { return _matrix(i % 2, i / 2); } double const & operator[](int i) const { return const_cast(_matrix)(i % 2, i / 2); } LinearTransform const invert() const; double computeDeterminant() const; /** \brief Whether the transform is a no-op. */ bool isIdentity() const { return getMatrix().isIdentity(); } /** * \brief Transform a Point2D object. * * This operation is equivalent to applying the LinearTransform to an * lsst::afw::geom::Extent */ Point2D operator()(Point2D const & p) const { return Point2D(getMatrix() * p.asEigen()); } /** * \brief Transform a Extent2D object. * * This operation is equivalent to applying the LinearTransform to an * lsst::afw::geom::Point */ Extent2D operator()(Extent2D const & p) const { return Extent2D(getMatrix() * p.asEigen()); } TransformDerivativeMatrix dTransform(Point2D const & input) const; /// Derivative of (*this)(input) with respect to the transform elements (for Extent); TransformDerivativeMatrix dTransform(Extent2D const & input) const { return dTransform(Point2D(input)); } private: Matrix _matrix; }; std::ostream & operator<<(std::ostream & os, lsst::afw::geom::LinearTransform const & t); }}} // namespace lsst::afw::geom #endif // !LSST_AFW_GEOM_LINEAR_TRANSFORM_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ce01a540

    commit ce01a5406f327071e1701d534e563f0e75b870c4
    Author: jbosch 
    Date:   Wed Feb 2 01:27:08 2011 +0000
    
        afw #1556 - ellipses updated (#1551), but swig wrappers for ellipses now broken
    

    95d17565

    commit 95d1756551e9b95838e816f351f3f425a06cfc47
    Author: dubcovsky 
    Date:   Wed Mar 17 22:02:57 2010 +0000
    
        #1169 merged to trunk
    

    Commits in /Users/nate/repos_lsst/afw/

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    src/table/BaseTable.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    #include "boost/make_shared.hpp"
                    
                    #include "lsst/afw/table/BaseColumnView.h"
                    #include "lsst/afw/table/BaseRecord.h"
                    #include "lsst/afw/table/BaseTable.h"
                    #include "lsst/afw/table/Catalog.h"
                    #include "lsst/afw/table/SchemaMapper.h"
                    #include "lsst/afw/table/io/FitsWriter.h"
                    #include "lsst/afw/table/detail/Access.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    // =============== BaseTableImpl and BaseRecordImpl =========================================================
                    
                    //  These are a private table/record pair -- they're what you actually get when you do TableBase::make(),
                    //  but we hide them here to avoid a giant nest of friending that would be necessary if they had to make
                    //  their constructors private or protected.
                    
                    namespace {
                    
                    class BaseRecordImpl;
                    
                    class BaseTableImpl : public BaseTable {
                    public:
                    
                        explicit BaseTableImpl(Schema const & schema) : BaseTable(schema) {}
                    
                        BaseTableImpl(BaseTableImpl const & other) : BaseTable(other) {}
                    
                    private:
                        virtual PTR(BaseTable) _clone() const;
                        virtual PTR(BaseRecord) _makeRecord();
                    };
                    
                    class BaseRecordImpl : public BaseRecord {
                    public:
                        explicit BaseRecordImpl(PTR(BaseTable) const & table) : BaseRecord(table) {}
                    };
                    
                    PTR(BaseTable) BaseTableImpl::_clone() const {
                        return boost::make_shared(*this);
                    }
                    
                    PTR(BaseRecord) BaseTableImpl::_makeRecord() {
                        return boost::make_shared(shared_from_this());
                    }
                    
                    } // anonymous
                    
                    // =============== Block ====================================================================================
                    
                    //  This is a block of memory that doles out record-sized chunks when a table asks for them.
                    //  It inherits from ndarray::Manager so we can return ndarrays that refer to the memory in the
                    //  block with correct reference counting (ndarray::Manager is just an empty base class with an
                    //  internal reference count - it's like a shared_ptr without the pointer and template parameter.
                    //
                    //  Records are allocated in Blocks for two reasons:
                    //    - it allows tables to be either totally contiguous in memory (enabling column views) or
                    //      not (enabling dynamic addition of records) all in one class.
                    //    - it saves us from ever having to reallocate all the records associated with a table
                    //      when we run out of space (that's what a std::vector-like model would require).  This keeps
                    //      records and/or iterators to them from being invalidated, and it keeps tables from having
                    //      to track all the records whose data it owns.
                    
                    namespace {
                    
                    class Block : public ndarray::Manager {
                    public:
                        typedef boost::intrusive_ptr Ptr;
                    
                        // If the last chunk allocated isn't needed after all (usually because of an exception in a constructor)
                        // we reuse it immediately.  If it wasn't the last chunk allocated, it can't be reclaimed until
                        // the entire block goes out of scope.
                        static void reclaim(std::size_t recordSize, void * data, ndarray::Manager::Ptr const & manager) {
                            Ptr block = boost::static_pointer_cast(manager);
                            if (reinterpret_cast(data) + recordSize == block->_next) {
                                block->_next -= recordSize;
                            }
                        }
                    
                        // Ensure we have space for at least the given number of records as a contiguous block.
                        // May not actually allocate anything if we already do.
                        static void preallocate(
                            std::size_t recordSize,
                            std::size_t recordCount,
                            ndarray::Manager::Ptr & manager
                        ) {
                            Ptr block = boost::static_pointer_cast(manager);
                            if (!block || static_cast(block->_end - block->_next) < recordSize * recordCount) {
                                block = Ptr(new Block(recordSize, recordCount));
                                manager = block;
                            }
                        }
                    
                        static std::size_t getBufferSize(
                            std::size_t recordSize,
                            ndarray::Manager::Ptr const & manager
                        ) {
                            Ptr block = boost::static_pointer_cast(manager);
                            return static_cast(block->_end - block->_next) / recordSize;
                        }
                    
                        // Get the next chunk from the block, making a new block and installing it into the table
                        // if we're all out of space.
                        static void * get(std::size_t recordSize, ndarray::Manager::Ptr & manager) {
                            Ptr block = boost::static_pointer_cast(manager);
                            if (!block || block->_next == block->_end) {
                                block = Ptr(new Block(recordSize, BaseTable::nRecordsPerBlock));
                                manager = block;
                            }
                            void * r = block->_next;
                            block->_next += recordSize;
                            return r;
                        }
                    
                        // Block is also keeper of the special number that says what alignment boundaries are needed for
                        // schemas.  Before we start using a schema, we need to first ensure it meets that requirement,
                        // and pad it if not.
                        static void padSchema(Schema & schema) {
                            static int const MIN_RECORD_ALIGN = sizeof(AllocType);
                            int remainder = schema.getRecordSize() % MIN_RECORD_ALIGN;
                            if (remainder) {
                                detail::Access::padSchema(schema, MIN_RECORD_ALIGN - remainder);
                            }
                        }
                    
                    private:
                    
                        struct AllocType {
                            double element[2];
                        };
                    
                        explicit Block(std::size_t recordSize, std::size_t recordCount) :
                            _mem(new AllocType[(recordSize * recordCount) / sizeof(AllocType)]),
                            _next(reinterpret_cast(_mem.get())),
                            _end(_next + recordSize * recordCount)
                        {
                            assert((recordSize * recordCount) % sizeof(AllocType) == 0);
                            std::fill(_next, _end, 0); // initialize to zero; we'll later initialize floats to NaN.
                        }
                    
                        boost::scoped_array _mem;
                        char * _next;
                        char * _end;
                    };
                    
                    } // anonymous
                    
                    // =============== BaseTable implementation (see header for docs) ===========================================
                    
                    void BaseTable::preallocate(std::size_t n) {
                        Block::preallocate(_schema.getRecordSize(), n, _manager);
                    }
                    
                    std::size_t BaseTable::getBufferSize() const {
                        if (_manager) {
                            return Block::getBufferSize(_schema.getRecordSize(), _manager);
                        } else {
                            return 0;
                        }
                    }
                    
                    PTR(BaseTable) BaseTable::make(Schema const & schema) {
                        return boost::make_shared(schema);
                    }
                    
                    PTR(BaseRecord) BaseTable::copyRecord(BaseRecord const & input) {
                        PTR(BaseRecord) output = makeRecord();
                        output->assign(input);
                        return output;
                    }
                    
                    PTR(BaseRecord) BaseTable::copyRecord(BaseRecord const & input, SchemaMapper const & mapper) {
                        PTR(BaseRecord) output = makeRecord();
                        output->assign(input, mapper);
                        return output;
                    }
                    
                    PTR(io::FitsWriter) BaseTable::makeFitsWriter(fits::Fits * fitsfile, int flags) const {
                        return boost::make_shared(fitsfile, flags);
                    }
                    
                    BaseTable::BaseTable(Schema const & schema) : daf::base::Citizen(typeid(this)), _schema(schema) {
                        Block::padSchema(_schema);
    
    187 028f751f + _schema.disconnectAliases();
    188 a7452ce2 + _schema.getAliasMap()->_table = this;
    189 028f751f + }
    190 028f751f +
    191 028f751f + BaseTable::~BaseTable() {
    192 a7452ce2 + _schema.getAliasMap()->_table = 0;
    } namespace { // A Schema Functor used to set floating point-fields to NaN and initialize variable-length arrays // using placement new. All other fields are left alone, as they should already be zero. struct RecordInitializer { template static void fill(T * element, int size) {} // this matches all non-floating-point-element fields. static void fill(float * element, int size) { std::fill(element, element + size, std::numeric_limits::quiet_NaN()); } static void fill(double * element, int size) { std::fill(element, element + size, std::numeric_limits::quiet_NaN()); } static void fill(Angle * element, int size) { fill(reinterpret_cast(element), size); } template void operator()(SchemaItem const & item) const { fill( reinterpret_cast::Element *>(data + item.key.getOffset()), item.key.getElementCount() ); } template void operator()(SchemaItem< Array > const & item) const { if (item.key.isVariableLength()) { new (data + item.key.getOffset()) ndarray::Array(); } else { fill( reinterpret_cast::Element *>(data + item.key.getOffset()), item.key.getElementCount() ); } } void operator()(SchemaItem const & item) const {} // do nothing for Flag fields; already 0 char * data; }; // A Schema Functor used to set destroy variable-length array fields using an explicit call to their // destructor (necessary since we used placement new). All other fields are ignored, as they're POD. struct RecordDestroyer { template void operator()(SchemaItem const & item) const {} template void operator()(SchemaItem< Array > const & item) const { typedef ndarray::Array Element; if (item.key.isVariableLength()) { (*reinterpret_cast< Element * >(data + item.key.getOffset())).~Element(); } } char * data; }; } // anonymous void BaseTable::_initialize(BaseRecord & record) { record._data = Block::get(_schema.getRecordSize(), _manager); RecordInitializer f = { reinterpret_cast(record._data) }; _schema.forEach(f); record._manager = _manager; // manager always points to the most recently-used block. } void BaseTable::_destroy(BaseRecord & record) { assert(record._table.get() == this); RecordDestroyer f = { reinterpret_cast(record._data) }; _schema.forEach(f); if (record._manager == _manager) Block::reclaim(_schema.getRecordSize(), record._data, _manager); } /* * JFB has no idea whether the default value below is sensible, or even whether * it should be expressed ultimately as an approximate size in bytes rather than a * number of records; the answer probably depends on both the typical size of * records and the typical number of records. */ int BaseTable::nRecordsPerBlock = 100; // =============== BaseCatalog instantiation ================================================================= template class CatalogT; template class CatalogT; }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    028f751f

    commit 028f751fa3d0fe5101d2467942ea2e5229ba5200
    Author: Jim Bosch 
    Date:   Wed Jul 9 18:13:59 2014 -0400
    
        Notify owning tables when schema aliases are modified.
    

    a7452ce2

    commit a7452ce222551998eaff639f457528a35a31dd54
    Author: Jim Bosch 
    Date:   Thu Jul 10 11:36:08 2014 -0400
    
        Rename AliasMap accessors
    

    Return to list

    include/lsst/afw/image/Mask.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief LSST bitmasks
                     */
                    
                    #ifndef LSST_AFW_IMAGE_MASK_H
                    #define LSST_AFW_IMAGE_MASK_H
                    
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/cstdint.hpp"
                    #include "boost/shared_ptr.hpp"
                    
                    #include "lsst/base.h"
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/daf/base/Persistable.h"
                    #include "lsst/daf/base/PropertySet.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/formatters/ImageFormatter.h"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/image/LsstImageTypes.h"
                    
                    namespace lsst {
                    namespace afw {
                        namespace formatters {
                            template class MaskFormatter;
                        }
                    namespace image {
                    
                    namespace detail {
                        class MaskDict;                     // forward declaration
                    }
                    
                    // all masks will initially be instantiated with the same pixel type
                    namespace detail {
                        /// tag for a Mask
                        struct Mask_tag : public detail::basic_tag { };
                    
                        typedef std::map MaskPlaneDict;
                    }
                    
                    /**
                     * \brief Represent a 2-dimensional array of bitmask pixels
                     *
                     * Some mask planes are always defined (although you can add more with Mask::addMaskPlane):
                     *
                     
    • \c BAD This pixel is known to be bad (e.g. the amplifier is not working)
    • \c CR This pixel is contaminated by a cosmic ray
    • \c DETECTED This pixel lies within an object's Footprint
    • \c DETECTED_NEGATIVE This pixel lies within an object's Footprint, and the detection was looking for pixels \em below a specified level
    • \c EDGE This pixel is too close to the edge to be processed properly
    • \c INTRP This pixel has been interpolated over \note should be called \c INTERPOLATED
    • \c SAT This pixel is saturated and has bloomed \note should be called \c SATURATED
    • \c SUSPECT This pixel is untrustworthy, and you may wish to discard any Source containing it
    */ template class Mask : public ImageBase { public: typedef boost::shared_ptr Ptr; typedef boost::shared_ptr ConstPtr; typedef detail::MaskPlaneDict MaskPlaneDict; typedef detail::Mask_tag image_category; #if !defined(SWIG) /// A templated class to return this classes' type (present in Image/Mask/MaskedImage) template struct ImageTypeFactory { /// Return the desired type typedef Mask type; }; #endif // Constructors explicit Mask( unsigned int width, unsigned int height,
    113 b5f3475b - MaskPlaneDict const& planeDefs = MaskPlaneDict()
    ? - -
    113 eea3eb4a + MaskPlaneDict const& planeDefs=MaskPlaneDict()
    ); explicit Mask( unsigned int width, unsigned int height, MaskPixelT initialValue,
    118 b5f3475b - MaskPlaneDict const& planeDefs = MaskPlaneDict()
    ? - -
    118 eea3eb4a + MaskPlaneDict const& planeDefs=MaskPlaneDict()
    ); explicit Mask( geom::Extent2I const & dimensions=geom::Extent2I(),
    122 3263f939 - MaskPlaneDict const& planeDefs = MaskPlaneDict()
    ? - -
    122 eea3eb4a + MaskPlaneDict const& planeDefs=MaskPlaneDict()
    ); explicit Mask( geom::Extent2I const & dimensions, MaskPixelT initialValue,
    127 3263f939 - MaskPlaneDict const& planeDefs = MaskPlaneDict()
    ? - -
    127 eea3eb4a + MaskPlaneDict const& planeDefs=MaskPlaneDict()
    ); explicit Mask(geom::Box2I const & bbox,
    130 3263f939 - MaskPlaneDict const& planeDefs = MaskPlaneDict());
    ? - -
    130 eea3eb4a + MaskPlaneDict const& planeDefs=MaskPlaneDict());
    explicit Mask(geom::Box2I const & bbox, MaskPixelT initialValue,
    132 3263f939 - MaskPlaneDict const& planeDefs = MaskPlaneDict());
    ? - -
    132 eea3eb4a + MaskPlaneDict const& planeDefs=MaskPlaneDict());
    /** * @brief Construct a Mask by reading a regular FITS file. * * @param[in] fileName File to read. * @param[in] hdu HDU to read, 1-indexed (i.e. 1=Primary HDU). The special value * of 0 reads the Primary HDU unless it is empty, in which case it * reads the first extension HDU. * @param[in,out] metadata Metadata read from the header (may be null). * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. * @param[in] conformMasks If true, make Mask conform to the mask layout in the file. * * The meaning of the bitplanes is given in the header. If conformMasks is false (default), * the bitvalues will be changed to match those in Mask's plane dictionary. If it's true, the * bitvalues will be left alone, but Mask's dictionary will be modified to match the * on-disk version. */ explicit Mask( std::string const & fileName, int hdu=0,
    154 29a92ec3 - PTR(lsst::daf::base::PropertySet) metadata = PTR(lsst::daf::base::PropertySet)(),
    ? - -
    154 eea3eb4a + PTR(lsst::daf::base::PropertySet) metadata=PTR(lsst::daf::base::PropertySet)(),
    155 42dadff6 - geom::Box2I const & bbox = geom::Box2I(),
    ? - -
    155 1a4ca329 + geom::Box2I const & bbox=geom::Box2I(),
    156 271e8097 - ImageOrigin origin = LOCAL,
    ? - ^^^^ ^
    156 93994d54 + ImageOrigin origin=PARENT,
    ? ^ ^^^^
    157 271e8097 - bool conformMasks = false
    ? - -
    157 1a4ca329 + bool conformMasks=false
    ); /** * @brief Construct a Mask by reading a FITS image in memory. * * @param[in] manager An object that manages the memory buffer to read. * @param[in] hdu HDU to read, 1-indexed (i.e. 1=Primary HDU). The special value * of 0 reads the Primary HDU unless it is empty, in which case it * reads the first extension HDU. * @param[in,out] metadata Metadata read from the header (may be null). * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. * @param[in] conformMasks If true, make Mask conform to the mask layout in the file. * * The meaning of the bitplanes is given in the header. If conformMasks is false (default), * the bitvalues will be changed to match those in Mask's plane dictionary. If it's true, the * bitvalues will be left alone, but Mask's dictionary will be modified to match the * on-disk version. */ explicit Mask( fits::MemFileManager & manager, int hdu=0,
    180 29a92ec3 - PTR(lsst::daf::base::PropertySet) metadata = PTR(lsst::daf::base::PropertySet)(),
    ? - -
    180 eea3eb4a + PTR(lsst::daf::base::PropertySet) metadata=PTR(lsst::daf::base::PropertySet)(),
    181 bdc29e6a - geom::Box2I const & bbox = geom::Box2I(),
    ? - -
    181 1a4ca329 + geom::Box2I const & bbox=geom::Box2I(),
    182 271e8097 - ImageOrigin origin = LOCAL,
    ? - ^^^^ ^
    182 93994d54 + ImageOrigin origin=PARENT,
    ? ^ ^^^^
    183 271e8097 - bool conformMasks = false
    ? - -
    183 1a4ca329 + bool conformMasks=false
    ); /** * @brief Construct a Mask from an already-open FITS object. * * @param[in] fitsfile A FITS object to read from, already at the desired HDU. * @param[in,out] metadata Metadata read from the header (may be null). * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. * @param[in] conformMasks If true, make Mask conform to the mask layout in the file. * * The meaning of the bitplanes is given in the header. If conformMasks is false (default), * the bitvalues will be changed to match those in Mask's plane dictionary. If it's true, the * bitvalues will be left alone, but Mask's dictionary will be modified to match the * on-disk version. */ explicit Mask( fits::Fits & fitsfile,
    203 29a92ec3 - PTR(lsst::daf::base::PropertySet) metadata = PTR(lsst::daf::base::PropertySet)(),
    ? - -
    203 eea3eb4a + PTR(lsst::daf::base::PropertySet) metadata=PTR(lsst::daf::base::PropertySet)(),
    204 42dadff6 - geom::Box2I const & bbox = geom::Box2I(),
    ? - -
    204 1a4ca329 + geom::Box2I const & bbox=geom::Box2I(),
    205 271e8097 - ImageOrigin origin = LOCAL,
    ? - ^^^^ ^
    205 93994d54 + ImageOrigin origin=PARENT,
    ? ^ ^^^^
    206 271e8097 - bool conformMasks = false
    ? - -
    206 1a4ca329 + bool conformMasks=false
    ); // generalised copy constructor template Mask(Mask const& rhs, const bool deep) : image::ImageBase(rhs, deep), _maskDict(rhs._maskDict) {} Mask(const Mask& src, const bool deep=false); Mask( const Mask& src, const geom::Box2I & bbox,
    219 2035d06f - ImageOrigin const origin=LOCAL,
    ? ^^^ ^
    219 93994d54 + ImageOrigin const origin=PARENT,
    ? ^ ^^^^ const bool deep=false );
    223 a7ce1e71 - explicit Mask(ndarray::Array const & array, bool deep = false,
    ? - -
    223 eea3eb4a + explicit Mask(ndarray::Array const & array, bool deep=false,
    224 0db2729c - geom::Point2I const & xy0 = geom::Point2I());
    ? - -
    224 eea3eb4a + geom::Point2I const & xy0=geom::Point2I());
    void swap(Mask& rhs); // Operators Mask& operator=(MaskPixelT const rhs); Mask& operator=(const Mask& rhs); void operator|=(Mask const& rhs); void operator|=(MaskPixelT const rhs); void operator&=(Mask const& rhs); void operator&=(MaskPixelT const rhs); static MaskPixelT getPlaneBitMask(const std::vector &names); void operator^=(Mask const& rhs); void operator^=(MaskPixelT const rhs); typename ImageBase::PixelReference operator()(int x, int y); typename ImageBase::PixelConstReference operator()(int x, int y) const; bool operator()(int x, int y, int plane) const; typename ImageBase::PixelReference operator()(int x, int y, CheckIndices const&); typename ImageBase::PixelConstReference operator()(int x, int y, CheckIndices const&) const; bool operator()(int x, int y, int plane, CheckIndices const&) const; /** * @brief Write a mask to a regular FITS file. * * @param[in] fileName Name of the file to write. * @param[in] metadata Additional values to write to the header (may be null). * @param[in] mode "w"=Create a new file; "a"=Append a new HDU. */ void writeFits( std::string const& fileName, CONST_PTR(lsst::daf::base::PropertySet) metadata=PTR(lsst::daf::base::PropertySet)(), std::string const& mode="w" ) const; /** * @brief Write a mask to a FITS RAM file. * * @param[in] manager Manager object for the memory block to write to. * @param[in] metadata Additional values to write to the header (may be null). * @param[in] mode "w"=Create a new file; "a"=Append a new HDU. */ void writeFits( fits::MemFileManager & manager, CONST_PTR(lsst::daf::base::PropertySet) metadata=PTR(lsst::daf::base::PropertySet)(), std::string const& mode="w" ) const; /** * @brief Write a mask to an open FITS file object. * * @param[in] fitsfile A FITS file already open to the desired HDU. * @param[in] metadata Additional values to write to the header (may be null). */ void writeFits( fits::Fits & fitsfile,
    284 29a92ec3 - CONST_PTR(lsst::daf::base::PropertySet) metadata = CONST_PTR(lsst::daf::base::PropertySet)()
    ? - -
    284 eea3eb4a + CONST_PTR(lsst::daf::base::PropertySet) metadata=CONST_PTR(lsst::daf::base::PropertySet)()
    ) const; /** * @brief Read a Mask from a regular FITS file. * * @param[in] filename Name of the file to read. * @param[in] hdu Number of the "header-data unit" to read (where 1 is the Primary HDU). * The default value of 0 is interpreted as "the first HDU with NAXIS != 0". */ static Mask readFits(std::string const & filename, int hdu=0) { return Mask(filename, hdu); } /** * @brief Read a Mask from a FITS RAM file. * * @param[in] manager Object that manages the memory to be read. * @param[in] hdu Number of the "header-data unit" to read (where 1 is the Primary HDU). * The default value of 0 is interpreted as "the first HDU with NAXIS != 0". */ static Mask readFits(fits::MemFileManager & manager, int hdu=0) { return Mask(manager, hdu); } /// Interpret a mask value as a comma-separated list of mask plane names static std::string interpret(MaskPixelT value); std::string getAsString(int x, int y) { return interpret((*this)(x, y)); } // Mask Plane ops void clearAllMaskPlanes(); void clearMaskPlane(int plane); void setMaskPlaneValues(const int plane, const int x0, const int x1, const int y); static MaskPlaneDict parseMaskPlaneMetadata(CONST_PTR(lsst::daf::base::PropertySet)); // // Operations on the mask plane dictionary // static void clearMaskPlaneDict(); static int addMaskPlane(const std::string& name); static void removeMaskPlane(const std::string& name); void removeAndClearMaskPlane(const std::string& name, bool const removeFromDefault=false); static int getMaskPlane(const std::string& name); static MaskPixelT getPlaneBitMask(const std::string& name); static int getNumPlanesMax() { return 8*sizeof(MaskPixelT); } static int getNumPlanesUsed(); MaskPlaneDict const& getMaskPlaneDict() const; void printMaskPlanes() const; static void addMaskPlanesToMetadata(PTR(lsst::daf::base::PropertySet)); // // This one isn't static, it fixes up a given Mask's planes void conformMaskPlanes(const MaskPlaneDict& masterPlaneDict); private: //LSST_PERSIST_FORMATTER(lsst::afw::formatters::MaskFormatter) PTR(detail::MaskDict) _maskDict; // our bitplane dictionary static PTR(detail::MaskDict) _maskPlaneDict(); static int _setMaskPlaneDict(MaskPlaneDict const& mpd); static const std::string maskPlanePrefix; static int addMaskPlane(std::string name, int plane); static int getMaskPlaneNoThrow(const std::string& name); static MaskPixelT getBitMaskNoThrow(int plane); static MaskPixelT getBitMask(int plane); void _initializePlanes(MaskPlaneDict const& planeDefs); // called by ctors // // Make names in templatized base class visible (Meyers, Effective C++, Item 43) // using ImageBase::_getRawView; using ImageBase::swap; void checkMaskDictionaries(Mask const& other); }; template void swap(Mask& a, Mask& b); }}} // lsst::afw::image #endif // LSST_AFW_IMAGE_MASK_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0db2729c

    commit 0db2729c943e400b3d741354fd8399f7fdde3431
    Author: Robert Lupton the Good 
    Date:   Thu Dec 22 15:06:34 2011 -0500
    
        Initial version that compiles with MaskDict implementation of private Mask dictionaries
    

    42dadff6

    commit 42dadff68d69c7a54f53cc9d55fe0153e7a5b350
    Author: Jim Bosch 
    Date:   Sun Nov 18 18:50:24 2012 -0500
    
        Reimplement FITS image reading to use afw::fits
    

    29a92ec3

    commit 29a92ec37ff511e11d4ec25a920188b82833caad
    Author: Robert Lupton the Good 
    Date:   Wed Jan 9 11:50:09 2013 -0500
    
        Fully qualify daf::base to make doxygen happy
        
        We should really get doxygen fixed, but this is a
        benign workaround
    

    a7ce1e71

    commit a7ce1e71d391ee1b194eabea9cead705bd9858da
    Author: Jim Bosch 
    Date:   Mon Mar 19 16:09:24 2012 -0400
    
        moved ndarray out of lsst namespace and header directories
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    bdc29e6a

    commit bdc29e6ad86424c77ce94df33957b3ee950deb92
    Author: Jim Bosch 
    Date:   Mon Nov 19 11:47:11 2012 -0500
    
        Re-enable RAM FITS reading, remove test cases that just test cfitsio.
    

    b5f3475b

    commit b5f3475ba49a88c2d499d4b138d4bc8232134ed3
    Author: rhl 
    Date:   Fri Apr 29 13:52:15 2011 +0000
    
        Reinstated the (width, height) form of Image etc. constructors (#1652).  Added Exposure(Exposure, deep).  Adjusted copying/creating of Exposure._psf
    

    2035d06f

    commit 2035d06f093eae708fc33e59f8733d7ed9303872
    Author: rhl 
    Date:   Mon Aug 22 19:16:06 2011 +0000
    
        Provided default of LOCAL for ImageOrigin in cctors
    

    271e8097

    commit 271e8097c7ebbadd88d2d43588a80148fdce619a
    Author: Jim Bosch 
    Date:   Mon Nov 19 12:50:21 2012 -0500
    
        Fix up and relocate doxygen for FITS-reading ctors.
    

    Commits in /Users/nate/repos_lsst/afw/

    eea3eb4a

    commit eea3eb4aaa72e0956cce3c5a4bb2c78863540dd3
    Author: Russell Owen 
    Date:   Thu Sep 18 17:23:09 2014 -0700
    
        Respond to review by restoring LOCAL where appropriate.
        Also enhanced documentation in detection.py
    

    1a4ca329

    commit 1a4ca329fc8ac9c646272236d4182d5917845984
    Author: Russell Owen 
    Date:   Wed Sep 10 13:22:32 2014 -0700
    
        Two more instances where the default image origin was LOCAL
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    tests/background.py

    Diff:

    1 ff0c8fc4 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Background Run with: ./Background.py or python >>> import Background; Background.run() """ import math
    36 ff0c8fc4 - import os
    37 c605dfcd + import os.path
    ? +++++
    37 8bf8afcb - import sys
    import unittest import numpy as np import pickle
    41 264e671e - import numpy
    42 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests import lsst.pex.exceptions
    45 034610f9 + from lsst.daf.base import PropertySet
    import lsst.afw.image.imageLib as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom import lsst.afw.display.ds9 as ds9
    49 281f3bde - import eups
    try: type(display) except NameError: display = False
    56 b84187e8 - numpy.random.seed(1)
    56 7cbb2bb9 + AfwdataDir = lsst.utils.getPackageDir("afwdata")
    # ==== summary to currently implemented tests ==== # getPixel: tests basic functionality of getPixel() method (floats) # BackgroundTestImages: tests Laher's afwdata/Statistics/*.fits images (doubles) # testRamp: make sure a constant slope is *exactly* reproduced by the spline model # testParabola: make sure a quadratic map is *well* reproduced by the spline model #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class BackgroundTestCase(unittest.TestCase): """A test case for Background""" def setUp(self): self.val = 10
    71 c9c89e06 - self.image = afwImage.ImageF(afwGeom.Extent2I(100, 200))
    71 034610f9 + self.image = afwImage.ImageF(afwGeom.Box2I(afwGeom.Point2I(1000, 500), afwGeom.Extent2I(100, 200)))
    ? ++++++++++++++++++++++++++++++++++++++++++ + self.image.set(self.val) def tearDown(self): del self.image #self.assertAlmostEqual(mean[1], sd/math.sqrt(image2.getWidth()*image2.getHeight()), 10) def testOddSize(self): ''' Test for ticket #1781 -- without it, in oddly-sized images there is a chunk of pixels on the right/bottom that do not go into the fit and are extrapolated. After this ticket, the subimage boundaries are spread more evenly so the last pixels get fit as well. This slightly strange test case checks that the interpolant is close to the function at the end. I could not think of an interpolant that would fit exactly, so this just puts a limit on the errors. ''' W,H = 2,99 image = afwImage.ImageF(afwGeom.Extent2I(W,H)) bgCtrl = afwMath.BackgroundControl(afwMath.Interpolate.LINEAR) bgCtrl.setNxSample(2) NY = 10 bgCtrl.setNySample(NY) for y in range(H): for x in range(W): B = 89 if y < B: image.set(x,y,y) else: image.set(x,y,B+(y-B)*-1.) #0.5) bobj = afwMath.makeBackground(image, bgCtrl)
    105 264e671e - back = bobj.getImageF()
    ? ^
    105 f31e7b32 + back = bobj.getImageD()
    ? ^ for iy,by in zip([image.get(0,y) for y in range(H)], [ back.get(0,y) for y in range(H)]): self.assertTrue( abs(iy - by) < 5 ) if False: import matplotlib matplotlib.use('Agg') import pylab as plt plt.clf() IY = [image.get(0,y) for y in range(H)] BY = [ back.get(0,y) for y in range(H)] for iy,by in zip(IY,BY): print 'diff', iy-by b = np.linspace(0, H-1, NY+1) plt.plot(IY, 'b-', lw=3, alpha=0.5) plt.plot(BY, 'r-') for y in b: plt.axvline(y) plt.savefig('bg.png') def testgetPixel(self): """Test the getPixel() function""" xcen, ycen = 50, 100 bgCtrl = afwMath.BackgroundControl(10, 10) bgCtrl.setNxSample(5) bgCtrl.setNySample(5) bgCtrl.getStatisticsControl().setNumIter(3) bgCtrl.getStatisticsControl().setNumSigmaClip(3) back = afwMath.makeBackground(self.image, bgCtrl) self.assertEqual(afwMath.cast_BackgroundMI(back).getPixel(xcen, ycen), self.val)
    145 034610f9 + @unittest.skipIf(AfwdataDir is None, "afwdata not setup")
    def testBackgroundTestImages(self): imginfolist = [] #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.05551471441612] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.00295902395123] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.08468385712251] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.00305806663295] ) # cooked to known value #imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 400.0035102188698] ) # cooked to known value imginfolist.append( ["v1_i1_g_m400_s20_f.fits", 399.9912966583894] ) # cooked to known value #imgfiles.append("v1_i1_g_m400_s20_u16.fits") #imgfiles.append("v1_i2_g_m400_s20_f.fits" #imgfiles.append("v1_i2_g_m400_s20_u16.fits") #imgfiles.append("v2_i1_p_m9_f.fits") #imgfiles.append("v2_i1_p_m9_u16.fits") #imgfiles.append("v2_i2_p_m9_f.fits") #imgfiles.append("v2_i2_p_m9_u16.fits")
    162 a4391028 - afwdataDir = eups.productDir("afwdata")
    163 8bf8afcb - if not afwdataDir:
    164 8bf8afcb - print >> sys.stderr, "Skipping testBackgroundTestImages as afwdata is not setup"
    165 8bf8afcb - return
    166 8bf8afcb -
    for imginfo in imginfolist: imgfile, centerValue = imginfo
    171 a4391028 - imgPath = afwdataDir + "/Statistics/" + imgfile
    ? ^^ - - ^^
    167 034610f9 + imgPath = os.path.join(AfwdataDir, "Statistics", imgfile)
    ? ++++ +++++++++ ^ ^ + # get the image and header
    174 264e671e - dimg = afwImage.DecoratedImageF(imgPath)
    ? ^
    170 a4391028 + dimg = afwImage.DecoratedImageD(imgPath)
    ? ^ img = dimg.getImage() fitsHdr = dimg.getMetadata() # the FITS header # get the True values of the mean and stdev reqMean = fitsHdr.getAsDouble("MEANREQ") reqStdev = fitsHdr.getAsDouble("SIGREQ") naxis1 = img.getWidth() naxis2 = img.getHeight() # create a background control object bctrl = afwMath.BackgroundControl(afwMath.Interpolate.AKIMA_SPLINE) bctrl.setNxSample(5) bctrl.setNySample(5) # run the background constructor and call the getPixel() and getImage() functions. backobj = afwMath.makeBackground(img, bctrl) pixPerSubimage = img.getWidth()*img.getHeight()/(bctrl.getNxSample()*bctrl.getNySample()) stdevInterp = reqStdev/math.sqrt(pixPerSubimage) # test getPixel()
    196 2915cbac - testval = afwMath.cast_BackgroundMI(backobj).getPixel(naxis1/2, naxis2/2)
    192 b80fe1d3 + testval = afwMath.cast_BackgroundMI(backobj).getPixel(naxis1//2, naxis2//2)
    ? + + self.assertAlmostEqual(testval/centerValue, 1, places=7) self.assertTrue( abs(testval - reqMean) < 2*stdevInterp ) # test getImage() by checking the center pixel
    201 264e671e - bimg = backobj.getImageF()
    ? ^
    197 ff0c8fc4 + bimg = backobj.getImageD()
    ? ^
    202 2f5e179c - testImgval = bimg.get(naxis1/2, naxis2/2)
    198 b80fe1d3 + testImgval = bimg.get(naxis1//2, naxis2//2)
    ? + + self.assertTrue( abs(testImgval - reqMean) < 2*stdevInterp ) def testRamp(self): # make a ramping image (spline should be exact for linear increasing image nx = 512 ny = 512
    211 264e671e - rampimg = afwImage.ImageF(afwGeom.Extent2I(nx, ny))
    ? ^
    207 c9c89e06 + rampimg = afwImage.ImageD(afwGeom.Extent2I(nx, ny))
    ? ^ dzdx, dzdy, z0 = 0.1, 0.2, 10000.0 for x in range(nx): for y in range(ny): rampimg.set(x, y, dzdx*x + dzdy*y + z0) # check corner, edge, and center pixels bctrl = afwMath.BackgroundControl(10, 10) bctrl.setInterpStyle(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(6) bctrl.setNySample(6) bctrl.getStatisticsControl().setNumSigmaClip(20.0) # something large enough to avoid clipping entirely bctrl.getStatisticsControl().setNumIter(1) backobj = afwMath.makeBackground(rampimg, bctrl)
    227 2f5e179c - xpixels = [0, nx/2, nx - 1]
    223 b80fe1d3 + xpixels = [0, nx//2, nx - 1]
    ? +
    228 2f5e179c - ypixels = [0, ny/2, ny - 1]
    224 b80fe1d3 + ypixels = [0, ny//2, ny - 1]
    ? + for xpix in xpixels: for ypix in ypixels: testval = afwMath.cast_BackgroundMI(backobj).getPixel(xpix, ypix) self.assertAlmostEqual(testval/rampimg.get(xpix, ypix), 1, 6) # Test pickle bg = afwMath.cast_BackgroundMI(backobj) new = pickle.loads(pickle.dumps(bg)) self.assertBackgroundEqual(bg, new) # Check creation of sub-image box = afwGeom.Box2I(afwGeom.Point2I(123, 45), afwGeom.Extent2I(45, 123)) bgImage = bg.getImageF("AKIMA_SPLINE") bgSubImage = afwImage.ImageF(bgImage, box) testImage = bg.getImageF(box, "AKIMA_SPLINE") self.assertEqual(testImage.getXY0(), bgSubImage.getXY0()) self.assertEqual(testImage.getDimensions(), bgSubImage.getDimensions()) self.assertTrue(np.all(testImage.getArray() == bgSubImage.getArray()))
    248 264e671e - def getParabolaImage(self, nx, ny, pars=(1.0e-4, 1.0e-4, 0.1, 0.2, 10.0)):
    244 09d5dad2 + def getParabolaImage(self, nx, ny):
    249 264e671e - parabimg = afwImage.ImageF(afwGeom.Extent2I(nx, ny))
    ? ^
    245 09d5dad2 + parabimg = afwImage.ImageD(afwGeom.Extent2I(nx, ny))
    ? ^
    250 264e671e - d2zdx2, d2zdy2, dzdx, dzdy, z0 = pars # no cross-terms
    ? ^^^^
    246 09d5dad2 + d2zdx2, d2zdy2, dzdx, dzdy, z0 = -1.0e-4, -1.0e-4, 0.1, 0.2, 10000.0 # no cross-terms
    ? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ for x in range(nx): for y in range(ny): parabimg.set(x, y, d2zdx2*x*x + d2zdy2*y*y + dzdx*x + dzdy*y + z0) return parabimg
    252 034610f9 + @unittest.skipIf(AfwdataDir is None, "afwdata not setup")
    def testTicket987(self): """This code used to abort; so the test is that it doesn't"""
    258 4d2a5dc2 - afwdataDir = eups.productDir("afwdata")
    259 4d2a5dc2 - if not afwdataDir:
    260 4d2a5dc2 - print >> sys.stderr, "Skipping testTicket987 as afwdata is not setup"
    261 4d2a5dc2 - return
    262 4d2a5dc2 -
    263 5b522953 - imagePath = os.path.join(afwdataDir, "DC3a-Sim", "sci", "v5-e0", "v5-e0-c011-a00.sci.fits")
    ? ^
    255 034610f9 + imagePath = os.path.join(AfwdataDir, "DC3a-Sim", "sci", "v5-e0", "v5-e0-c011-a00.sci.fits")
    ? ^ mimg = afwImage.MaskedImageF(imagePath) binsize = 512 bctrl = afwMath.BackgroundControl("NATURAL_SPLINE") ### Adding this line solves the problem ### # note: by default undersampleStyle is THROW_EXCEPTION bctrl.setUndersampleStyle(afwMath.REDUCE_INTERP_ORDER) ################################################ nx = int(mimg.getWidth()/binsize) + 1 ny = int(mimg.getHeight()/binsize) + 1 #print 'Binning', nx, ny bctrl.setNxSample(nx) bctrl.setNySample(ny) image = mimg.getImage() backobj = afwMath.makeBackground(image, bctrl) image -= backobj.getImageF() def testTicket1781(self): # make an unusual-sized image nx = 526 ny = 154 parabimg = self.getParabolaImage(nx, ny) bctrl = afwMath.BackgroundControl(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(16) bctrl.setNySample(4) bctrl.getStatisticsControl().setNumSigmaClip(10.0) bctrl.getStatisticsControl().setNumIter(1) backobj = afwMath.makeBackground(parabimg, bctrl)
    289 034610f9 + if False:
    297 9d2b6e90 - #parabimg.writeFits('in.fits')
    ? ^
    290 034610f9 + parabimg.writeFits('in.fits')
    ? ^^^^
    298 9d2b6e90 - #backobj.getImageF().writeFits('out.fits')
    ? ^
    291 034610f9 + backobj.getImageF().writeFits('out.fits')
    ? ^^^^
    299 09d5dad2 -
    def testParabola(self): # make an image which varies parabolicly (spline should be exact for 2rd order polynomial) nx = 512 ny = 512 parabimg = self.getParabolaImage(nx, ny) # check corner, edge, and center pixels bctrl = afwMath.BackgroundControl(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(24) bctrl.setNySample(24) bctrl.getStatisticsControl().setNumSigmaClip(10.0) bctrl.getStatisticsControl().setNumIter(1) backobj = afwMath.makeBackground(parabimg, bctrl) # debug
    318 264e671e - #bimg = backobj.getImageF()
    ? ^
    310 2eb9dac3 + #bimg = backobj.getImageD()
    ? ^ #ds9.mtv(parabimg) #ds9.mtv(bimg, frame=1) #parabimg.writeFits("a.fits") #bimg.writeFits("b.fits") segmentCenter = int(0.5*nx/bctrl.getNxSample())
    325 2f5e179c - xpixels = [segmentCenter, nx/2, nx - segmentCenter]
    317 b80fe1d3 + xpixels = [segmentCenter, nx//2, nx - segmentCenter]
    ? +
    326 2f5e179c - ypixels = [segmentCenter, ny/2, ny - segmentCenter]
    318 b80fe1d3 + ypixels = [segmentCenter, ny//2, ny - segmentCenter]
    ? + for xpix in xpixels: for ypix in ypixels: testval = afwMath.cast_BackgroundMI(backobj).getPixel(bctrl.getInterpStyle(), xpix, ypix) realval = parabimg.get(xpix, ypix) #print "Parab: ", xpix, ypix, realval, -(testval - realval) # quadratic terms skew the averages of the subimages and the clipped mean for # a subimage != value of center pixel. 1/20 counts on a 10000 count sky # is a fair (if arbitrary) test. self.assertTrue( abs(testval - realval) < 0.5 )
    329 034610f9 + @unittest.skipIf(AfwdataDir is None, "afwdata not setup")
    def testCFHT_oldAPI(self): """Test background subtraction on some real CFHT data"""
    340 8bf8afcb - afwdataDir = eups.productDir("afwdata")
    341 8bf8afcb - if not afwdataDir:
    342 8bf8afcb - print >> sys.stderr, "Skipping testCFHT as afwdata is not setup"
    343 8bf8afcb - return
    344 8bf8afcb -
    345 8bf8afcb - mi = afwImage.MaskedImageF(os.path.join(afwdataDir,
    ? ^
    333 034610f9 + mi = afwImage.MaskedImageF(os.path.join(AfwdataDir,
    ? ^ "CFHT", "D4", "cal-53535-i-797722_1.fits")) mi = mi.Factory(mi, afwGeom.Box2I(afwGeom.Point2I(32, 2), afwGeom.Point2I(2079, 4609)), afwImage.LOCAL) bctrl = afwMath.BackgroundControl(afwMath.Interpolate.AKIMA_SPLINE) bctrl.setNxSample(16) bctrl.setNySample(16) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) backobj = afwMath.makeBackground(mi.getImage(), bctrl) if display: ds9.mtv(mi, frame = 0) im = mi.getImage() im -= backobj.getImageF() if display: ds9.mtv(mi, frame = 1)
    365 3bc167f3 -
    353 034610f9 + def getCfhtImage(self):
    354 034610f9 + """Get a portion of a CFHT image as a MaskedImageF
    355 034610f9 + """
    356 034610f9 + bbox = afwGeom.Box2I(afwGeom.Point2I(500, 2000), afwGeom.Point2I(2079, 4609))
    357 034610f9 + imagePath = os.path.join(AfwdataDir, "CFHT", "D4", "cal-53535-i-797722_1.fits")
    358 034610f9 + return afwImage.MaskedImageF(imagePath, PropertySet(), bbox)
    359 034610f9 +
    360 034610f9 + @unittest.skipIf(AfwdataDir is None, "afwdata not setup")
    361 034610f9 + def testXY0(self):
    362 034610f9 + """Test fitting the background to an image with nonzero xy0
    363 034610f9 +
    364 034610f9 + The statsImage and background image should not vary with xy0
    365 034610f9 + """
    366 034610f9 + bgImageList = [] # list of background images, one per xy0
    367 034610f9 + statsImageList = [] # list of stats images, one per xy0
    368 034610f9 + for xy0 in (afwGeom.Point2I(0, 0), afwGeom.Point2I(-100, -999), afwGeom.Point2I(1000, 500)):
    369 034610f9 + mi = self.getCfhtImage()
    370 034610f9 + mi.setXY0(xy0)
    371 034610f9 +
    372 034610f9 + bctrl = afwMath.BackgroundControl(mi.getWidth()//128, mi.getHeight()//128)
    373 034610f9 + backobj = afwMath.makeBackground(mi.getImage(), bctrl)
    374 034610f9 + bgImage = backobj.getImageF()
    375 034610f9 + self.assertEqual(bgImage.getBBox(), mi.getBBox())
    376 034610f9 + bgImageList.append(bgImage)
    377 034610f9 +
    378 034610f9 + statsImage = afwMath.cast_BackgroundMI(backobj).getStatsImage()
    379 034610f9 + statsImageList.append(statsImage)
    380 034610f9 +
    381 034610f9 + # changing the bounding box should make no difference to the pixel values,
    382 034610f9 + # so compare pixels using exact equality
    383 034610f9 + for bgImage in bgImageList[1:]:
    384 034610f9 + self.assertTrue(np.all(bgImage.getArray() == bgImageList[0].getArray()))
    385 034610f9 + for statsImage in statsImageList[1:]:
    386 034610f9 + for i in range(3):
    387 034610f9 + self.assertTrue(np.all(statsImage.getArrays()[i] == statsImageList[0].getArrays()[i]))
    388 034610f9 +
    389 034610f9 + @unittest.skipIf(AfwdataDir is None, "afwdata not setup")
    390 034610f9 + def testSubImage(self):
    391 034610f9 + """Test getImage on a subregion of the full background image
    392 034610f9 +
    393 034610f9 + Using real image data is a cheap way to get a variable background
    394 034610f9 + """
    395 034610f9 + mi = self.getCfhtImage()
    396 149224f2 +
    397 034610f9 + bctrl = afwMath.BackgroundControl(mi.getWidth()//128, mi.getHeight()//128)
    398 034610f9 + backobj = afwMath.makeBackground(mi.getImage(), bctrl)
    399 034610f9 + subBBox = afwGeom.Box2I(afwGeom.Point2I(1000, 3000), afwGeom.Extent2I(100, 100))
    400 149224f2 +
    401 034610f9 + bgFullImage = backobj.getImageF()
    402 034610f9 + self.assertEqual(bgFullImage.getBBox(), mi.getBBox())
    403 034610f9 +
    404 034610f9 + subFullArr = afwImage.ImageF(bgFullImage, subBBox).getArray()
    405 034610f9 +
    406 034610f9 + bgSubImage = backobj.getImageF(subBBox, bctrl.getInterpStyle())
    407 034610f9 + subArr = bgSubImage.getArray()
    408 034610f9 +
    409 034610f9 + # the pixels happen to be identical but it is safer not to rely on that; close is good enough
    410 034610f9 + self.assertTrue(np.allclose(subArr, subFullArr))
    411 034610f9 +
    412 034610f9 + @unittest.skipIf(AfwdataDir is None, "afwdata not setup")
    def testCFHT(self): """Test background subtraction on some real CFHT data"""
    415 034610f9 + mi = self.getCfhtImage()
    368 149224f2 -
    369 149224f2 - afwdataDir = eups.productDir("afwdata")
    370 149224f2 - if not afwdataDir:
    371 149224f2 - print >> sys.stderr, "Skipping testCFHT as afwdata is not setup"
    372 149224f2 - return
    373 149224f2 -
    374 149224f2 - mi = afwImage.MaskedImageF(os.path.join(afwdataDir,
    375 5b522953 - "CFHT", "D4", "cal-53535-i-797722_1.fits"))
    376 149224f2 - mi = mi.Factory(mi, afwGeom.Box2I(afwGeom.Point2I(32, 2), afwGeom.Point2I(2079, 4609)), afwImage.LOCAL)
    bctrl = afwMath.BackgroundControl(mi.getWidth()//128, mi.getHeight()//128) bctrl.getStatisticsControl().setNumSigmaClip(3.0) bctrl.getStatisticsControl().setNumIter(2) backobj = afwMath.makeBackground(mi.getImage(), bctrl) if display: ds9.mtv(mi, frame = 0) im = mi.getImage() im -= backobj.getImageF("AKIMA_SPLINE") if display: ds9.mtv(mi, frame = 1) statsImage = afwMath.cast_BackgroundMI(backobj).getStatsImage() if display:
    395 e01c5df9 - ds9.mtv(backobj.getStatsImage(), frame=2)
    ? ^^^^^^^^^^^^ --
    434 034610f9 + ds9.mtv(statsImage, frame=2)
    ? ^
    396 e01c5df9 - ds9.mtv(backobj.getStatsImage().getVariance(), frame=3)
    ? ^^^^^^^^^^^^ --
    435 034610f9 + ds9.mtv(statsImage.getVariance(), frame=3)
    ? ^ def testUndersample(self): """Test how the program handles nx,ny being too small for requested interp style.""" # make an image nx = 64 ny = 64
    404 264e671e - img = afwImage.ImageF(afwGeom.Extent2I(nx, ny))
    ? ^
    443 c9c89e06 + img = afwImage.ImageD(afwGeom.Extent2I(nx, ny))
    ? ^ # make a background control object bctrl = afwMath.BackgroundControl(10, 10) bctrl.setInterpStyle(afwMath.Interpolate.CUBIC_SPLINE) bctrl.setNxSample(3) bctrl.setNySample(3) if False: # INCREASE_NXNYSAMPLE is no longer supported post #2074 bctrl.setNxSample(2) bctrl.setNySample(2) # see if it adjusts the nx,ny values up to 3x3 bctrl.setUndersampleStyle(afwMath.INCREASE_NXNYSAMPLE) backobj = afwMath.makeBackground(img, bctrl) self.assertEqual(backobj.getBackgroundControl().getNxSample(), 3) self.assertEqual(backobj.getBackgroundControl().getNySample(), 3) # put nx,ny back to 2 and see if it adjusts the interp style down to linear bctrl.setNxSample(2) bctrl.setNySample(2) bctrl.setUndersampleStyle("REDUCE_INTERP_ORDER") backobj = afwMath.makeBackground(img, bctrl) backobj.getImageF() # Need to interpolate background to discover what we actually needed self.assertEqual(backobj.getAsUsedInterpStyle(), afwMath.Interpolate.LINEAR) # put interp style back up to cspline and see if it throws an exception bctrl.setUndersampleStyle("THROW_EXCEPTION") def tst(img, bctrl): backobj = afwMath.makeBackground(img, bctrl) backobj.getImageF("CUBIC_SPLINE") # only now do we see that we have too few points
    434 1d43230a - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    473 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError,
    ? ^^ ^ ^^ ^ tst, img, bctrl) def testOnlyOneGridCell(self): """Test how the program handles nxSample,nySample being 1x1.""" # try a ramping image ... has an easy analytic solution nx = 64 ny = 64
    444 264e671e - img = afwImage.ImageF(afwGeom.Extent2I(nx, ny), 10)
    ? ^
    483 c9c89e06 + img = afwImage.ImageD(afwGeom.Extent2I(nx, ny), 10)
    ? ^ dzdx, dzdy, z0 = 0.1, 0.2, 10000.0 mean = z0 + dzdx*(nx - 1)/2 + dzdy*(ny - 1)/2 # the analytic solution for x in range(nx): for y in range(ny): img.set(x, y, dzdx*x + dzdy*y + z0) # make a background control object bctrl = afwMath.BackgroundControl(10, 10) bctrl.setInterpStyle(afwMath.Interpolate.CONSTANT) bctrl.setNxSample(1) bctrl.setNySample(1) bctrl.setUndersampleStyle(afwMath.THROW_EXCEPTION) backobj = afwMath.makeBackground(img, bctrl)
    460 392cdeba - xpixels = [0, nx/2, nx - 1]
    499 b80fe1d3 + xpixels = [0, nx//2, nx - 1]
    ? +
    461 392cdeba - ypixels = [0, ny/2, ny - 1]
    500 b80fe1d3 + ypixels = [0, ny//2, ny - 1]
    ? + for xpix in xpixels: for ypix in ypixels: testval = afwMath.cast_BackgroundMI(backobj).getPixel(bctrl.getInterpStyle(), xpix, ypix) self.assertAlmostEqual(testval/mean, 1) def testTicket1681OffByOne(self): if False: # doesn't seem to actually test anything, and writes b?im.fits im = afwImage.ImageF(40, 40); im.set(5, 6, 100); nx, ny = im.getWidth()//2, im.getHeight()//2 print nx, ny bctrl = afwMath.BackgroundControl("LINEAR", nx, ny) bctrl.setStatisticsProperty(afwMath.MEAN) bkd = afwMath.makeBackground(im, bctrl) bim = bkd.getImageF() im.writeFits("im.fits") bim.writeFits("bim.fits") def testAdjustLevel(self): """Test that we can adjust a background level""" sky = 100 im = afwImage.ImageF(40, 40); im.set(sky); nx, ny = im.getWidth()//2, im.getHeight()//2 bctrl = afwMath.BackgroundControl("LINEAR", nx, ny) bkd = afwMath.makeBackground(im, bctrl) self.assertEqual(afwMath.makeStatistics(bkd.getImageF(), afwMath.MEAN).getValue(), sky) delta = 123 bkd += delta self.assertEqual(afwMath.makeStatistics(bkd.getImageF(), afwMath.MEAN).getValue(), sky + delta) bkd -= delta self.assertEqual(afwMath.makeStatistics(bkd.getImageF(), afwMath.MEAN).getValue(), sky) def testNaNFromMaskedImage(self): """Check that an extensively masked image doesn't lead to NaNs in the background estimation""" image = afwImage.MaskedImageF(800, 800) msk = image.getMask() bbox = afwGeom.BoxI(afwGeom.PointI(560, 0), afwGeom.PointI(799, 335)) smsk = msk.Factory(msk, bbox) smsk.set(msk.getPlaneBitMask("DETECTED")) binSize = 256 nx = image.getWidth()//binSize + 1 ny = image.getHeight()//binSize + 1 sctrl = afwMath.StatisticsControl() sctrl.setAndMask(reduce(lambda x, y: x | image.getMask().getPlaneBitMask(y), ['EDGE', 'DETECTED', 'DETECTED_NEGATIVE'], 0x0)) bctrl = afwMath.BackgroundControl(nx, ny, sctrl, "MEANCLIP") bkgd = afwMath.makeBackground(image, bctrl) bkgdImage = bkgd.getImageF("NATURAL_SPLINE", "THROW_EXCEPTION") if display: ds9.mtv(image) ds9.mtv(bkgdImage, frame=1) self.assertFalse(np.isnan(bkgdImage.get(0,0))) # Check that the non-string API works too bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.THROW_EXCEPTION) def testBadAreaFailsSpline(self): """Check that a NaN in the stats image doesn't cause spline interpolation to fail (#2734)""" image = afwImage.ImageF(15, 9) for y in range(image.getHeight()): for x in range(image.getWidth()): image.set(x, y, 1 + 2*y) # n.b. linear, which is what the interpolation will fall back to # Set the right corner to NaN. This will mean that we have too few points for a spline interpolator binSize = 3 image[-binSize:, -binSize:] = np.nan nx = image.getWidth()//binSize ny = image.getHeight()//binSize sctrl = afwMath.StatisticsControl() bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(image, bctrl) if display: ds9.mtv(image) ds9.mtv(afwMath.cast_BackgroundMI(bkgd).getStatsImage(), frame=1) # # Should throw if we don't permit REDUCE_INTERP_ORDER #
    550 6a926a3a - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.OutOfRangeException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    589 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.OutOfRangeError,
    ? ^^ ^ ^^ ^ bkgd.getImageF, afwMath.Interpolate.NATURAL_SPLINE) # # The interpolation should fall back to linear for the right part of the image # where the NaNs don't permit spline interpolation (n.b. this happens to be exact) # bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.REDUCE_INTERP_ORDER) if display: ds9.mtv(bkgdImage, frame=2) image -= bkgdImage self.assertEqual(afwMath.makeStatistics(image, afwMath.MEAN).getValue(), 0.0) def testBadPatch(self): """Test that a large bad patch of an image doesn't cause an absolute failure""" initialValue = 20 mi = afwImage.MaskedImageF(500, 200) mi.set((initialValue, 0x0, 1.0)) im = mi.getImage() im[0:200, :] = np.nan del im msk = mi.getMask() badBits = msk.getPlaneBitMask(['EDGE', 'DETECTED', 'DETECTED_NEGATIVE']) msk[0:400, :] |= badBits del msk if display: ds9.mtv(mi, frame=0) sctrl = afwMath.StatisticsControl() sctrl.setAndMask(badBits) nx, ny = 17, 17 bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(mi, bctrl) statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage() if display: ds9.mtv(statsImage, frame=1) # the test is that this doesn't fail if the bug (#2297) is fixed bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.REDUCE_INTERP_ORDER) self.assertEqual(np.mean(bkgdImage[0:100, 0:100].getArray()), initialValue) if display: ds9.mtv(bkgdImage, frame=2) # # Check that we can fix the NaNs in the statsImage #
    599 122f849c - defaultValue = 10
    sim = statsImage.getImage().getArray()
    601 122f849c - sim[np.isnan(sim)] = defaultValue # replace NaN by defaultValue
    ? ^^^ - - ^^^ - -
    639 d31fcd9b + sim[np.isnan(sim)] = initialValue # replace NaN by initialValue
    ? ^^^^^ ^^^^^ bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.REDUCE_INTERP_ORDER)
    604 122f849c - self.assertEqual(np.mean(bkgdImage[0:100, 0:100].getArray()), defaultValue)
    ? ^^^ - -
    642 d31fcd9b + self.assertAlmostEqual(np.mean(bkgdImage[0:100, 0:100].getArray(), dtype=np.float64), initialValue)
    ? ++++++ ++++++++++++++++++ ^^^^^ def testBadRows(self): """Test that a bad set of rows in an image doesn't cause a failure""" initialValue = 20 mi = afwImage.MaskedImageF(500, 200) mi.set((initialValue, 0x0, 1.0)) im = mi.getImage() im[:, 0:100] = np.nan del im msk = mi.getMask() badBits = msk.getPlaneBitMask(['EDGE', 'DETECTED', 'DETECTED_NEGATIVE']) msk[0:400, :] |= badBits del msk if display: ds9.mtv(mi, frame=0) sctrl = afwMath.StatisticsControl() sctrl.setAndMask(badBits) nx, ny = 17, 17 bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(mi, bctrl) statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage() if display: ds9.mtv(statsImage, frame=1) # the test is that this doesn't fail if the bug (#2297) is fixed bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.REDUCE_INTERP_ORDER) self.assertEqual(np.mean(bkgdImage[0:100, 0:100].getArray()), initialValue) if display: ds9.mtv(bkgdImage, frame=2) def testBadImage(self): """Test that an entirely bad image doesn't cause an absolute failure""" initialValue = 20 mi = afwImage.MaskedImageF(500, 200) # # Check that no good values don't crash (they return NaN), and that a single good value # is enough to redeem the entire image # for pix00 in [np.nan, initialValue]: mi.getImage()[:] = np.nan mi.getImage()[0, 0] = pix00 sctrl = afwMath.StatisticsControl() nx, ny = 17, 17 bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(mi, bctrl)
    657 ecc83dad - statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage()
    ? -------------
    695 034610f9 + afwMath.cast_BackgroundMI(bkgd).getStatsImage()
    # the test is that this doesn't fail if the bug (#2297) is fixed bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.REDUCE_INTERP_ORDER) val = np.mean(bkgdImage[0:100, 0:100].getArray()) if np.isfinite(pix00): self.assertEqual(val, pix00) else: self.assertTrue(np.isnan(val)) def testBackgroundFromStatsImage(self): """Check that we can rebuild a Background from a BackgroundMI.getStatsImage()""" bgCtrl = afwMath.BackgroundControl(10, 10) bkgd = afwMath.cast_BackgroundMI(afwMath.makeBackground(self.image, bgCtrl)) interpStyle = afwMath.Interpolate.AKIMA_SPLINE undersampleStyle = afwMath.REDUCE_INTERP_ORDER bkgdImage = bkgd.getImageF(interpStyle, undersampleStyle) self.assertEqual(np.mean(bkgdImage.getArray()), self.val) self.assertEqual(interpStyle, bkgd.getAsUsedInterpStyle()) self.assertEqual(undersampleStyle, bkgd.getAsUsedUndersampleStyle()) # # OK, we have our background. Make a copy # bkgd2 = afwMath.BackgroundMI(self.image.getBBox(), bkgd.getStatsImage())
    684 2b4b80a5 - del bkgd; bkgd = None # we should be handling the memory correctly, but let's check
    ? -------------
    722 034610f9 + del bkgd # we should be handling the memory correctly, but let's check
    bkgdImage2 = bkgd2.getImageF(interpStyle) self.assertEqual(np.mean(bkgdImage2.getArray()), self.val) def testBackgroundList(self): """Test that a BackgroundLists behaves like a list""" bgCtrl = afwMath.BackgroundControl(10, 10) interpStyle = afwMath.Interpolate.AKIMA_SPLINE undersampleStyle = afwMath.REDUCE_INTERP_ORDER
    694 13cd7b6a - approxStyle = afwMath.ApproximateControl.UNKNOWN
    695 264e671e - approxOrderX = 0
    696 264e671e - approxOrderY = 0
    backgroundList = afwMath.BackgroundList()
    699 c16ef84d - backImage = afwImage.ImageF(self.image.getDimensions())
    for i in range(2): bkgd = afwMath.makeBackground(self.image, bgCtrl) if i == 0:
    703 13cd7b6a - # no need to call getImage
    704 264e671e - backgroundList.append((bkgd, interpStyle, undersampleStyle,
    737 c16ef84d + backgroundList.append((bkgd, interpStyle, undersampleStyle,)) # no need to call getImage
    ? +++++++++++++++++++++++++++++
    705 264e671e - approxStyle, approxOrderX, approxOrderY))
    else: backgroundList.append(bkgd) # Relies on having called getImage; deprecated def assertBackgroundList(bgl): self.assertEqual(len(bgl), 2) # check that len() works for a in bgl: # check that we can iterate pass
    713 264e671e - self.assertEqual(len(bgl[0]), 6) # check that we can index
    ? ^
    745 65b8e9b5 + self.assertEqual(len(bgl[0]), 3) # check that we can index
    ? ^
    746 65b8e9b5 + self.assertEqual(len(bgl[1]), 3) # check that we always have a tuple (bkgd, interp, under)
    714 264e671e - # check that we always have a tuple (bkgd, interp, under, approxStyle, orderX, orderY)
    715 264e671e - self.assertEqual(len(bgl[1]), 6)
    assertBackgroundList(backgroundList) # Check pickling new = pickle.loads(pickle.dumps(backgroundList)) assertBackgroundList(new) self.assertEqual(len(new), len(backgroundList)) for i, j in zip(new, backgroundList): self.assertBackgroundEqual(i[0], j[0]) self.assertEqual(i[1:], j[1:]) def assertBackgroundEqual(self, lhs, rhs): lhsStats, rhsStats = lhs.getStatsImage(), rhs.getStatsImage() self.assertEqual(lhs.getImageBBox(), rhs.getImageBBox()) self.assertTrue(np.all(lhsStats.getImage().getArray() == rhsStats.getImage().getArray())) self.assertTrue(np.all(lhsStats.getMask().getArray() == rhsStats.getMask().getArray())) self.assertTrue(np.all(lhsStats.getVariance().getArray() == rhsStats.getVariance().getArray()))
    734 264e671e -
    735 264e671e - def testApproximate(self):
    736 264e671e - """Test I/O for BackgroundLists with Approximate"""
    737 264e671e -
    738 264e671e - # approx and interp should be very close, but not the same
    739 264e671e - img = self.getParabolaImage(256, 256)
    740 264e671e -
    741 264e671e - # try regular interpolated image (the default)
    742 264e671e - bgCtrl = afwMath.BackgroundControl(6, 6)
    743 264e671e - bgCtrl.setInterpStyle(afwMath.Interpolate.AKIMA_SPLINE)
    744 264e671e - bgCtrl.setUndersampleStyle(afwMath.REDUCE_INTERP_ORDER)
    745 264e671e - bkgd = afwMath.makeBackground(img, bgCtrl)
    746 264e671e - interpImage = bkgd.getImageF()
    747 264e671e - bglInterp = afwMath.BackgroundList()
    748 264e671e - bglInterp.append(bkgd)
    749 264e671e - bgiFile = "tests/bgInterp.fits"
    750 264e671e - bglInterp.writeFits(bgiFile)
    751 264e671e -
    752 264e671e - # try an approx background
    753 264e671e - approxStyle = afwMath.ApproximateControl.CHEBYSHEV
    754 264e671e - approxOrder = 2
    755 264e671e - actrl = afwMath.ApproximateControl(approxStyle, approxOrder)
    756 264e671e - bkgd.getBackgroundControl().setApproximateControl(actrl)
    757 264e671e - approxImage = bkgd.getImageF()
    758 264e671e - bglApprox = afwMath.BackgroundList()
    759 264e671e - bglApprox.append(bkgd)
    760 264e671e - bgaFile = "tests/bgApprox.fits"
    761 264e671e - bglApprox.writeFits(bgaFile)
    762 264e671e -
    763 264e671e - # take a difference and make sure the two are very similar
    764 264e671e - interpNp = interpImage.getArray()
    765 264e671e - diff = numpy.abs(interpNp - approxImage.getArray())/interpNp
    766 264e671e -
    767 264e671e - # the image and interp/approx parameters are chosen so these limits
    768 264e671e - # will be greater than machine precision for float. The two methods
    769 264e671e - # should be measurably different (so we know we're not just getting the
    770 264e671e - # same thing from the getImage() method. But they should be very close
    771 264e671e - # since they're both doing the same sort of thing.
    772 264e671e - tolSame = 1.0e-3 # should be the same to this order
    773 264e671e - tolDiff = 1.0e-4 # should be different here
    774 264e671e - self.assertLess(diff.max(), tolSame)
    775 264e671e - self.assertGreater(diff.max(), tolDiff)
    776 264e671e - #print "Interp/Approx diff min and max:", diff.min(), diff.max()
    777 264e671e -
    778 264e671e - # now see if we can reload them from files and get the same images we wrote
    779 264e671e - interpImage2 = afwMath.BackgroundList().readFits(bgiFile).getImage()
    780 264e671e - approxImage2 = afwMath.BackgroundList().readFits(bgaFile).getImage()
    781 264e671e -
    782 264e671e - idiff = interpImage.getArray() - interpImage2.getArray()
    783 264e671e - adiff = approxImage.getArray() - approxImage2.getArray()
    784 264e671e -
    785 264e671e - self.assertEqual(idiff.max(), 0.0)
    786 264e671e - self.assertEqual(adiff.max(), 0.0)
    787 264e671e - #print "Reloaded interp and approx diff max:", idiff.max(), adiff.max()
    788 264e671e -
    def testBackgroundListIO(self): """Test I/O for BackgroundLists""" bgCtrl = afwMath.BackgroundControl(10, 10) interpStyle = afwMath.Interpolate.AKIMA_SPLINE undersampleStyle = afwMath.REDUCE_INTERP_ORDER
    794 b84187e8 - approxOrderX = 6
    795 b84187e8 - approxOrderY = 6
    797 b84187e8 - im = self.image.Factory(self.image, self.image.getBBox(afwImage.PARENT))
    798 b84187e8 - arr = im.getArray()
    799 b84187e8 - arr += numpy.random.normal(size=(im.getHeight(),im.getWidth()))
    800 b84187e8 -
    801 b84187e8 - for astyle in afwMath.ApproximateControl.UNKNOWN, afwMath.ApproximateControl.CHEBYSHEV:
    802 b84187e8 -
    803 b84187e8 - actrl = afwMath.ApproximateControl(astyle, approxOrderX)
    804 b84187e8 - bgCtrl.setApproximateControl(actrl)
    805 b84187e8 -
    806 b84187e8 - backgroundList = afwMath.BackgroundList()
    ? ----
    771 883e4114 + backgroundList = afwMath.BackgroundList()
    807 b84187e8 - backImage = afwImage.ImageF(im.getDimensions())
    ? ----
    772 2b4b80a5 + backImage = afwImage.ImageF(self.image.getDimensions())
    ? +++++ +++
    808 b84187e8 - for i in range(2):
    ? ----
    773 2b4b80a5 + for i in range(2):
    809 b84187e8 - bkgd = afwMath.makeBackground(im, bgCtrl)
    ? ----
    774 2b4b80a5 + bkgd = afwMath.makeBackground(self.image, bgCtrl)
    ? +++++ +++
    810 b84187e8 - if i == 0:
    ? ----
    775 883e4114 + if i == 0:
    811 b84187e8 - # no need to call getImage
    812 b84187e8 - backgroundList.append((bkgd, interpStyle, undersampleStyle,
    ? ----
    776 883e4114 + backgroundList.append((bkgd, interpStyle, undersampleStyle,)) # no need to call getImage
    ? +++++++++++++++++++++++++++++
    813 b84187e8 - astyle, approxOrderX, approxOrderY))
    814 b84187e8 - else:
    ? ----
    777 883e4114 + else:
    815 b84187e8 - backgroundList.append(bkgd) # Relies on having called getImage; deprecated
    ? ----
    778 883e4114 + backgroundList.append(bkgd) # Relies on having called getImage; deprecated
    817 b84187e8 - backImage += bkgd.getImageF(interpStyle, undersampleStyle)
    ? ----
    780 883e4114 + backImage += bkgd.getImageF(interpStyle, undersampleStyle)
    782 c605dfcd + with utilsTests.getTempFilePath(".fits") as fileName:
    819 b84187e8 - fileName = "backgroundList.fits"
    820 b84187e8 - try:
    821 b84187e8 - backgroundList.writeFits(fileName)
    ? ----
    783 883e4114 + backgroundList.writeFits(fileName)
    823 b84187e8 - backgrounds = afwMath.BackgroundList.readFits(fileName)
    ? ----
    785 883e4114 + backgrounds = afwMath.BackgroundList.readFits(fileName)
    824 b84187e8 - finally:
    825 b84187e8 - if os.path.exists(fileName):
    826 b84187e8 - os.unlink(fileName)
    img = backgrounds.getImage() # # Check that the read-back image is identical to that generated from the backgroundList # round-tripped to disk # backImage -= img
    834 b84187e8 -
    793 c605dfcd +
    self.assertEqual(np.min(backImage.getArray()), 0.0) self.assertEqual(np.max(backImage.getArray()), 0.0)
    837 2b4b80a5 -
    def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(BackgroundTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests"""
    809 034610f9 + if AfwdataDir is None:
    810 034610f9 + print "Warning: afwdata is not setup so some tests will be skipped"
    utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    281f3bde

    commit 281f3bde5519e928d8e438c4350c1505295322af
    Author: rhl 
    Date:   Fri Jan 16 02:44:44 2009 +0000
    
        Add an example of subtracting an image from real data;  no tests that it actually worked; #0
    

    09d5dad2

    commit 09d5dad20b363c3bdb90908c652cb8d6a2408428
    Author: dstn 
    Date:   Sun Nov 6 18:56:50 2011 +0000
    
        manually extrapolate to 2nd order (Jim Bosch reports that new GSL versions refuse to extrapolate in the interpolation routines)
    

    392cdeba

    commit 392cdebac27de4d9b19e8b8c6069780b4a4cf4ac
    Author: bick 
    Date:   Sat Oct 31 23:33:22 2009 +0000
    
        #987 Added special case code to handle when nx,nySample is 1x1.
    

    4d2a5dc2

    commit 4d2a5dc2ed6820bbdc3a913322eb848071c1e439
    Author: Robert Lupton the Good 
    Date:   Fri Oct 12 14:46:27 2012 -0400
    
        No longer interesting as an example; moved to tests/background.py as testTicket987
    

    c16ef84d

    commit c16ef84dbc57a40a79480b3b277261cb6bbe22c6
    Author: Robert Lupton the Good 
    Date:   Wed Apr 3 16:45:18 2013 -0400
    
        Cleanups as proposed by REO in code review for #2732
    

    149224f2

    commit 149224f23c8fd769e4a40a63b07c5b586b77d503
    Author: Robert Lupton the Good 
    Date:   Wed Oct 10 12:34:20 2012 -0400
    
        Moved generation of interpolated background images from ctor to getImage()
    

    9d2b6e90

    commit 9d2b6e90744c1f64be153ca8bad2b17ea7046452
    Author: Paul Price 
    Date:   Wed Jan 18 16:25:47 2012 -0500
    
        Don't write FITS files unnecessarily.
    

    6a926a3a

    commit 6a926a3aa6122a4241f38f924414eb07d867062d
    Author: Robert Lupton the Good 
    Date:   Wed Mar 6 21:50:34 2013 -0500
    
        Added more complete testing of the fixed functionality
    

    2f5e179c

    commit 2f5e179ca9f56a84d41cd5a8f8dbabc3f7141d46
    Merge: dfdd78a deba9f6
    Author: bick 
    Date:   Wed Oct 7 16:41:35 2009 +0000
    
        #955 Updated against afw/trunk.
    

    a4391028

    commit a43910287bbfe15fdafc2112c5086a72d6697f6d
    Author: bick 
    Date:   Thu Nov 19 00:14:28 2009 +0000
    
        On afw/trunk/.  Attended to some pylint errors and added examples/ to SConstruct install.
    

    ff0c8fc4

    commit ff0c8fc4d3fb8d3e18c90ccf5d5efac743619b4a
    Author: bick 
    Date:   Wed Jan 14 16:50:33 2009 +0000
    
        Merging ticket 395 (image statistics and background estimation) on to trunk.
    

    5b522953

    commit 5b522953c3a80b54c7832793f353c7e00d3b5ea7
    Author: Jim Bosch 
    Date:   Tue Nov 20 14:53:52 2012 -0500
    
        Convert tests to use MEFs (requires afwdata update), remove a worthless one.
    

    13cd7b6a

    commit 13cd7b6a7bcaaed466148aa40fa2db5fc4809d28
    Author: Steven Bickerton 
    Date:   Thu Oct 16 19:23:42 2014 +0900
    
        Allow background to persist info about approx
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    3bc167f3

    commit 3bc167f3f9f9451bb0043df4c06c98189bb88ad9
    Author: bick 
    Date:   Fri Oct 30 17:58:29 2009 +0000
    
        #987 Added code to handle case where nx,ny in background are too small for requested interpolation style.
    

    2915cbac

    commit 2915cbac8ebf464fe28a3c0f2752a8211d9be37b
    Author: Robert Lupton the Good 
    Date:   Tue Oct 16 13:19:16 2012 -0400
    
        Changed names of Background classes
        
        BackgroundBase -> Background
        Background     -> BackgroundMI
    

    122f849c

    commit 122f849c93f149f80297366a015975120da80231
    Author: Robert Lupton the Good 
    Date:   Thu Apr 18 17:46:57 2013 -0400
    
        Added test for large-areas-of-masked-pixels-and/or-NaNs (#2297)
    

    e01c5df9

    commit e01c5df9ccfd5163f07d1910f164ef14e1cae4f4
    Author: Robert Lupton the Good 
    Date:   Wed Oct 10 22:06:38 2012 -0400
    
        Add method to return the "statsImage" extracted from the input Image
    

    b84187e8

    commit b84187e8186d89267b706d375daf5a6b4e6cc501
    Author: Steven Bickerton 
    Date:   Thu Apr 16 16:54:02 2015 +0900
    
        Add a test for BackgroundListIO with an approx background.
    

    1d43230a

    commit 1d43230ade70f73e04e016b19b3387746b51b12d
    Author: bick 
    Date:   Fri Oct 30 18:44:52 2009 +0000
    
        #987 Added tests for background interp handling.
    

    264e671e

    commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
    Author: Steven Bickerton 
    Date:   Fri Oct 24 14:37:15 2014 +0900
    
        Use shared_ptr.  Add test.  Disable double,int backgrounds.
    

    ecc83dad

    commit ecc83dadc3e7c194f68ee4a4c44a05090e83eecb
    Author: Robert Lupton the Good 
    Date:   Thu Apr 25 16:08:17 2013 -0400
    
        Handle the case that not only columns are bad but rows too
        
        And an entirely bad image, for that matter (sets background to NaN).  A
        single good pixel is enough to avoid this fate
    

    2b4b80a5

    commit 2b4b80a531b4f37ae62b237534c8142eb3450449
    Author: Robert Lupton the Good 
    Date:   Sat Mar 9 07:01:06 2013 +0900
    
        Make it possible to round-trip a list of Backgrounds via disk
        
        This involved adding a ctor to make a BackgroundMI from a statsImage
        and the full-resolution image bounding box (n.b. the origin is
        still ignored).   Because much task code still uses legacy API where
        the interpolation style is specified in the ctor, not as arguments to
        getImage where it's actually used, it seemed out of scope to expect
        the list to be of tuples (Background, interpStyle, undersampleStyle)
        so I use the values that were last used to get an Image.  This is
        probably safe, but is a little ugly.
    

    8bf8afcb

    commit 8bf8afcb1757c8e66cee20a2444cd1a5e55fca0b
    Author: Robert Lupton the Good 
    Date:   Thu Apr 26 17:28:05 2012 -0400
    
        Added a test that illustrates #2073
    

    Commits in /Users/nate/repos_lsst/afw/

    65b8e9b5

    commit 65b8e9b522cb4d92402c3272872d57d1e832ce29
    Author: Paul Price 
    Date:   Fri Feb 7 16:11:23 2014 -0500
    
        Background: make BackgroundMI and BackgroundList picklable
        
        Note that an item returned by lsst.afw.math.makeBackground() cannot be
        pickled directly (it's difficult to properly pickle SWIGed polymorphic
        objects).  The current workaround is to cast it to a BackgroundMI; best
        would be to not use polymorphism from python.
    

    c16ef84d

    commit c16ef84dbc57a40a79480b3b277261cb6bbe22c6
    Author: Robert Lupton the Good 
    Date:   Wed Apr 3 16:45:18 2013 -0400
    
        Cleanups as proposed by REO in code review for #2732
    

    d31fcd9b

    commit d31fcd9b9545f895284075abc03748bb99b9c83b
    Author: Mario Juric 
    Date:   Tue Oct 14 04:48:31 2014 -0500
    
        bugfix: do approximate comparison to initialValue in testBadPatch()
        
        Equality is not guaranteed due to roundoff errors in spline interpolation.
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    149224f2

    commit 149224f23c8fd769e4a40a63b07c5b586b77d503
    Author: Robert Lupton the Good 
    Date:   Wed Oct 10 12:34:20 2012 -0400
    
        Moved generation of interpolated background images from ctor to getImage()
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    883e4114

    commit 883e41145dc276f8fd42185b7cc16c26d6ddebdc
    Author: Robert Lupton the Good 
    Date:   Tue Mar 12 06:37:25 2013 +0900
    
        Add BackgroundList object so as to allow the butler to handle I/O
    

    09d5dad2

    commit 09d5dad20b363c3bdb90908c652cb8d6a2408428
    Author: dstn 
    Date:   Sun Nov 6 18:56:50 2011 +0000
    
        manually extrapolate to 2nd order (Jim Bosch reports that new GSL versions refuse to extrapolate in the interpolation routines)
    

    034610f9

    commit 034610f9b20b86a988c52e9b09a15dc49affadbd
    Author: Russell Owen 
    Date:   Fri Mar 20 15:40:36 2015 -0700
    
        Change Background to use the xy0 of the image bbox
        
        The Background and BackgroundMI objects ignored the xy0 of the image
        from which they were constructed. This code modifies these classes
        to record the xy0, so that the background images constructed from an image
        have the same xy0 as the image.
        
        It appears that ignoring the image's xy0 was an accident based
        on a misunderstanding about the old default behavior of Image.getBBox(),
        which used to return a LOCAL bounding box (xy0=0,0). Much of the existing
        code seems to be based on the bounding box possibly having a non-zero xy0.
        Nonetheless, simply changing the way the bounding box was read from the image
        was insufficient and I had to make additional changes. There were two possible
        approaches:
        - Use PARENT coordinates everywhere. This requires changingmore code, but results in all
        variables using the same coordinate system (PARENT coordinates), so I felt it was
        worth trying. Unfortunately I was not able to get it to work.
        - Continue to use LOCAL coordinates for all the math and just apply the XY0
        after computing the background image. This is a minimally invasive approach,
        but result in the code using two coordinate systems, which is potentially confusing.
        Nonetheless this is the approach I took.
        
        tests/background.py includes two new tests for these changes. I also made
        other changes to this test, including:
        - Minor changes to make the file pass the pyflakes linter with no warnings
        - Use @skipIt for tests if afwdata is not setup, as requested by the reviewer
        
        Improve the background.py unit test as per John S's review
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    a4391028

    commit a43910287bbfe15fdafc2112c5086a72d6697f6d
    Author: bick 
    Date:   Thu Nov 19 00:14:28 2009 +0000
    
        On afw/trunk/.  Attended to some pylint errors and added examples/ to SConstruct install.
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    2b4b80a5

    commit 2b4b80a531b4f37ae62b237534c8142eb3450449
    Author: Robert Lupton the Good 
    Date:   Sat Mar 9 07:01:06 2013 +0900
    
        Make it possible to round-trip a list of Backgrounds via disk
        
        This involved adding a ctor to make a BackgroundMI from a statsImage
        and the full-resolution image bounding box (n.b. the origin is
        still ignored).   Because much task code still uses legacy API where
        the interpolation style is specified in the ctor, not as arguments to
        getImage where it's actually used, it seemed out of scope to expect
        the list to be of tuples (Background, interpStyle, undersampleStyle)
        so I use the values that were last used to get an Image.  This is
        probably safe, but is a little ugly.
    

    f31e7b32

    commit f31e7b32ba20a8b3b3a531361fdeabc24a7245d1
    Author: Dustin Lang 
    Date:   Sun Jan 8 16:28:13 2012 -0600
    
        split background into more evenly sized subimages
    

    ff0c8fc4

    commit ff0c8fc4d3fb8d3e18c90ccf5d5efac743619b4a
    Author: bick 
    Date:   Wed Jan 14 16:50:33 2009 +0000
    
        Merging ticket 395 (image statistics and background estimation) on to trunk.
    

    2eb9dac3

    commit 2eb9dac33eec6f13a73c03cc2827aa9884ff06cc
    Author: rowen 
    Date:   Mon Sep 28 22:55:55 2009 +0000
    
        Removed all tabs.
    

    Return to list

    src/math/minimize.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file
                     *
                     * @brief Definition of member functions for minuit adaptors
                     *
                     * This file is meant to be included by lsst/afw/math/minimize.h
                     *
                     * @author Andrew Becker and Russell Owen
                     *
                     * @ingroup afw
                     */
                    
                    #include 
                    
                    #include "Minuit2/FunctionMinimum.h"
                    #include "Minuit2/MnMigrad.h"
                    #include "Minuit2/MnMinos.h"
                    #include "Minuit2/MnPrint.h"
                    
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/math/minimize.h"
                    
                    namespace afwMath = lsst::afw::math;
                    
                    namespace {
                        /*
                         * Minuit wrapper for a function(x)
                         */
                        template
                        class MinimizerFunctionBase1 : public ROOT::Minuit2::FCNBase, public lsst::daf::base::Citizen {
                        public:
                            explicit MinimizerFunctionBase1(
                                afwMath::Function1 const &function,
                                std::vector const &measurementList,
                                std::vector const &varianceList,
                                std::vector const &xPositionList,
                                double errorDef
                            );
                            virtual ~MinimizerFunctionBase1() {};
                            // Required by ROOT::Minuit2::FCNBase
                            virtual double Up() const { return _errorDef; }
                            virtual double operator() (const std::vector&) const;
                    
                    #if 0                                   // not used
                            inline std::vector getMeasurements() const {return _measurementList;}
                            inline std::vector getVariances() const {return _varianceList;}
                            inline std::vector getPositions() const {return _xPositionList;}
                            inline void setErrorDef(double def) {_errorDef=def;}
                    #endif
                        private:
                            boost::shared_ptr > _functionPtr;
                            std::vector _measurementList;
                            std::vector _varianceList;
                            std::vector _xPositionList;
                            double _errorDef;
                        };
                            
                        /*
                         * Minuit wrapper for a function(x, y)
                         */
                        template
                        class MinimizerFunctionBase2 : public ROOT::Minuit2::FCNBase, public lsst::daf::base::Citizen {
                        public:
                            explicit MinimizerFunctionBase2(
                                afwMath::Function2 const &function,
                                std::vector const &measurementList,
                                std::vector const &varianceList,
                                std::vector const &xPositionList,
                                std::vector const &yPositionList,
                                double errorDef
                            );
                            virtual ~MinimizerFunctionBase2() {};
                            // Required by ROOT::Minuit2::FCNBase
                            virtual double Up() const { return _errorDef; }
                            virtual double operator() (const std::vector& par) const;
                            
                    #if 0                                   // not used
                            inline std::vector getMeasurements() const {return _measurementList;}
                            inline std::vector getVariances() const {return _varianceList;}
                            inline std::vector getPosition1() const {return _xPositionList;}
                            inline std::vector getPosition2() const {return _yPositionList;}
                            inline void setErrorDef(double def) {_errorDef=def;}
                    #endif
                        private:
                            boost::shared_ptr > _functionPtr;
                            std::vector _measurementList;
                            std::vector _varianceList;
                            std::vector _xPositionList;
                            std::vector _yPositionList;
                            double _errorDef;
                        };
                    }
                    /// \cond
                    template
                    MinimizerFunctionBase1::MinimizerFunctionBase1(
                        lsst::afw::math::Function1 const &function,
                        std::vector const &measurementList,
                        std::vector const &varianceList,
                        std::vector const &xPositionList, 
                        double errorDef)
                    :
                        lsst::daf::base::Citizen(typeid(this)),
                        _functionPtr(function.clone()),
                        _measurementList(measurementList),
                        _varianceList(varianceList),
                        _xPositionList(xPositionList),
                        _errorDef(errorDef)
                    {}
                    
                    template
                    MinimizerFunctionBase2::MinimizerFunctionBase2(
                        lsst::afw::math::Function2 const &function,
                        std::vector const &measurementList,
                        std::vector const &varianceList,
                        std::vector const &xPositionList,
                        std::vector const &yPositionList,
                        double errorDef)
                    :
                        lsst::daf::base::Citizen(typeid(this)),
                        _functionPtr(function.clone()),
                        _measurementList(measurementList),
                        _varianceList(varianceList),
                        _xPositionList(xPositionList),
                        _yPositionList(yPositionList),
                        _errorDef(errorDef)
                    {}
                    
                    
                    
                    // Only method we need to set up; basically this is a chi^2 routine
                    template
                    double MinimizerFunctionBase1::operator() (const std::vector& par) const {
                        // Initialize the function with the fit parameters
                        this->_functionPtr->setParameters(par);
                        
                        double chi2 = 0.0;
                        for (unsigned int i = 0; i < this->_measurementList.size(); i++) {
                            double resid = (*(this->_functionPtr))(this->_xPositionList[i]) - this->_measurementList[i];
                            chi2 += resid * resid / this->_varianceList[i];
                        }
                        
                        return chi2;
                    }
                    
                    
                    template
                    double MinimizerFunctionBase2::operator() (const std::vector& par) const {
                        // Initialize the function with the fit parameters
                        this->_functionPtr->setParameters(par);
                        
                        double chi2 = 0.0;
                        for (unsigned int i = 0; i < this->_measurementList.size(); i++) {
                            double resid = (*(this->_functionPtr))(this->_xPositionList[i],
                                                                   this->_yPositionList[i]) - this->_measurementList[i];
                            chi2 += resid * resid / this->_varianceList[i];
                        }
                        
                        return chi2;
                    }
                    /// \endcond
                    
                    /**
                     * Find the minimum of a function(x)
                     *
                     * @return true if minimum is valid, false otherwise
                     *
                     * Uses the Minuit fitting package with a standard definition of chiSq
                     * (see MinimizerFunctionBase1).
                     *
    
    194 3771b5eb - * @throw lsst::pex::exceptions::InvalidParameterException if any input vector is the wrong length
    ? ^^^^^^ ^
    194 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if any input vector is the wrong length
    ? ^^ ^ * * To do: * - Document stepSizeList better * - Document errorDef * - Compute stepSize automatically? (if so, find a different way to fix parameters) */ template afwMath::FitResults afwMath::minimize( lsst::afw::math::Function1 const &function, ///< function(x) to be minimized std::vector const &initialParameterList, ///< initial guess for parameters std::vector const &stepSizeList, ///< step size for each parameter; use 0.0 to fix a parameter std::vector const &measurementList, ///< measured values std::vector const &varianceList, ///< variance for each measurement std::vector const &xPositionList, ///< x position of each measurement double errorDef ///< what is this? ) { unsigned int const nParameters = function.getNParameters(); if (initialParameterList.size() != nParameters) {
    213 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    213 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "initialParameterList is the wrong length"); } if (stepSizeList.size() != nParameters) {
    217 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    217 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "stepSizeList is the wrong length"); } unsigned int const nMeasurements = measurementList.size(); if (varianceList.size() != nMeasurements) {
    222 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    222 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "varianceList is the wrong length"); } if (xPositionList.size() != nMeasurements) {
    226 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    226 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "xPositionList is the wrong length"); } MinimizerFunctionBase1 minimizerFunc( function, measurementList, varianceList, xPositionList, errorDef ); ROOT::Minuit2::MnUserParameters fitPar; std::vector paramNames; for (unsigned int i = 0; i < nParameters; ++i) { paramNames.push_back((boost::format("p%d") % i).str()); fitPar.Add(paramNames[i].c_str(), initialParameterList[i], stepSizeList[i]); } ROOT::Minuit2::MnMigrad migrad(minimizerFunc, fitPar); ROOT::Minuit2::FunctionMinimum min = migrad(); ROOT::Minuit2::MnMinos minos(minimizerFunc, min); FitResults fitResults; fitResults.chiSq = min.Fval(); fitResults.isValid = min.IsValid() && std::isfinite(fitResults.chiSq); if (!fitResults.isValid) { lsst::pex::logging::Trace("lsst::afw::math::minimize", 1, "WARNING : Fit failed to converge"); } for (unsigned int i = 0; i < nParameters; ++i) { fitResults.parameterList.push_back(min.UserState().Value(paramNames[i].c_str())); if (fitResults.isValid) { fitResults.parameterErrorList.push_back(minos(i)); } else { double e = min.UserState().Error(paramNames[i].c_str()); std::pair ep(-1 * e, e); fitResults.parameterErrorList.push_back(ep); } } return fitResults; } /** * Find the minimum of a function(x, y) * * Uses the Minuit fitting package with a standard definition of chiSq. * (see MinimizerFunctionBase2). * * @return true if minimum is valid, false otherwise *
    278 3771b5eb - * @throw lsst::pex::exceptions::InvalidParameterException if any input vector is the wrong length
    ? ^^^^^^ ^
    278 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if any input vector is the wrong length
    ? ^^ ^ * * To do: * - Document stepSizeList better * - Document errorDef * - Compute stepSize automatically? (if so, find a different way to fix parameters) */ template afwMath::FitResults afwMath::minimize( lsst::afw::math::Function2 const &function, ///< function(x,y) to be minimized std::vector const &initialParameterList, ///< initial guess for parameters std::vector const &stepSizeList, ///< step size for each parameter; use 0.0 to fix a parameter std::vector const &measurementList, ///< measured values std::vector const &varianceList, ///< variance for each measurement std::vector const &xPositionList, ///< x position of each measurement std::vector const &yPositionList, ///< y position of each measurement double errorDef ///< what is this? ) { unsigned int const nParameters = function.getNParameters(); if (initialParameterList.size() != nParameters) {
    298 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    298 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "initialParameterList is the wrong length"); } if (stepSizeList.size() != nParameters) {
    302 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    302 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "stepSizeList is the wrong length"); } unsigned int const nMeasurements = measurementList.size(); if (varianceList.size() != nMeasurements) {
    307 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    307 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "varianceList is the wrong length"); } if (xPositionList.size() != nMeasurements) {
    311 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    311 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "xPositionList is the wrong length"); } if (yPositionList.size() != nMeasurements) {
    315 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    315 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "yPositionList is the wrong length"); } MinimizerFunctionBase2 minimizerFunc( function, measurementList, varianceList, xPositionList, yPositionList, errorDef ); ROOT::Minuit2::MnUserParameters fitPar; std::vector paramNames; for (unsigned int i = 0; i < nParameters; ++i) { paramNames.push_back((boost::format("p%d") % i).str()); fitPar.Add(paramNames[i].c_str(), initialParameterList[i], stepSizeList[i]); } ROOT::Minuit2::MnMigrad migrad(minimizerFunc, fitPar); ROOT::Minuit2::FunctionMinimum min = migrad(); ROOT::Minuit2::MnMinos minos(minimizerFunc, min); FitResults fitResults; fitResults.chiSq = min.Fval(); fitResults.isValid = min.IsValid() && std::isfinite(fitResults.chiSq); if (!fitResults.isValid) { lsst::pex::logging::Trace("lsst::afw::math::minimize", 1, "WARNING : Fit failed to converge"); } for (unsigned int i = 0; i < nParameters; ++i) { fitResults.parameterList.push_back(min.UserState().Value(paramNames[i].c_str())); if (fitResults.isValid) { fitResults.parameterErrorList.push_back(minos(i)); } else { double e = min.UserState().Error(paramNames[i].c_str()); std::pair ep(-1 * e, e); fitResults.parameterErrorList.push_back(ep); } } return fitResults; } // Explicit instantiation /// \cond #define NL /* */ #define minimizeFuncs(ReturnT) \ template afwMath::FitResults afwMath::minimize( \ afwMath::Function1 const &, \ std::vector const &, \ std::vector const &, \ std::vector const &, \ std::vector const &, \ std::vector const &, \ double \ ); NL \ template afwMath::FitResults afwMath::minimize( \ afwMath::Function2 const &, \ std::vector const &, \ std::vector const &, \ std::vector const &, \ std::vector const &, \ std::vector const &, \ std::vector const &, \ double \ ); minimizeFuncs(float) minimizeFuncs(double) /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7a6ea5ce

    commit 7a6ea5ce178494cb61090089847aacd809082e36
    Author: bick 
    Date:   Wed Jan 6 20:50:58 2010 +0000
    
        #1113 sundry style corrections on afw.
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/testSchema.py

    Diff:

    1 9ccc92c4 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for table.Schema Run with: ./testSchema.py or python >>> import testSchema; testSchema.run() """
    35 9ccc92c4 - import sys
    36 9ccc92c4 - import os
    import unittest import numpy import lsst.utils.tests import lsst.pex.exceptions import lsst.afw.table import lsst.afw.geom import lsst.afw.coord try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class SchemaTestCase(unittest.TestCase):
    54 35ba793d - def testSchema(self):
    53 a25b9eb2 + def xtestSchema(self):
    ? + schema = lsst.afw.table.Schema();
    56 2cf33503 - ab_k = schema.addField("a.b", type="Coord", doc="parent coord")
    ? ^
    55 a25b9eb2 + ab_k = schema.addField("a_b", type="Coord", doc="parent coord")
    ? ^
    57 47a82785 - abi_k = schema.addField("a.b.i", type=int, doc="int")
    ? ^ ^
    56 a25b9eb2 + abi_k = schema.addField("a_b_i", type=int, doc="int")
    ? ^ ^
    58 47a82785 - acf_k = schema.addField("a.c.f", type=numpy.float32, doc="float")
    ? ^ ^
    57 a25b9eb2 + acf_k = schema.addField("a_c_f", type=numpy.float32, doc="float")
    ? ^ ^
    59 2cf33503 - egd_k = schema.addField("e.g.d", type=lsst.afw.geom.Angle, doc="angle")
    ? ^ ^
    58 a25b9eb2 + egd_k = schema.addField("e_g_d", type=lsst.afw.geom.Angle, doc="angle")
    ? ^ ^
    60 9813ec58 - abp_k = schema.addField("a.b.p", type="PointD", doc="point")
    ? ^ ^
    59 47c9897e + abp_k = schema.addField("a_b_p", type="PointD", doc="point")
    ? ^ ^
    61 3e1f9e0b - ab_si = schema.find("a.b")
    ? ^
    60 a25b9eb2 + ab_si = schema.find("a_b")
    ? ^ self.assertEqual(ab_si.key, ab_k)
    63 3e1f9e0b - self.assertEqual(ab_si.field.getName(), "a.b")
    ? ^
    62 a25b9eb2 + self.assertEqual(ab_si.field.getName(), "a_b")
    ? ^
    64 2cf33503 - self.assertEqual(ab_k.getRa(), schema["a.b.ra"].asKey());
    ? ^ ^
    63 a25b9eb2 + self.assertEqual(ab_k.getRa(), schema["a_b_ra"].asKey());
    ? ^ ^
    65 47a82785 - abp_si = schema.find("a.b.p")
    ? ^ ^
    64 a25b9eb2 + abp_si = schema.find("a_b_p")
    ? ^ ^ self.assertEqual(abp_si.key, abp_k)
    67 47a82785 - self.assertEqual(abp_si.field.getName(), "a.b.p")
    ? ^ ^
    66 a25b9eb2 + self.assertEqual(abp_si.field.getName(), "a_b_p")
    ? ^ ^
    68 47a82785 - abpx_si = schema.find("a.b.p.x")
    ? ^ ^ ^
    67 a25b9eb2 + abpx_si = schema.find("a_b_p_x")
    ? ^ ^ ^ self.assertEqual(abp_k.getX(), abpx_si.key);
    70 47a82785 - self.assertEqual(abpx_si.field.getName(), "a.b.p.x")
    ? ^ ^ ^
    69 a25b9eb2 + self.assertEqual(abpx_si.field.getName(), "a_b_p_x")
    ? ^ ^ ^ self.assertEqual(abpx_si.field.getDoc(), "point")
    72 47a82785 - self.assertEqual(abp_k, schema["a.b.p"].asKey())
    ? ^ ^
    71 a25b9eb2 + self.assertEqual(abp_k, schema["a_b_p"].asKey())
    ? ^ ^
    73 47a82785 - self.assertEqual(abp_k.getX(), schema["a.b.p.x"].asKey());
    ? ^ ^ ^
    72 a25b9eb2 + self.assertEqual(abp_k.getX(), schema["a_b_p_x"].asKey());
    ? ^ ^ ^
    74 3e1f9e0b - self.assertEqual(schema.getNames(), ("a.b", "a.b.i", "a.b.p", "a.c.f", "e.g.d"))
    ? ^ ^ ^ ^ ^ ^ ^ ^ ^
    73 a25b9eb2 + self.assertEqual(schema.getNames(), ("a_b", "a_b_i", "a_b_p", "a_c_f", "e_g_d"))
    ? ^ ^ ^ ^ ^ ^ ^ ^ ^ self.assertEqual(schema.getNames(True), ("a", "e"))
    76 3e1f9e0b - self.assertEqual(schema["a"].getNames(), ("b", "b.i", "b.p", "c.f"))
    ? ^ ^ ^
    75 a25b9eb2 + self.assertEqual(schema["a"].getNames(), ("b", "b_i", "b_p", "c_f"))
    ? ^ ^ ^ self.assertEqual(schema["a"].getNames(True), ("b", "c")) schema2 = lsst.afw.table.Schema(schema) self.assertEqual(schema, schema2) schema2.addField("q", type=float, doc="another double") self.assertNotEqual(schema, schema2) schema3 = lsst.afw.table.Schema() schema3.addField("j", type=lsst.afw.coord.Coord, doc="coord") schema3.addField("i", type="I", doc="int") schema3.addField("f", type="F", doc="float") schema3.addField("d", type="Angle", doc="angle") schema3.addField("p", type="PointD", doc="point") self.assertEqual(schema3, schema) schema4 = lsst.afw.table.Schema() keys = [] keys.append(schema4.addField("a", type="Coord", doc="a")) keys.append(schema4.addField("b", type="Flag", doc="b")) keys.append(schema4.addField("c", type=int, doc="c")) keys.append(schema4.addField("d", type="Flag", doc="d")) self.assertEqual(keys[1].getBit(), 0) self.assertEqual(keys[3].getBit(), 1) for n1, n2 in zip(schema4.getOrderedNames(), "abcd"): self.assertEqual(n1, n2) keys2 = map(lambda x: x.key, schema4.asList()) self.assertEqual(keys, keys2) def testInspection(self): schema = lsst.afw.table.Schema() keys = [] keys.append(schema.addField("d", type=int)) keys.append(schema.addField("c", type=float)) keys.append(schema.addField("b", type="ArrayF", size=3)) keys.append(schema.addField("a", type="CovPointF")) for key, item in zip(keys, schema): self.assertEqual(item.key, key) self.assert_(key in schema) for name in ("a", "b", "c", "d"): self.assert_(name in schema) self.assertFalse("e" in schema) otherSchema = lsst.afw.table.Schema() otherKey = otherSchema.addField("d", type=float) self.assertFalse(otherKey in schema) self.assertNotEqual(keys[0], keys[1]) def testKeyAccessors(self): schema = lsst.afw.table.Schema() arrayKey = schema.addField("a", type="ArrayF", doc="doc for array field", size=5) arrayElementKey = arrayKey[1] self.assertEqual(lsst.afw.table.Key["F"], type(arrayElementKey)) covKey = schema.addField("c", type="CovF", doc="doc for cov field", size=5) covElementKey = covKey[1,2] self.assertEqual(lsst.afw.table.Key["F"], type(covElementKey)) pointKey = schema.addField("p", type="PointD", doc="doc for point field") pointElementKey = pointKey.getX() self.assertEqual(lsst.afw.table.Key["D"], type(pointElementKey)) shapeKey = schema.addField("s", type="MomentsD", doc="doc for shape field") shapeElementKey = shapeKey.getIxx() self.assertEqual(lsst.afw.table.Key["D"], type(shapeElementKey)) def testComparison(self): schema1 = lsst.afw.table.Schema() schema1.addField("a", type=float, doc="doc for a", units="units for a") schema1.addField("b", type=int, doc="doc for b", units="units for b") schema2 = lsst.afw.table.Schema() schema2.addField("a", type=int, doc="doc for a", units="units for a") schema2.addField("b", type=float, doc="doc for b", units="units for b") cmp1 = schema1.compare(schema2, lsst.afw.table.Schema.IDENTICAL) self.assertTrue(cmp1 & lsst.afw.table.Schema.EQUAL_NAMES) self.assertTrue(cmp1 & lsst.afw.table.Schema.EQUAL_DOCS) self.assertTrue(cmp1 & lsst.afw.table.Schema.EQUAL_UNITS) self.assertFalse(cmp1 & lsst.afw.table.Schema.EQUAL_KEYS) schema3 = lsst.afw.table.Schema(schema1) schema3.addField("c", type=str, doc="doc for c", size=4) self.assertFalse(schema1.compare(schema3)) self.assertFalse(schema1.contains(schema3)) self.assertTrue(schema3.contains(schema1)) schema1.addField("d", type=str, doc="no docs!", size=4) cmp2 = schema1.compare(schema3, lsst.afw.table.Schema.IDENTICAL) self.assertFalse(cmp2 & lsst.afw.table.Schema.EQUAL_NAMES) self.assertFalse(cmp2 & lsst.afw.table.Schema.EQUAL_DOCS) self.assertTrue(cmp2 & lsst.afw.table.Schema.EQUAL_KEYS) self.assertTrue(cmp2 & lsst.afw.table.Schema.EQUAL_UNITS) self.assertFalse(schema1.compare(schema3, lsst.afw.table.Schema.EQUAL_NAMES))
    158 9ccc92c4 +
    159 1ad0851f + def testDelimiter(self):
    160 1ad0851f + s0 = lsst.afw.table.Schema(0)
    161 1ad0851f + s1 = lsst.afw.table.Schema(1)
    162 1ad0851f + k0abc = s0.addField("a.b.c", type=int, doc="version 0: period separators")
    163 1ad0851f + k1abc = s1.addField("a_b_c", type=int, doc="version 1: underscore separators")
    164 1ad0851f + # Note: eventually we'll remove compound types like Point2I, but in the meantime we want subfields
    165 1ad0851f + # to be accessed properly
    166 1ad0851f + k0d = s0.addField("d", type="PointI", doc="version 0: period separators")
    167 1ad0851f + k1d = s1.addField("d", type="PointI", doc="version 1: underscore separators")
    168 1ad0851f + self.assertEqual(s0["a"]["b"].find("c").key, k0abc)
    169 1ad0851f + self.assertEqual(s1["a"]["b"].find("c").key, k1abc)
    170 1ad0851f + self.assertEqual(s0.find("d.x").key, k0d.getX())
    171 1ad0851f + self.assertEqual(s1.find("d_x").key, k1d.getX())
    172 1ad0851f +
    173 56df42d2 + def testVersions(self):
    174 56df42d2 + s0 = lsst.afw.table.Schema(0)
    175 56df42d2 + s1 = lsst.afw.table.Schema(1)
    176 56df42d2 + self.assertEqual(s0.getVersion(), 0)
    177 56df42d2 + self.assertEqual(s1.getVersion(), 1)
    178 1ad0851f +
    179 56df42d2 + s0.setVersion(1)
    180 56df42d2 + s1.setVersion(0)
    181 56df42d2 + self.assertEqual(s0.getVersion(), 1)
    182 56df42d2 + self.assertEqual(s1.getVersion(), 0)
    class SchemaMapperTestCase(unittest.TestCase): def testJoin(self): inputs = [lsst.afw.table.Schema(), lsst.afw.table.Schema(), lsst.afw.table.Schema()] inputs = lsst.afw.table.SchemaVector(inputs) prefixes = ["u", "v", "w"] ka = inputs[0].addField("a", type=numpy.float64, doc="doc for a") kb = inputs[0].addField("b", type=numpy.int32, doc="doc for b") kc = inputs[1].addField("c", type=numpy.float32, doc="doc for c") kd = inputs[2].addField("d", type=numpy.int64, doc="doc for d") flags1 = lsst.afw.table.Schema.IDENTICAL flags2 = flags1 & ~lsst.afw.table.Schema.EQUAL_NAMES mappers1 = lsst.afw.table.SchemaMapper.join(inputs) mappers2 = lsst.afw.table.SchemaMapper.join(inputs, prefixes) records = [lsst.afw.table.BaseTable.make(schema).makeRecord() for schema in inputs] records[0].set(ka, 3.14159) records[0].set(kb, 21623) records[1].set(kc, 1.5616) records[2].set(kd, 1261236) for mappers, flags in zip((mappers1, mappers2), (flags1, flags2)): output = lsst.afw.table.BaseTable.make(mappers[0].getOutputSchema()).makeRecord() for mapper, record in zip(mappers, records): output.assign(record, mapper) self.assertEqual(mapper.getOutputSchema().compare(output.getSchema(), flags), flags) self.assertEqual(mapper.getInputSchema().compare(record.getSchema(), flags), flags) names = output.getSchema().getOrderedNames() self.assertEqual(output.get(names[0]), records[0].get(ka)) self.assertEqual(output.get(names[1]), records[0].get(kb)) self.assertEqual(output.get(names[2]), records[1].get(kc)) self.assertEqual(output.get(names[3]), records[2].get(kd)) def testMinimalSchema(self): front = lsst.afw.table.Schema() ka = front.addField("a", type=numpy.float64, doc="doc for a") kb = front.addField("b", type=numpy.int32, doc="doc for b") full = lsst.afw.table.Schema(front) kc = full.addField("c", type=numpy.float32, doc="doc for c") kd = full.addField("d", type=numpy.int64, doc="doc for d") mapper1 = lsst.afw.table.SchemaMapper(full) mapper2 = lsst.afw.table.SchemaMapper(full) mapper3 = lsst.afw.table.SchemaMapper.removeMinimalSchema(full, front) mapper1.addMinimalSchema(front) mapper2.addMinimalSchema(front, False) self.assert_(ka in mapper1.getOutputSchema()) self.assert_(kb in mapper1.getOutputSchema()) self.assert_(kc not in mapper1.getOutputSchema()) self.assert_(kd not in mapper1.getOutputSchema()) self.assert_(ka in mapper2.getOutputSchema()) self.assert_(kb in mapper2.getOutputSchema()) self.assert_(kc not in mapper2.getOutputSchema()) self.assert_(kd not in mapper2.getOutputSchema()) self.assert_(ka not in mapper3.getOutputSchema()) self.assert_(kb not in mapper3.getOutputSchema()) self.assert_(kc not in mapper3.getOutputSchema()) self.assert_(kd not in mapper3.getOutputSchema()) inputRecord = lsst.afw.table.BaseTable.make(full).makeRecord() inputRecord.set(ka, numpy.pi) inputRecord.set(kb, 2) inputRecord.set(kc, numpy.exp(1)) inputRecord.set(kd, 4) outputRecord1 = lsst.afw.table.BaseTable.make(mapper1.getOutputSchema()).makeRecord() outputRecord1.assign(inputRecord, mapper1) self.assertEqual(inputRecord.get(ka), outputRecord1.get(ka)) self.assertEqual(inputRecord.get(kb), outputRecord1.get(kb)) def testOutputSchema(self): mapper = lsst.afw.table.SchemaMapper(lsst.afw.table.Schema()) out1 = mapper.getOutputSchema() out2 = mapper.editOutputSchema() k1 = out1.addField("a1", type=int) self.assert_(k1 not in mapper.getOutputSchema()) self.assert_(k1 in out1) self.assert_(k1 not in out2) k2 = mapper.addOutputField(lsst.afw.table.Field[float]("a2", "doc for a2")) self.assert_(k2 not in out1) self.assert_(k2 in mapper.getOutputSchema()) self.assert_(k2 in out2) k3 = out2.addField("a3", type=numpy.float32, doc="doc for a3") self.assert_(k3 not in out1) self.assert_(k3 in mapper.getOutputSchema()) self.assert_(k3 in out2) def testDoReplace(self): inSchema = lsst.afw.table.Schema() ka = inSchema.addField("a", type=int) outSchema = lsst.afw.table.Schema(inSchema) kb = outSchema.addField("b", type=int) kc = outSchema.addField("c", type=int) mapper1 = lsst.afw.table.SchemaMapper(inSchema, outSchema) mapper1.addMapping(ka, True) self.assertEqual(mapper1.getMapping(ka), ka) mapper2 = lsst.afw.table.SchemaMapper(inSchema, outSchema) mapper2.addMapping(ka, lsst.afw.table.Field[int]("b", "doc for b"), True) self.assertEqual(mapper2.getMapping(ka), kb) mapper3 = lsst.afw.table.SchemaMapper(inSchema, outSchema) mapper3.addMapping(ka, "c", True) self.assertEqual(mapper3.getMapping(ka), kc)
    282 56df42d2 + def testVersions(self):
    283 56df42d2 + s0 = lsst.afw.table.Schema(0)
    284 56df42d2 + s1 = lsst.afw.table.Schema(1)
    285 56df42d2 + sm0 = lsst.afw.table.SchemaMapper(s0)
    286 56df42d2 + sm1 = lsst.afw.table.SchemaMapper(s1)
    287 56df42d2 + self.assertEqual(sm0.getOutputSchema().getVersion(), 0)
    288 56df42d2 + self.assertEqual(sm1.getOutputSchema().getVersion(), 1)
    289 56df42d2 + sm0.editOutputSchema().setVersion(1)
    290 56df42d2 + sm1.editOutputSchema().setVersion(0)
    291 56df42d2 + self.assertEqual(sm0.getOutputSchema().getVersion(), 1)
    292 56df42d2 + self.assertEqual(sm1.getOutputSchema().getVersion(), 0)
    293 56df42d2 +
    294 4899a4da + def testJoin(self):
    295 4899a4da + s0 = lsst.afw.table.Schema(0)
    296 4899a4da + s1 = lsst.afw.table.Schema(1)
    297 4899a4da + self.assertEqual(s0.join("a", "b"), "a.b")
    298 4899a4da + self.assertEqual(s0.join("a", "b", "c"), "a.b.c")
    299 4899a4da + self.assertEqual(s0.join("a", "b", "c", "d"), "a.b.c.d")
    300 4899a4da + self.assertEqual(s1.join("a", "b"), "a_b")
    301 4899a4da + self.assertEqual(s1.join("a", "b", "c"), "a_b_c")
    302 4899a4da + self.assertEqual(s1.join("a", "b", "c", "d"), "a_b_c_d")
    303 56df42d2 +
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" lsst.utils.tests.init() suites = [] suites += unittest.makeSuite(SchemaTestCase) suites += unittest.makeSuite(SchemaMapperTestCase) suites += unittest.makeSuite(lsst.utils.tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" lsst.utils.tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3e1f9e0b

    commit 3e1f9e0b78f337ea33e6fef04ba5e24c2eb5a47f
    Author: Jim Bosch 
    Date:   Wed Jan 11 16:58:43 2012 -0500
    
        added configurable canonical fields to SourceTable/SourceRecord, renamed Shape tag class to Moments to avoid collisions with long-standing measurement names.
    

    47a82785

    commit 47a82785e72101346846b8a2823ec2ff9b1f7f0f
    Author: Jim Bosch 
    Date:   Mon Jan 9 17:18:42 2012 -0500
    
        moved all schema tests to Python, made Schema name sets return Python tuples instead of wrapped std::sets, moved common SWIG stuff to utils' p_lsstSwig.i
    

    9ccc92c4

    commit 9ccc92c4fd4e52ea5f809bd6d05404363ec0a896
    Author: Jim Bosch 
    Date:   Wed Jan 4 23:35:32 2012 -0500
    
        started SWIG for table package; Schema mostly wrapped
    

    2cf33503

    commit 2cf33503feb13b45c362d6b1d9fc16e74eafc9df
    Author: Jim Bosch 
    Date:   Fri Jan 20 18:31:39 2012 -0500
    
        added Angle and Coord field types, reworked Source measurement slots
    

    35ba793d

    commit 35ba793db845ad818cf7cdb8d83b2b0354413371
    Author: Jim Bosch 
    Date:   Fri Jan 4 20:17:42 2013 -0500
    
        Add generally-used SchemaMapper features that we'll want for ExposureCatalog persistence.
    

    9813ec58

    commit 9813ec58cd70d7c99981884489aabdfe21fdafd5
    Author: Jim Bosch 
    Date:   Sat Nov 22 15:16:27 2014 -0500
    
        Remove Point and Moments types from afw::table
        
        These are very rarely used (and we can use the double versions instead
        where they are), and we want to make room for other types under the
        Boost.Variant-imposed 20-type limit.
    

    Commits in /Users/nate/repos_lsst/afw/

    4899a4da

    commit 4899a4dafc36ff465cca197db1051b2525209af7
    Author: Jim Bosch 
    Date:   Wed Oct 1 14:41:45 2014 -0400
    
        Add Schema methods to join strings using appropriate delimiter.
        
        The appropriate delimiter for field names depends on the schema version, making it
        difficult to write version-independent code without something like these
        convenience methods.
    

    56df42d2

    commit 56df42d2bb5dd4ebec2e5c67b0d16a137bb1dee2
    Author: Jim Bosch 
    Date:   Wed Aug 20 13:27:23 2014 -0400
    
        Add constructors to Schema and SchemaMapper to set version immediately.
    

    9ccc92c4

    commit 9ccc92c4fd4e52ea5f809bd6d05404363ec0a896
    Author: Jim Bosch 
    Date:   Wed Jan 4 23:35:32 2012 -0500
    
        started SWIG for table package; Schema mostly wrapped
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    47c9897e

    commit 47c9897e3dc4c0c8e10fc761f1672ca3aef341fa
    Author: Jim Bosch 
    Date:   Sat Nov 22 15:16:27 2014 -0500
    
        Remove Point and Moments types from afw::table
        
        These are very rarely used (and we can use the double versions instead
        where they are), and we want to make room for other types under the
        Boost.Variant-imposed 20-type limit.
        Conflicts:
            tests/testSchema.py
    

    a25b9eb2

    commit a25b9eb2df1c00b862411068c0447f4391bb12f4
    Author: pgee 
    Date:   Wed Mar 4 17:06:38 2015 -0800
    
        DM-1076, remove need of unit tests to setVersion(0), and move tests to default version.
        
        Note that there are several version tests in the unit tests which should not be changed.
        Also needed to change Schema::getNames to use the '_' separator for version > 0.
        Also included responses to review comments
    

    1ad0851f

    commit 1ad0851fe7f9b4642f701986230d1e96fa456644
    Author: Jim Bosch 
    Date:   Wed Aug 20 16:39:01 2014 -0400
    
        Switch between '.' and '_' separators in Schema, depending on version.
    

    Return to list

    include/lsst/afw/table.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef LSST_AFW_table_h_INCLUDED
                    #define LSST_AFW_table_h_INCLUDED
                    
                    #include "lsst/afw/table/Schema.h"
                    #include "lsst/afw/table/SchemaMapper.h"
                    #include "lsst/afw/table/Source.h"
                    #include "lsst/afw/table/Exposure.h"
                    #include "lsst/afw/table/Match.h"
                    #include "lsst/afw/table/BaseColumnView.h"
    
    11 cfb9c7f4 + #include "lsst/afw/table/FunctorKey.h"
    12 642353b0 + #include "lsst/afw/table/aggregates.h"
    13 f9fa5877 + #include "lsst/afw/table/arrays.h"
    #endif // !LSST_AFW_table_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    cfb9c7f4

    commit cfb9c7f46b1c0486102a1eb7e2caa7032eee2efc
    Author: Jim Bosch 
    Date:   Wed Apr 9 11:41:43 2014 -0400
    
        Started work on FunctorKey
    

    642353b0

    commit 642353b05ce94732f1a75e0fe3c22def01364a3c
    Author: Jim Bosch 
    Date:   Thu Apr 10 17:05:27 2014 -0400
    
        Python wrappers for Point, Quadrupole aggregates
    

    f9fa5877

    commit f9fa5877d27976c5bbec22173b33e1337aa420fa
    Author: Jim Bosch 
    Date:   Thu Sep 18 17:21:34 2014 -0400
    
        Add FunctorKey for arrays
    

    Return to list

    tests/ticket2352.py

    Diff:

    1 6ba23cd8 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import os, os.path import unittest
    27 6ba23cd8 - import pickle
    import lsst.afw.image as afwImage import lsst.utils.tests as utilsTests
    31 6ba23cd8 - import lsst.pex.exceptions.exceptionsLib as exceptions
    DATA = os.path.join("tests", "data", "ticket2352.fits") #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ReadMefTest(unittest.TestCase): """Test the reading of a multi-extension FITS (MEF) file""" def checkExtName(self, name, value, extNum): filename = DATA + "[%s]" % name header = afwImage.readMetadata(filename) self.assertEqual(header.get("EXT_NUM"), extNum) self.assertEqual(header.get("EXTNAME").strip(), name) image = afwImage.ImageI(filename) self.assertEqual(image.get(0,0), value) def testExtName(self): self.checkExtName("ONE", 1, 2) self.checkExtName("TWO", 2, 3) self.checkExtName("THREE", 3, 4) def checkExtNum(self, hdu, extNum): header = afwImage.readMetadata(DATA, hdu) self.assertEqual(header.get("EXT_NUM"), extNum) def testExtNum(self): self.checkExtNum(0, 2) # Should skip PHU self.checkExtNum(1, 1) self.checkExtNum(2, 2) self.checkExtNum(3, 3) self.checkExtNum(4, 4) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ReadMefTest) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6ba23cd8

    commit 6ba23cd8144c92f2d36c598c9cb34dee67d829c4
    Author: Paul Price 
    Date:   Tue Oct 2 17:26:41 2012 -0400
    
        Test for and fix opening multi-extension FITS files by extension name.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    tests/rgb.py

    Diff:

                    #!/usr/bin/env python
                    """
                    Tests for RGB Images
                    
                    Run with:
                       ./rgb.py
                    or
                       python
                       >>> import rgb; rgb.run()
                    """
                    
                    import math
    
    13 16cfe977 - import os
    13 7e2503b6 + import unittest
    14 7e2503b6 +
    import numpy as np
    15 16cfe977 - import unittest
    import lsst.utils.tests as utilsTests import lsst.afw.detection as afwDetect import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.afw.math as afwMath import lsst.afw.display.ds9 as ds9 import lsst.afw.display.rgb as rgb
    25 f49676d7 - ver1, ver2, ver3 = 1, 3, 1
    26 f49676d7 - NO_MATPLOTLIB_STRING = "Requires matplotlib >= %d.%d.%d" % (ver1, ver2, ver3)
    try: import matplotlib versionInfo = tuple(int(s.strip("rc")) for s in matplotlib.__version__.split("."))
    30 f49676d7 - HAVE_MATPLOTLIB = versionInfo >= (ver1, ver2, ver3)
    ? --- ^^^^ ^^^^
    28 f5c92c2e + HAVE_MATPLOTLIB = versionInfo >= (1, 3, 1)
    ? ^ ^ except ImportError: HAVE_MATPLOTLIB = False try:
    35 08a7740e - import scipy.misc
    36 f73544e1 - scipy.misc.imresize
    37 08a7740e - HAVE_SCIPY_MISC = True
    38 f73544e1 - except (ImportError, AttributeError):
    39 08a7740e - HAVE_SCIPY_MISC = False
    40 08a7740e -
    41 08a7740e - try:
    type(display) except NameError: display = False
    45 16cfe977 -
    46 16cfe977 - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    47 16cfe977 - #
    48 16cfe977 - # A context object to clean up temporary files
    49 16cfe977 - #
    50 16cfe977 - from contextlib import contextmanager
    51 16cfe977 -
    52 16cfe977 - @contextmanager
    53 16cfe977 - def Tempfile(fileName, remove=True):
    54 16cfe977 - pass # entry to context block
    55 16cfe977 - yield
    56 16cfe977 - if remove: # exit from context block
    57 16cfe977 - os.remove(fileName)
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def saturate(image, satValue): """Simulate saturation on an image, so we can test 'replaceSaturatedPixels' Takes an Image, sets saturated pixels to NAN and masks them, returning a MaskedImage. """ image = afwImage.makeMaskedImage(image) afwDetect.FootprintSet(image, afwDetect.Threshold(satValue), "SAT") arr = image.getImage().getArray() arr[np.where(arr >= satValue)] = np.nan return image R, G, B = 2, 1, 0 class RgbTestCase(unittest.TestCase): """A test case for Rgb""" def setUp(self): self.min, self.range, self.Q = 0, 5, 20 # asinh width, height = 85, 75 self.images = [] self.images.append(afwImage.ImageF(afwGeom.ExtentI(width, height))) self.images.append(afwImage.ImageF(afwGeom.ExtentI(width, height))) self.images.append(afwImage.ImageF(afwGeom.ExtentI(width, height))) for (x, y, A, g_r, r_i) in [(15, 15, 1000, 1.0, 2.0), (50, 45, 5500, -1.0, -0.5), (30, 30, 600, 1.0, 2.5), (45, 15, 20000, 1.0, 1.0), ]: for i in range(len(self.images)): if i == B: amp = A elif i == G: amp = A*math.pow(10, 0.4*g_r) elif i == R: amp = A*math.pow(10, 0.4*r_i) self.images[i].set(x, y, amp) psf = afwMath.AnalyticKernel(15, 15, afwMath.GaussianFunction2D(2.5, 1.5, 0.5)) convolvedImage = type(self.images[0])(self.images[0].getDimensions()) randomImage = type(self.images[0])(self.images[0].getDimensions()) rand = afwMath.Random("MT19937", 666) for i in range(len(self.images)): afwMath.convolve(convolvedImage, self.images[i], psf, True, True) afwMath.randomGaussianImage(randomImage, rand) randomImage *= 2 convolvedImage += randomImage self.images[i] <<= convolvedImage del convolvedImage; del randomImage def tearDown(self): for im in self.images: del im del self.images
    119 f49676d7 - def testStarsAsinh(self):
    ? -----
    97 7e2503b6 + def testStars(self):
    120 f49676d7 - """Test creating an RGB image using an asinh stretch"""
    ? -----------------------
    98 7e2503b6 + """Test creating an RGB image"""
    asinhMap = rgb.AsinhMapping(self.min, self.range, self.Q) rgbImage = asinhMap.makeRgbImage(self.images[R], self.images[G], self.images[B]) if display: rgb.displayRGB(rgbImage)
    105 7e1ab7ff + @unittest.skipUnless(HAVE_MATPLOTLIB, "Requires matplotlib >= 1.3.1")
    127 f49676d7 - def testStarsAsinhZscale(self):
    128 f49676d7 - """Test creating an RGB image using an asinh stretch estimated using zscale"""
    129 f49676d7 -
    130 f49676d7 - rgbImages = [self.images[R], self.images[G], self.images[B]]
    131 f49676d7 -
    132 f49676d7 - map = rgb.AsinhZScaleMapping(rgbImages[0])
    133 f49676d7 - rgbImage = map.makeRgbImage(*rgbImages)
    134 f49676d7 -
    135 f49676d7 - if display:
    136 f49676d7 - rgb.displayRGB(rgbImage)
    137 f49676d7 -
    138 f49676d7 - def testStarsAsinhZscaleIntensity(self):
    139 f49676d7 - """Test creating an RGB image using an asinh stretch estimated using zscale on the intensity"""
    140 f49676d7 -
    141 f49676d7 - rgbImages = [self.images[R], self.images[G], self.images[B]]
    142 f49676d7 -
    143 f49676d7 - map = rgb.AsinhZScaleMapping(rgbImages)
    144 f49676d7 - rgbImage = map.makeRgbImage(*rgbImages)
    145 f49676d7 -
    146 f49676d7 - if display:
    147 f49676d7 - rgb.displayRGB(rgbImage)
    148 f49676d7 -
    149 f49676d7 - def testStarsAsinhZscaleIntensityPedestal(self):
    150 f49676d7 - """Test creating an RGB image using an asinh stretch estimated using zscale on the intensity
    151 f49676d7 - where the images each have a pedestal added"""
    152 f49676d7 -
    153 f49676d7 - rgbImages = [self.images[R], self.images[G], self.images[B]]
    154 f49676d7 -
    155 f49676d7 - pedestal = [100, 400, -400]
    156 f49676d7 - for i, ped in enumerate(pedestal):
    157 f49676d7 - rgbImages[i] += ped
    158 f49676d7 -
    159 f49676d7 - map = rgb.AsinhZScaleMapping(rgbImages, pedestal=pedestal)
    160 f49676d7 - rgbImage = map.makeRgbImage(*rgbImages)
    161 f49676d7 -
    162 f49676d7 - if display:
    163 f49676d7 - rgb.displayRGB(rgbImage)
    164 f49676d7 -
    165 f49676d7 - def testStarsAsinhZscaleIntensityBW(self):
    166 f49676d7 - """Test creating a black-and-white image using an asinh stretch estimated
    167 f49676d7 - using zscale on the intensity"""
    168 f49676d7 -
    169 f49676d7 - rgbImage = rgb.AsinhZScaleMapping(self.images[R]).makeRgbImage()
    170 f49676d7 -
    171 f49676d7 - if display:
    172 f49676d7 - rgb.displayRGB(rgbImage)
    173 f49676d7 -
    174 f49676d7 - @unittest.skipUnless(HAVE_MATPLOTLIB, NO_MATPLOTLIB_STRING)
    def testMakeRGB(self): """Test the function that does it all"""
    177 88d838b7 - fileName = "makeRGB.png"
    178 88d838b7 -
    179 88d838b7 - assert "imageLib.ImageF" in repr(self.images[R]) # check that ImageF is supported
    180 88d838b7 - with Tempfile(fileName, remove=True):
    181 f49676d7 - rgb.makeRGB(self.images[R], self.images[G], self.images[B],
    182 88d838b7 - self.min, self.range, self.Q, fileName=fileName)
    183 f49676d7 - self.assertTrue(os.path.exists(fileName))
    184 88d838b7 -
    185 88d838b7 - def testMakeRGBU(self):
    186 88d838b7 - """Test the function that does it all works with unsigned short images"""
    187 88d838b7 -
    188 88d838b7 - rgbImages = [afwImage.ImageU(_.getArray().astype('uint16')) for _ in [
    189 88d838b7 - self.images[R], self.images[G], self.images[B]]]
    190 88d838b7 -
    191 88d838b7 - assert "imageLib.ImageU" in repr(rgbImages[0]) # check that ImageU is supported
    192 f49676d7 - rgbImage = rgb.makeRGB(*rgbImages, minimum=self.min, range=self.range, Q=self.Q)
    193 f49676d7 -
    194 f49676d7 - def testStars2(self):
    195 f49676d7 - """Test creating an RGB image using makeRGB"""
    196 f49676d7 - rgbImage = rgb.makeRGB(self.images[R], self.images[G], self.images[B])
    197 f49676d7 -
    198 f49676d7 - if display:
    199 f49676d7 - rgb.displayRGB(rgbImage)
    200 f49676d7 -
    201 f49676d7 - def testLinear(self):
    202 f49676d7 - """Test using a specified linear stretch"""
    203 f49676d7 -
    204 f49676d7 - rgbImage = rgb.LinearMapping(-8.45, 13.44).makeRgbImage(self.images[R])
    205 f49676d7 -
    206 f49676d7 - if display:
    207 f49676d7 - rgb.displayRGB(rgbImage)
    208 f49676d7 -
    209 f49676d7 - def testLinearMinMax(self):
    210 f49676d7 - """Test using a min/max linear stretch
    211 f49676d7 -
    212 f49676d7 - N.b. also checks that an image passed to the ctor is used as the default in makeRgbImage()
    213 f49676d7 - """
    214 f49676d7 -
    215 f49676d7 - rgbImage = rgb.LinearMapping(image=self.images[R]).makeRgbImage()
    216 88d838b7 -
    217 88d838b7 - if display:
    218 88d838b7 - rgb.displayRGB(rgbImage)
    219 88d838b7 -
    220 f49676d7 - @unittest.skipUnless(HAVE_MATPLOTLIB, NO_MATPLOTLIB_STRING)
    221 88d838b7 - def testMakeRGBSaturated(self):
    222 88d838b7 - """Test the function that does it all when there are saturated pixels"""
    223 88d838b7 - fileName = "makeRGB.png"
    satValue = 1000.0
    225 88d838b7 - with Tempfile(fileName, remove=True):
    109 c605dfcd + with utilsTests.getTempFilePath(".png") as fileName:
    red = saturate(self.images[R], satValue) green = saturate(self.images[G], satValue) blue = saturate(self.images[B], satValue)
    229 88d838b7 - assert "imageLib.MaskedImageF" in repr(red) # check that MaskedImageF is supported
    rgb.makeRGB(red, green, blue, self.min, self.range, self.Q, fileName=fileName, saturatedBorderWidth=1, saturatedPixelValue=2000)
    232 f49676d7 - self.assertTrue(os.path.exists(fileName))
    116 f5c92c2e + @unittest.skipUnless(HAVE_MATPLOTLIB, "Requires matplotlib >= 1.3.1")
    234 f49676d7 - def testZScale(self):
    235 f49676d7 - """Test using a zscale stretch"""
    236 f49676d7 -
    237 f49676d7 - rgbImage = rgb.ZScaleMapping(self.images[R]).makeRgbImage()
    238 88d838b7 -
    239 f49676d7 - if display:
    240 f49676d7 - plt = rgb.displayRGB(rgbImage, False)
    241 f49676d7 - plt.title("zscale");
    242 f49676d7 - plt.show()
    243 f49676d7 -
    244 f49676d7 - @unittest.skipUnless(HAVE_MATPLOTLIB, NO_MATPLOTLIB_STRING)
    def testWriteStars(self): """Test writing RGB files to disk""" asinhMap = rgb.AsinhMapping(self.min, self.range, self.Q) rgbImage = asinhMap.makeRgbImage(self.images[R], self.images[G], self.images[B])
    121 c605dfcd + with utilsTests.getTempFilePath(".png") as fileName:
    249 254d7248 - fileName = "rgb.png"
    250 254d7248 - with Tempfile(fileName, remove=True):
    rgb.writeRGB(fileName, rgbImage)
    253 254d7248 - if False: # you'll also want to set remove=False in Tempfile manager
    254 254d7248 - os.system("open %s > /dev/null 2>&1" % fileName)
    255 16cfe977 -
    256 f49676d7 - self.assertTrue(os.path.exists(fileName))
    257 f49676d7 -
    def testSaturated(self): """Test interpolating saturated pixels""" satValue = 1000.0 for f in [R, G, B]: self.images[f] = saturate(self.images[f], satValue) rgb.replaceSaturatedPixels(self.images[R], self.images[G], self.images[B], 1, 2000) # # Check that we replaced those NaNs with some reasonable value # for f in [R, G, B]: self.assertTrue(np.isfinite(self.images[f].getImage().getArray()).all()) if False: ds9.mtv(self.images[B], frame=0, title="B") ds9.mtv(self.images[G], frame=1, title="G") ds9.mtv(self.images[R], frame=2, title="R") # # Prepare for generating an output file # for f in [R, G, B]: self.images[f] = self.images[f].getImage() asinhMap = rgb.AsinhMapping(self.min, self.range, self.Q) rgbImage = asinhMap.makeRgbImage(self.images[R], self.images[G], self.images[B]) if display:
    286 f49676d7 - rgb.displayRGB(rgbImage)
    152 7e2503b6 + rgb.displayRGB(rgbImage)
    ? ++++++++++++
    287 16cfe977 -
    288 08a7740e - @unittest.skipUnless(HAVE_SCIPY_MISC, "Resizing images requires scipy.misc")
    289 08a7740e - def testStarsResizeToSize(self):
    290 08a7740e - """Test creating an RGB image of a specified size"""
    291 08a7740e -
    292 08a7740e - xSize = self.images[R].getWidth()/2
    293 08a7740e - ySize = self.images[R].getHeight()/2
    294 08a7740e - for rgbImages in ([self.images[R], self.images[G], self.images[B]],
    295 08a7740e - [afwImage.ImageU(_.getArray().astype('uint16')) for _ in [
    296 08a7740e - self.images[R], self.images[G], self.images[B]]]):
    297 08a7740e - rgbImage = rgb.AsinhZScaleMapping(rgbImages[0]).makeRgbImage(*rgbImages,
    298 08a7740e - xSize=xSize, ySize=ySize)
    299 08a7740e -
    300 08a7740e - if display:
    301 08a7740e - rgb.displayRGB(rgbImage)
    302 08a7740e -
    303 08a7740e - @unittest.skipUnless(HAVE_SCIPY_MISC, "Resizing images requires scipy.misc")
    304 08a7740e - def testStarsResizeSpecifications(self):
    305 08a7740e - """Test creating an RGB image changing the output """
    306 08a7740e -
    307 08a7740e - rgbImages = [self.images[R], self.images[G], self.images[B]]
    308 08a7740e - map = rgb.AsinhZScaleMapping(rgbImages[0])
    309 08a7740e -
    310 08a7740e - for xSize, ySize, frac in [(self.images[R].getWidth()/2, self.images[R].getHeight()/2, None),
    311 08a7740e - (2*self.images[R].getWidth(), None, None),
    312 08a7740e - (self.images[R].getWidth()/2, None, None),
    313 08a7740e - (None, self.images[R].getHeight()/2, None),
    314 08a7740e - (None, None, 0.5),
    315 08a7740e - (None, None, 2),
    316 08a7740e - ]:
    317 08a7740e - rgbImage = map.makeRgbImage(*rgbImages, xSize=xSize, ySize=ySize, rescaleFactor=frac)
    318 08a7740e -
    319 08a7740e - h, w = rgbImage.shape[0:2]
    320 08a7740e - self.assertTrue(xSize is None or xSize == w)
    321 08a7740e - self.assertTrue(ySize is None or ySize == h)
    322 08a7740e - self.assertTrue(frac is None or w == int(frac*self.images[R].getWidth()),
    323 08a7740e - "%g == %g" % (w, int((frac if frac else 1)*self.images[R].getWidth())))
    324 08a7740e -
    325 08a7740e - if display:
    326 08a7740e - rgb.displayRGB(rgbImage)
    327 08a7740e -
    328 08a7740e - @unittest.skipUnless(HAVE_SCIPY_MISC, "Resizing images requires scipy.misc")
    329 08a7740e - @unittest.skipUnless(HAVE_MATPLOTLIB, NO_MATPLOTLIB_STRING)
    330 08a7740e - def testMakeRGBResize(self):
    331 08a7740e - """Test the function that does it all, including rescaling"""
    332 08a7740e - fileName = "makeRGB.png"
    333 08a7740e -
    334 08a7740e - rgb.makeRGB(self.images[R], self.images[G], self.images[B], xSize=40, ySize=60)
    335 08a7740e -
    336 08a7740e - with Tempfile(fileName, remove=True):
    337 08a7740e - rgb.makeRGB(self.images[R], self.images[G], self.images[B], fileName=fileName, rescaleFactor=0.5)
    338 08a7740e - self.assertTrue(os.path.exists(fileName))
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- # # Test that the legacy API still works, although it's deprecated # def writeFileLegacyAPI(self, fileName): asinh = rgb.asinhMappingF(self.min, self.range, self.Q) rgbImage = rgb.RgbImageF(self.images[R], self.images[G], self.images[B], asinh) if False: ds9.mtv(self.images[B], frame=0, title="B") ds9.mtv(self.images[G], frame=1, title="G") ds9.mtv(self.images[R], frame=2, title="R") rgbImage.write(fileName)
    354 f49676d7 - @unittest.skipUnless(HAVE_MATPLOTLIB, NO_MATPLOTLIB_STRING)
    168 f5c92c2e + @unittest.skipUnless(HAVE_MATPLOTLIB, "Requires matplotlib >= 1.3.1")
    def testWriteStarsLegacyAPI(self):
    170 c605dfcd + with utilsTests.getTempFilePath(".png") as fileName:
    356 254d7248 - fileName = "rgb_legacyAPI.png"
    357 254d7248 - with Tempfile(fileName, remove=True):
    self.writeFileLegacyAPI(fileName)
    359 16cfe977 -
    360 254d7248 - if False:
    361 254d7248 - os.system("open %s > /dev/null 2>&1" % fileName)
    362 16cfe977 -
    363 f49676d7 - self.assertTrue(os.path.exists(fileName))
    def tst(): self.writeFileLegacyAPI("rgb.unknown")
    367 6295076e - self.assertRaises(ValueError, tst)
    ? ^^
    175 7e2503b6 + utilsTests.assertRaisesLsstCpp(self, ValueError, tst)
    ? ++++ + ^^^ +++++++ ++++++ #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(RgbTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    254d7248

    commit 254d7248ea20d98de481d968f6503d1610b16ae7
    Author: Jim Bosch 
    Date:   Thu Mar 19 12:31:48 2015 -0400
    
        Remove tests of writing rgb images to jpeg and tiff
        
        These depend on PIL, not vanilla matplotlib, and while they'll
        work when matplotlib was built against PIL, we don't want
        to require that.
    

    16cfe977

    commit 16cfe9776e35798afb73eab2a10ce798ab25dcca
    Author: Robert Lupton the Good 
    Date:   Mon Mar 16 18:01:42 2015 -0400
    
        Initial port/rewrite from afw_extensions_rgb
        
        With changes from code reviews squashed in
    

    88d838b7

    commit 88d838b74898d9572bbc8c46121da029958c1c72
    Author: Paul Price 
    Date:   Thu Mar 26 17:14:28 2015 -0400
    
        rgb: fix makeRGB so it can replace saturated pixels and produce an image
        
        Replacing saturated pixels requires that the input images to makeRGB
        be MaskedImages, but the Mapping.makeRgbImage didn't support
        MaskedImages.  Changed Mapping.makeRgbImage to support MaskedImages,
        fix variable names, check that saturatedPixelValue is set when
        replacing saturated pixels, and add test for makeRGB.
        
        Added checks that the code works for ImageU and ImageF, as well as MaskedImageF
    

    f49676d7

    commit f49676d7f1348f9de8ca21ee633e0c25473251ae
    Author: Robert Lupton the Good 
    Date:   Sun Apr 19 10:50:17 2015 -0300
    
        Implemented Linear and ZScale transformations, HSC-1206
        
        Linear was already available with Q=0, but this way is clearer; the default is to use min/max limits.
        
        I also added AsinhZScaleMapping which uses the zscale code to set the stretch.
        
        I did not port the log mappings, as the C++ is not really something I'd like to see in the long-term stack (e.g. reinterpret_casts between ints and doubles).
        It would be easy to add a LogMapper in pure python, and if this is needed please open a new issue.
        
        The ZScale code comes from Mineo-san's fitsthumb, but doesn't give quite the same upper limit as ds9.  I'm not sure where the discrepancy is, but I don't think it matters.
    

    08a7740e

    commit 08a7740ed756ee7b2c845b4ce6aed8d9a0f50d04
    Author: Robert Lupton the Good 
    Date:   Tue Apr 21 10:21:27 2015 -0400
    
        Added xSize, ySize, and rescaleFactor arguments to {make,write}RGB; HSC-1207
        
        N.b. requires scipy which is not a dependency of afw.
    

    6295076e

    commit 6295076e1f08c8b3bdde0e21a7adee46ec1bdb51
    Author: Robert Lupton the Good 
    Date:   Wed Mar 18 21:23:49 2015 -0700
    
        Changes to back out LSST changes with exception names and testing
    

    f73544e1

    commit f73544e15abd2760bf84794798cf4b84e97e938d
    Author: Robert Lupton the Good 
    Date:   Sat Apr 25 08:21:39 2015 -0400
    
        Add a test that not only does scipy.misc exist, but it also supports imresize
    

    Commits in /Users/nate/repos_lsst/afw/

    7e2503b6

    commit 7e2503b6b492a50a007c974e9a05a2cc64fd0138
    Author: Robert Lupton the Good 
    Date:   Mon Mar 16 18:01:42 2015 -0400
    
        Initial port/rewrite from afw_extensions_rgb
        
        With changes from code reviews squashed in
    

    f5c92c2e

    commit f5c92c2e020bc8f87b8209008190734d3ede13af
    Author: Jim Bosch 
    Date:   Thu Mar 19 12:12:24 2015 -0400
    
        Add optional dependency on matplotlib code, make tests conditional.
        
        The RGB code looks like it's just calling NumPy to save RGB(A)
        images, but NumPy is actually delegating to Matplotlib.  And
        that functionality is actually broken in Matplotlib prior to
        version 1.3.1.
    

    7e1ab7ff

    commit 7e1ab7ff2e5b3f085f5ed7c1cb189744d6428dcf
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:17:24 2015 -0400
    
        Conditionally skip test that requires matplotlib.
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    Return to list

    src/table/io/OutputArchive.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/format.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/table/io/ArchiveIndexSchema.h"
                    #include "lsst/afw/table/io/Persistable.h"
                    #include "lsst/afw/table/io/CatalogVector.h"
                    #include "lsst/afw/fits.h"
                    
                    namespace lsst { namespace afw { namespace table { namespace io {
                    
                    namespace {
                    
                    ArchiveIndexSchema const & indexKeys = ArchiveIndexSchema::get();
                    
                    typedef std::map Map;
                    
                    typedef Map::value_type MapItem;
                    
                    } // anonymous
                    
                    // ----- OutputArchive::Impl --------------------------------------------------------------------------------
                    
                    class OutputArchive::Impl {
                    public:
                    
                        BaseCatalog makeCatalog(Schema const & schema) {
                            int catArchive = 1;
                            CatalogVector::iterator iter = _catalogs.begin();
                            int const flags = table::Schema::EQUAL_KEYS | table::Schema::EQUAL_NAMES;
                            for (; iter != _catalogs.end(); ++iter, ++catArchive) {
                                if (iter->getSchema().compare(schema, flags) == flags) {
                                    break;
                                }
                            }
                            if (iter == _catalogs.end()) {
                                iter = _catalogs.insert(_catalogs.end(), BaseCatalog(schema));
                            }
                            if (!iter->getTable()->getMetadata()) {
                                PTR(daf::base::PropertyList) metadata(new daf::base::PropertyList());
                                iter->getTable()->setMetadata(metadata);
                                metadata->set("EXTTYPE", "ARCHIVE_DATA");
    
    49 504cf02b - metadata->set("EXTNAME", "ARCHIVE_DATA");
    metadata->set("AR_CATN", catArchive, "# of this catalog relative to the start of this archive"); } return BaseCatalog(iter->getTable()); } void saveCatalog( BaseCatalog const & catalog, int id, std::string const & name, std::string const & module, int catPersistable ) { PTR(BaseRecord) indexRecord = _index.addNew(); indexRecord->set(indexKeys.id, id); indexRecord->set(indexKeys.name, name); indexRecord->set(indexKeys.module, module); indexRecord->set(indexKeys.catPersistable, catPersistable); indexRecord->set(indexKeys.nRows, catalog.size()); int catArchive = 1; CatalogVector::iterator iter = _catalogs.begin(); for (; iter != _catalogs.end(); ++iter, ++catArchive) { if (iter->getTable() == catalog.getTable()) { break; } } if (iter == _catalogs.end()) { throw LSST_EXCEPT(
    75 4aaa02e3 - pex::exceptions::LogicErrorException,
    ? ---------
    74 21597d88 + pex::exceptions::LogicError,
    "All catalogs passed to saveCatalog must be created by makeCatalog" ); } iter->getTable()->getMetadata()->add("AR_NAME", name, "Class name for objects stored here"); indexRecord->set(indexKeys.row0, iter->size()); indexRecord->set(indexKeys.catArchive, catArchive); iter->insert(iter->end(), catalog.begin(), catalog.end(), false); } int put(Persistable const * obj, PTR(Impl) const & self, bool permissive) { if (!obj) return 0; if (permissive && !obj->isPersistable()) return 0; MapItem item(obj, _nextId); std::pair r = _map.insert(item); if (r.second) { ++_nextId; OutputArchiveHandle handle( r.first->second, obj->getPersistenceName(), obj->getPythonModule(), self ); obj->write(handle); } assert(r.first->first == obj); // either way we return the ID of the object in the archive return r.first->second; } void writeFits(fits::Fits & fitsfile) { _index.getTable()->getMetadata()->set("AR_NCAT", int(_catalogs.size() + 1), "# of catalogs in this archive, including the index"); _index.writeFits(fitsfile); int n = 1; for ( CatalogVector::const_iterator iter = _catalogs.begin(); iter != _catalogs.end(); ++iter, ++n ) { iter->writeFits(fitsfile); } } Impl() : _nextId(1), _map(), _index(ArchiveIndexSchema::get().schema) { PTR(daf::base::PropertyList) metadata(new daf::base::PropertyList()); metadata->set("EXTTYPE", "ARCHIVE_INDEX");
    119 504cf02b - metadata->set("EXTNAME", "ARCHIVE_INDEX");
    metadata->set("AR_CATN", 0, "# of this catalog relative to the start of this archive"); _index.getTable()->setMetadata(metadata); } int _nextId; Map _map; BaseCatalog _index; CatalogVector _catalogs; }; // ----- OutputArchive -------------------------------------------------------------------------------------- OutputArchive::OutputArchive() : _impl(new Impl()) {} OutputArchive::OutputArchive(OutputArchive const & other) : _impl(other._impl) {} OutputArchive & OutputArchive::operator=(OutputArchive const & other) { _impl = other._impl; return *this; } OutputArchive::~OutputArchive() {} int OutputArchive::put(Persistable const * obj, bool permissive) { if (!_impl.unique()) { // copy on write PTR(Impl) tmp(new Impl(*_impl)); _impl.swap(tmp); } return _impl->put(obj, _impl, permissive); } BaseCatalog const & OutputArchive::getIndexCatalog() const { return _impl->_index; } BaseCatalog const & OutputArchive::getCatalog(int n) const { if (n == 0) return _impl->_index; if (std::size_t(n) > _impl->_catalogs.size() || n < 0) { throw LSST_EXCEPT(
    159 4aaa02e3 - pex::exceptions::LengthErrorException,
    ? ---------
    157 21597d88 + pex::exceptions::LengthError,
    (boost::format("Catalog number %d is out of range [0,%d]") % n % _impl->_catalogs.size()).str() ); } return _impl->_catalogs[n-1]; } int OutputArchive::countCatalogs() const { return _impl->_catalogs.size() + 1; } void OutputArchive::writeFits(fits::Fits & fitsfile) const { _impl->writeFits(fitsfile); } // ----- OutputArchiveHandle ------------------------------------------------------------------------------ BaseCatalog OutputArchiveHandle::makeCatalog(Schema const & schema) { return _impl->makeCatalog(schema); } void OutputArchiveHandle::saveCatalog(BaseCatalog const & catalog) { _impl->saveCatalog(catalog, _id, _name, _module, _catPersistable); ++_catPersistable; } int OutputArchiveHandle::put(Persistable const * obj, bool permissive) { // Handle doesn't worry about copy-on-write, because Handles should only exist // while an OutputArchive::put() call is active. return _impl->put(obj, _impl, permissive); } OutputArchiveHandle::OutputArchiveHandle( int id, std::string const & name, std::string const & module, PTR(OutputArchive::Impl) impl) : _id(id), _catPersistable(0), _name(name), _module(module), _impl(impl) {} OutputArchiveHandle::~OutputArchiveHandle() {} }}}} // namespace lsst::afw::table::io

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4aaa02e3

    commit 4aaa02e3e38d04136492c4fcaed39ee875d98edd
    Author: Jim Bosch 
    Date:   Thu Dec 6 19:41:40 2012 -0500
    
        New interface for table-based persistence.
    

    504cf02b

    commit 504cf02b6a6c50b1614a9b6285e4155c8e30d2d2
    Author: Jim Bosch 
    Date:   Fri Mar 1 12:08:40 2013 +0900
    
        Set EXTNAME as well as EXTTYPE to descriptive names for HDUs; it seems to be more commonly interpreted by various FITS readers.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/table/Source.h.m4

    Diff:

                    changecom(`###')dnl
                    // -*- lsst-c++ -*-
    
    3 2cf33503 - /*
    ? -
    3 e1fc4de2 + /*
    * LSST Data Management System
    5 2cf33503 - * Copyright 2008, 2009, 2010, 2011 LSST Corporation.
    ? ^^^^^^^^ ^
    5 e1fc4de2 + * Copyright 2008-2014, 2011 LSST Corporation.
    ? ^ ^
    6 2cf33503 - *
    ? -
    6 e1fc4de2 + *
    * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
    14 2cf33503 - *
    ? -
    14 e1fc4de2 + *
    * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
    19 2cf33503 - *
    ? -
    19 e1fc4de2 + *
    20 2cf33503 - * You should have received a copy of the LSST License Statement and
    ? -
    20 e1fc4de2 + * You should have received a copy of the LSST License Statement and
    21 2cf33503 - * the GNU General Public License along with this program. If not,
    ? -
    21 e1fc4de2 + * the GNU General Public License along with this program. If not,
    * see . */ // THIS FILE IS AUTOMATICALLY GENERATED from Source.h.m4, AND WILL BE OVERWRITTEN IF EDITED MANUALLY. define(`m4def', defn(`define'))dnl m4def(`DECLARE_SLOT_GETTERS', `/// @brief Get the value of the $1$2 slot measurement.
    30 dbc20e58 - $2::MeasValue get$1$2() const;
    30 0c8edce7 + $2SlotDefinition::MeasValue get$1$2() const;
    ? ++++++++++++++ /// @brief Get the uncertainty on the $1$2 slot measurement.
    33 6581586d - $2::ErrValue get$1$2Err() const;
    33 0c8edce7 + $2SlotDefinition::ErrValue get$1$2Err() const;
    ? ++++++++++++++
    35 6581586d - /// @brief Return true if the measurement in the $1$2 slot was successful.
    ? ^ ^^^^^^ ^^^^^
    35 3375f4f0 + /// @brief Return true if the measurement in the $1$2 slot failed.
    ? ^ ^^ ^ bool get$1$2Flag() const; ')dnl
    38 6581586d - m4def(`DECLARE_FLUX_GETTERS', `DECLARE_SLOT_GETTERS($1, `Flux')')dnl
    39 6581586d - m4def(`DECLARE_CENTROID_GETTERS', `DECLARE_SLOT_GETTERS(`', `Centroid')')dnl
    40 6581586d - m4def(`DECLARE_SHAPE_GETTERS', `DECLARE_SLOT_GETTERS(`', `Shape')')dnl
    m4def(`DEFINE_SLOT_GETTERS',
    42 dbc20e58 - `inline $2::MeasValue SourceRecord::get$1$2() const {
    39 0c8edce7 + `inline $2SlotDefinition::MeasValue SourceRecord::get$1$2() const {
    ? ++++++++++++++
    43 03ea6486 - return this->get(getTable()->get$1$2Key());
    40 0c8edce7 + return this->get(getTable()->get$1$2Slot().getMeasKey());
    ? ++++++++++++++ }
    46 6581586d - inline $2::ErrValue SourceRecord::get$1$2Err() const {
    43 0c8edce7 + inline $2SlotDefinition::ErrValue SourceRecord::get$1$2Err() const {
    ? ++++++++++++++
    47 6581586d - return this->get(getTable()->get$1$2ErrKey());
    44 0c8edce7 + return this->get(getTable()->get$1$2Slot().getErrKey());
    ? ++++++++++ } inline bool SourceRecord::get$1$2Flag() const {
    51 6581586d - return this->get(getTable()->get$1$2FlagKey());
    48 0c8edce7 + return this->get(getTable()->get$1$2Slot().getFlagKey());
    ? ++++++++++ } ')dnl
    54 6581586d - m4def(`DEFINE_FLUX_GETTERS', `DEFINE_SLOT_GETTERS($1, `Flux')')dnl
    55 6581586d - m4def(`DEFINE_CENTROID_GETTERS', `DEFINE_SLOT_GETTERS(`', `Centroid')')dnl
    56 6581586d - m4def(`DEFINE_SHAPE_GETTERS', `DEFINE_SLOT_GETTERS(`', `Shape')')dnl
    m4def(`DECLARE_SLOT_DEFINERS',
    58 2cf33503 - `/**
    52 fbe6dc40 + `
    53 0c8edce7 + $2SlotDefinition const & get$1$2Slot() const { return _slots.def$1$2; }
    54 0c8edce7 +
    55 2063bd97 + /**
    59 2cf33503 - * @brief Set the measurement used for the $1$2 slot using Keys.
    ? -----------
    56 3375f4f0 + * @brief Set the measurement used for the $1$2 slot.
    ? +
    60 2cf33503 - */
    ? -
    57 2cf33503 + *
    58 3375f4f0 + * The definitions for slots are actually managed by the Schema object, and its associated
    59 3375f4f0 + * AliasMap, so this simply sets the "slot_$1$2" alias (or "slot.$1$2" for version 0 tables)
    60 3375f4f0 + * to point to the given field name prefix. See $2SlotDefinition for more information.
    61 2063bd97 - void define$1$2(
    62 2063bd97 - $2::MeasKey const & meas,
    63 2063bd97 - $2::ErrKey const & err = $2::ErrKey(),
    64 2063bd97 - Key const & flag = Key()
    65 2063bd97 - ) {
    66 6581586d - _slot$2$3 = KeyTuple<$2>(meas, err, flag);
    67 2cf33503 - }
    68 2cf33503 -
    69 2cf33503 - /**
    70 2063bd97 - * @brief Set the measurement used for the $1$2 slot using Keys.
    71 2063bd97 - */
    72 2063bd97 - void define$1$2(
    73 2063bd97 - $2::MeasKey const & meas,
    74 2063bd97 - Key const & flag
    75 2063bd97 - ) {
    76 2063bd97 - _slot$2$3 = KeyTuple<$2>(meas, $2::ErrKey(), flag);
    77 2063bd97 - }
    78 2063bd97 -
    79 2063bd97 - /**
    80 2cf33503 - * @brief Set the measurement used for the $1$2 slot with a field name.
    81 2cf33503 - *
    82 2cf33503 - * This requires that the measurement adhere to the convention of having
    83 734f09be - * "", ".err", and ".flags" fields for all three fields
    84 734f09be - * to be attached to slots. Only the main measurement field is required.
    */ void define$1$2(std::string const & name) {
    63 0c8edce7 + getSchema().getAliasMap()->set(get$1$2Slot().getAlias(getSchema().getVersion()), name);
    87 2cf33503 - Schema schema = getSchema();
    88 2063bd97 - _slot$2$3.meas = schema[name];
    89 2063bd97 - try {
    90 2063bd97 - _slot$2$3.err = schema[name]["err"];
    91 2063bd97 - } catch (pex::exceptions::NotFoundException) {}
    92 2063bd97 - try {
    93 2063bd97 - _slot$2$3.flag = schema[name]["flags"];
    94 2063bd97 - } catch (pex::exceptions::NotFoundException) {}
    }
    66 e1fc4de2 + /**
    97 2cf33503 - /// @brief Return the name of the field used for the $1$2 slot.
    ? ^^^
    67 e1fc4de2 + * @brief Return the name of the field used for the $1$2 slot.
    ? ^^^
    68 e1fc4de2 + *
    69 e5f4f916 + * @throw NotFoundError if the slot is not defined.
    70 0c8edce7 + *
    71 3375f4f0 + * @deprecated in favor of
    72 0c8edce7 + * @code
    73 3375f4f0 + * getSchema().getAliasMap()->get("slot_$1$2") # or "slot.$1$2" for version 0 tables
    74 0c8edce7 + * @endcode
    75 e1fc4de2 + */
    std::string get$1$2Definition() const {
    99 6581586d - return getSchema().find(_slot$2$3.meas).field.getName();
    77 0c8edce7 + return getSchema().getAliasMap()->get(get$1$2Slot().getAlias(getSchema().getVersion()));
    78 cf817499 + }
    79 cf817499 +
    80 0c8edce7 + /**
    81 e5f4f916 + * @brief Return true if the $1$2 slot corresponds to a valid field.
    100 2cf33503 - }
    ? ^
    82 0c8edce7 + *
    ? ^^
    83 0c8edce7 + * @deprecated in favor of get$1$2Slot().isValid().
    84 0c8edce7 + */
    85 cf817499 + bool has$1$2Slot() const {
    86 0c8edce7 + return get$1$2Slot().isValid();
    87 2cf33503 + }
    89 0c8edce7 + /**
    90 0c8edce7 + * @brief Return the key used for the $1$2 slot measurement value.
    91 0c8edce7 + *
    92 0c8edce7 + * @deprecated in favor of get$1$2Slot().getMeasKey().
    93 0c8edce7 + */
    94 0c8edce7 + $2SlotDefinition::MeasKey get$1$2Key() const {
    95 0c8edce7 + return get$1$2Slot().getMeasKey();
    96 21b6c7c5 + }
    97 2cf33503 +
    98 0c8edce7 + /**
    102 03ea6486 - /// @brief Return the key used for the $1$2 slot.
    ? ^^^
    99 3375f4f0 + * @brief Return the key used for the $1$2 slot uncertainty.
    ? ^^^ ++++++++++++
    103 6581586d - $2::MeasKey get$1$2Key() const { return _slot$2$3.meas; }
    100 0c8edce7 + *
    101 0c8edce7 + * @deprecated in favor of get$1$2Slot().getErrKey().
    102 0c8edce7 + */
    103 0c8edce7 + $2SlotDefinition::ErrKey get$1$2ErrKey() const {
    104 0c8edce7 + return get$1$2Slot().getErrKey();
    105 21b6c7c5 + }
    107 0c8edce7 + /**
    105 03ea6486 - /// @brief Return the key used for $1$2 slot error or covariance.
    106 6581586d - $2::ErrKey get$1$2ErrKey() const { return _slot$2$3.err; }
    107 6581586d -
    108 6581586d - /// @brief Return the key used for the $1$2 slot success flag.
    ? ^^^ ^ ^^ --
    108 0c8edce7 + * @brief Return the key used for the $1$2 slot failure flag.
    ? ^^^ ^^^^ ^
    109 0c8edce7 + *
    110 0c8edce7 + * @deprecated in favor of get$1$2Slot().getFlagKey().
    111 0c8edce7 + */
    109 6581586d - Key get$1$2FlagKey() const { return _slot$2$3.flag; }
    ? -------------------------
    112 21b6c7c5 + Key get$1$2FlagKey() const {
    113 0c8edce7 + return get$1$2Slot().getFlagKey();
    114 21b6c7c5 + }
    ')dnl
    111 6581586d - m4def(`DECLARE_FLUX_DEFINERS', `DECLARE_SLOT_DEFINERS($1, `Flux', `[FLUX_SLOT_`'translit($1, `a-z', `A-Z')]')')dnl
    112 6581586d - m4def(`DECLARE_CENTROID_DEFINERS', `DECLARE_SLOT_DEFINERS(`', `Centroid', `')')dnl
    113 6581586d - m4def(`DECLARE_SHAPE_DEFINERS', `DECLARE_SLOT_DEFINERS(`', `Shape', `')')dnl
    define(`m4def', defn(`define'))dnl m4def(`DEFINE_FLUX_COLUMN_GETTERS', `/// @brief Get the value of the $1Flux slot measurement. ndarray::Array get$1Flux() const {
    118 4ce9656b - return this->operator[](this->getTable()->get$1FluxKey());
    120 0c8edce7 + return this->operator[](this->getTable()->get$1FluxSlot().getMeasKey());
    ? ++++++++++++++ } /// @brief Get the uncertainty on the $1Flux slot measurement. ndarray::Array get$1FluxErr() const {
    122 4ce9656b - return this->operator[](this->getTable()->get$1FluxErrKey());
    124 0c8edce7 + return this->operator[](this->getTable()->get$1FluxSlot().getErrKey());
    ? ++++++++++ } ')dnl #ifndef AFW_TABLE_Source_h_INCLUDED #define AFW_TABLE_Source_h_INCLUDED #include "boost/array.hpp" #include "boost/type_traits/is_convertible.hpp"
    133 4633b1d0 + #include "lsst/utils/ieee.h"
    #include "lsst/afw/detection/Footprint.h" #include "lsst/afw/table/Simple.h"
    136 5e98dbb9 + #include "lsst/afw/table/aggregates.h"
    #include "lsst/afw/table/IdFactory.h" #include "lsst/afw/table/Catalog.h" #include "lsst/afw/table/BaseColumnView.h"
    140 0c8edce7 + #include "lsst/afw/table/slots.h"
    #include "lsst/afw/table/io/FitsWriter.h" namespace lsst { namespace afw { namespace image { class Wcs; } // namespace image namespace table { /** * @brief Bitflags to be passed to SourceCatalog::readFits and SourceCatalog::writeFits * * Note that these flags may also be passed when reading/writing SourceCatalogs via the Butler, * by passing a "flags" key/value pair as part of the data ID. */ enum SourceFitsFlags { SOURCE_IO_NO_FOOTPRINTS = 0x1, ///< Do not read/write footprints at all SOURCE_IO_NO_HEAVY_FOOTPRINTS = 0x2 ///< Read/write heavy footprints as non-heavy footprints }; typedef lsst::afw::detection::Footprint Footprint; class SourceRecord; class SourceTable;
    161 447cb7df -
    162 d6480e01 - /// @brief A collection of types that correspond to common measurements.
    163 3e1f9e0b - template
    164 3e1f9e0b - struct Measurement {
    165 d6480e01 - typedef MeasTagT MeasTag; ///< the tag (template parameter) type used for the measurement
    166 d6480e01 - typedef ErrTagT ErrTag; ///< the tag (template parameter) type used for the uncertainty
    167 d6480e01 - typedef typename Field::Value MeasValue; ///< the value type used for the measurement
    168 d6480e01 - typedef typename Field::Value ErrValue; ///< the value type used for the uncertainty
    169 d6480e01 - typedef Key MeasKey; ///< the Key type for the actual measurement
    170 d6480e01 - typedef Key ErrKey; ///< the Key type for the error on the measurement
    171 3e1f9e0b - };
    172 3e1f9e0b -
    173 3e1f9e0b - #ifndef SWIG
    174 3e1f9e0b -
    175 d6480e01 - /// A collection of types useful for flux measurement algorithms.
    176 2cf33503 - struct Flux : public Measurement {};
    177 d6480e01 -
    178 d6480e01 - /// A collection of types useful for centroid measurement algorithms.
    179 36b29961 - struct Centroid : public Measurement< Point, Covariance< Point > > {};
    180 d6480e01 -
    181 d6480e01 - /// A collection of types useful for shape measurement algorithms.
    182 36b29961 - struct Shape : public Measurement< Moments, Covariance< Moments > > {};
    183 3e1f9e0b -
    184 d6480e01 - /// An enum for all the special flux aliases in Source.
    185 2cf33503 - enum FluxSlotEnum {
    186 2cf33503 - FLUX_SLOT_PSF=0,
    187 2cf33503 - FLUX_SLOT_MODEL,
    188 2cf33503 - FLUX_SLOT_AP,
    189 2cf33503 - FLUX_SLOT_INST,
    190 62ae3464 - FLUX_SLOT_CALIB,
    191 2cf33503 - N_FLUX_SLOTS
    192 3e1f9e0b - };
    193 d6480e01 - /**
    194 d6480e01 - * @brief A three-element tuple of measurement, uncertainty, and flag keys.
    195 d6480e01 - *
    196 d6480e01 - * Most measurement should have more than one flag key to indicate different kinds of failures.
    197 d6480e01 - * This flag key should usually be set to be a logical OR of all of them, so it is set whenever
    198 d6480e01 - * a measurement cannot be fully trusted.
    199 d6480e01 - */
    200 3e1f9e0b - template
    201 6581586d - struct KeyTuple {
    202 d6480e01 - typename MeasurementT::MeasKey meas; ///< Key used for the measured value.
    203 d6480e01 - typename MeasurementT::ErrKey err; ///< Key used for the uncertainty.
    204 d6480e01 - Key flag; ///< Failure bit; set if the measurement did not fully succeed.
    205 3e1f9e0b -
    206 d6480e01 - /// Default-constructor; all keys will be invalid.
    207 6581586d - KeyTuple() {}
    208 3e1f9e0b -
    209 d6480e01 - /// Main constructor.
    210 6581586d - KeyTuple(
    211 3e1f9e0b - typename MeasurementT::MeasKey const & meas_,
    212 6581586d - typename MeasurementT::ErrKey const & err_,
    213 6581586d - Key const & flag_
    214 6581586d - ) : meas(meas_), err(err_), flag(flag_) {}
    215 6581586d -
    216 3e1f9e0b - };
    217 3e1f9e0b -
    218 6581586d - /// Convenience function to setup fields for centroid measurement algorithms.
    219 6581586d - KeyTuple addCentroidFields(Schema & schema, std::string const & name, std::string const & doc);
    220 6581586d -
    221 6581586d - /// Convenience function to setup fields for shape measurement algorithms.
    222 6581586d - KeyTuple addShapeFields(Schema & schema, std::string const & name, std::string const & doc);
    223 6581586d -
    224 6581586d - /// Convenience function to setup fields for flux measurement algorithms.
    225 6581586d - KeyTuple addFluxFields(Schema & schema, std::string const & name, std::string const & doc);
    226 6581586d -
    227 3e1f9e0b - #endif // !SWIG
    template class SourceColumnViewT; /** * @brief Record class that contains measurements made on a single exposure. * * Sources provide four additions to SimpleRecord / SimpleRecord: * - Specific fields that must always be present, with specialized getters. * The schema for a SourceTable should always be constructed by starting with the result of * SourceTable::makeMinimalSchema. * - A shared_ptr to a Footprint for each record. * - A system of aliases (called slots) in which a SourceTable instance stores keys for particular * measurements (a centroid, a shape, and a number of different fluxes) and SourceRecord uses * this keys to provide custom getters and setters. These are not separate fields, but rather
    242 d6480e01 - * aliases that can point to custom fields.
    180 3375f4f0 + * aliases that can point to custom fields. See the SlotDefinition hierarchy for more information.
    */ class SourceRecord : public SimpleRecord { public: typedef SourceTable Table; typedef SourceColumnViewT ColumnView; typedef SortedCatalogT Catalog; typedef SortedCatalogT ConstCatalog; PTR(Footprint) getFootprint() const { return _footprint; } void setFootprint(PTR(Footprint) const & footprint) { _footprint = footprint; } CONST_PTR(SourceTable) getTable() const { return boost::static_pointer_cast(BaseRecord::getTable()); } //@{ /// @brief Convenience accessors for the keys in the minimal source schema. RecordId getParent() const; void setParent(RecordId id); //@}
    266 dbc20e58 - DECLARE_FLUX_GETTERS(`Psf')
    ? ^ ^^
    204 0c8edce7 + DECLARE_SLOT_GETTERS(`Psf', `Flux')
    ? ^ ^^ ++++++++
    267 dbc20e58 - DECLARE_FLUX_GETTERS(`Model')
    ? ^ ^^
    205 0c8edce7 + DECLARE_SLOT_GETTERS(`Model', `Flux')
    ? ^ ^^ ++++++++
    268 dbc20e58 - DECLARE_FLUX_GETTERS(`Ap')
    ? ^ ^^
    206 0c8edce7 + DECLARE_SLOT_GETTERS(`Ap', `Flux')
    ? ^ ^^ ++++++++
    269 dbc20e58 - DECLARE_FLUX_GETTERS(`Inst')
    ? ^ ^^
    207 0c8edce7 + DECLARE_SLOT_GETTERS(`Inst', `Flux')
    ? ^ ^^ ++++++++
    208 0c8edce7 + DECLARE_SLOT_GETTERS(`', `Centroid')
    270 62ae3464 - DECLARE_FLUX_GETTERS(`Calib')
    ? ^ ^^ ^ ^^^
    209 0c8edce7 + DECLARE_SLOT_GETTERS(`', `Shape')
    ? ^ ^^ ^^^^^^ ^^
    271 dbc20e58 - DECLARE_CENTROID_GETTERS
    272 dbc20e58 - DECLARE_SHAPE_GETTERS
    /// @brief Return the centroid slot x coordinate. double getX() const; /// @brief Return the centroid slot y coordinate. double getY() const; /// @brief Return the shape slot Ixx value. double getIxx() const; /// @brief Return the shape slot Iyy value. double getIyy() const; /// @brief Return the shape slot Ixy value. double getIxy() const; /// @brief Update the coord field using the given Wcs and the field in the centroid slot. void updateCoord(image::Wcs const & wcs); /// @brief Update the coord field using the given Wcs and the image center from the given key. void updateCoord(image::Wcs const & wcs, Key< Point > const & key); protected: SourceRecord(PTR(SourceTable) const & table); virtual void _assign(BaseRecord const & other); private: PTR(Footprint) _footprint; }; /** * @brief Table class that contains measurements made on a single exposure. * * @copydetails SourceRecord */ class SourceTable : public SimpleTable { public: typedef SourceRecord Record; typedef SourceColumnViewT ColumnView; typedef SortedCatalogT Catalog; typedef SortedCatalogT ConstCatalog; /** * @brief Construct a new table. * * @param[in] schema Schema that defines the fields, offsets, and record size for the table. * @param[in] idFactory Factory class to generate record IDs when they are not explicitly given. * If null, record IDs will default to zero. * * Note that not passing an IdFactory at all will call the other override of make(), which will * set the ID factory to IdFactory::makeSimple(). */ static PTR(SourceTable) make(Schema const & schema, PTR(IdFactory) const & idFactory); /** * @brief Construct a new table. * * @param[in] schema Schema that defines the fields, offsets, and record size for the table. * * This overload sets the ID factory to IdFactory::makeSimple(). */ static PTR(SourceTable) make(Schema const & schema) { return make(schema, IdFactory::makeSimple()); } /** * @brief Return a minimal schema for Source tables and records. * * The returned schema can and generally should be modified further, * but many operations on sources will assume that at least the fields * provided by this routine are present. * * Keys for the standard fields added by this routine can be obtained * from other static member functions of the SourceTable class. */
    349 dbc20e58 - static Schema makeMinimalSchema() { return getMinimalSchema().schema; }
    286 af38dfb3 + static Schema makeMinimalSchema() {
    287 af38dfb3 + Schema r = getMinimalSchema().schema;
    288 af38dfb3 + r.disconnectAliases();
    289 af38dfb3 + return r;
    290 af38dfb3 + }
    /** * @brief Return true if the given schema is a valid SourceTable schema.
    353 dbc20e58 - *
    ? --
    294 e1fc4de2 + *
    * This will always be true if the given schema was originally constructed * using makeMinimalSchema(), and will rarely be true otherwise. */ static bool checkSchema(Schema const & other) { return other.contains(getMinimalSchema().schema); } /// @brief Key for the parent ID. static Key getParentKey() { return getMinimalSchema().parent; } /// @copydoc BaseTable::clone PTR(SourceTable) clone() const { return boost::static_pointer_cast(_clone()); } /// @copydoc BaseTable::makeRecord PTR(SourceRecord) makeRecord() { return boost::static_pointer_cast(_makeRecord()); } /// @copydoc BaseTable::copyRecord PTR(SourceRecord) copyRecord(BaseRecord const & other) { return boost::static_pointer_cast(BaseTable::copyRecord(other)); } /// @copydoc BaseTable::copyRecord PTR(SourceRecord) copyRecord(BaseRecord const & other, SchemaMapper const & mapper) { return boost::static_pointer_cast(BaseTable::copyRecord(other, mapper)); }
    380 dbc20e58 - DECLARE_FLUX_DEFINERS(`Psf')
    ? ^ ^^
    321 0c8edce7 + DECLARE_SLOT_DEFINERS(`Psf', `Flux')
    ? ^ ^^ ++++++++
    381 dbc20e58 - DECLARE_FLUX_DEFINERS(`Model')
    ? ^ ^^
    322 0c8edce7 + DECLARE_SLOT_DEFINERS(`Model', `Flux')
    ? ^ ^^ ++++++++
    382 dbc20e58 - DECLARE_FLUX_DEFINERS(`Ap')
    ? ^ ^^
    323 0c8edce7 + DECLARE_SLOT_DEFINERS(`Ap', `Flux')
    ? ^ ^^ ++++++++
    383 dbc20e58 - DECLARE_FLUX_DEFINERS(`Inst')
    ? ^ ^^
    324 0c8edce7 + DECLARE_SLOT_DEFINERS(`Inst', `Flux')
    ? ^ ^^ ++++++++
    325 0c8edce7 + DECLARE_SLOT_DEFINERS(`', `Centroid')
    384 62ae3464 - DECLARE_FLUX_DEFINERS(`Calib')
    ? ^ ^^ ^ ^^^
    326 0c8edce7 + DECLARE_SLOT_DEFINERS(`', `Shape')
    ? ^ ^^ ^^^^^^ ^^
    385 dbc20e58 - DECLARE_CENTROID_DEFINERS
    386 dbc20e58 - DECLARE_SHAPE_DEFINERS
    protected: SourceTable(Schema const & schema, PTR(IdFactory) const & idFactory); SourceTable(SourceTable const & other);
    333 73c4ab11 +
    334 e1fc4de2 + virtual void handleAliasChange(std::string const & alias);
    private: // Struct that holds the minimal schema and the special keys we've added to it. struct MinimalSchema { Schema schema; Key parent; MinimalSchema(); };
    403 dbc20e58 -
    345 e1fc4de2 +
    // Return the singleton minimal schema. static MinimalSchema & getMinimalSchema(); friend class io::FitsWriter;
    350 0c8edce7 + friend class SourceRecord;
    // Return a writer object that knows how to save in FITS format. See also FitsWriter. virtual PTR(io::FitsWriter) makeFitsWriter(fits::Fits * fitsfile, int flags) const;
    355 0c8edce7 + SlotSuite _slots;
    412 d6480e01 - boost::array< KeyTuple, N_FLUX_SLOTS > _slotFlux; // aliases for flux measurements
    413 d6480e01 - KeyTuple _slotCentroid; // alias for a centroid measurement
    414 d6480e01 - KeyTuple _slotShape; // alias for a shape measurement
    }; template class SourceColumnViewT : public ColumnViewT { public: typedef RecordT Record; typedef typename RecordT::Table Table; // See the documentation for BaseColumnView for an explanation of why these // accessors *appear* to violate const-correctness. DEFINE_FLUX_COLUMN_GETTERS(`Psf') DEFINE_FLUX_COLUMN_GETTERS(`Ap') DEFINE_FLUX_COLUMN_GETTERS(`Model') DEFINE_FLUX_COLUMN_GETTERS(`Inst')
    431 62ae3464 - DEFINE_FLUX_COLUMN_GETTERS(`Calib')
    ndarray::Array const getX() const { return this->operator[](this->getTable()->getCentroidKey().getX()); } ndarray::Array const getY() const { return this->operator[](this->getTable()->getCentroidKey().getY()); } ndarray::Array const getIxx() const { return this->operator[](this->getTable()->getShapeKey().getIxx()); } ndarray::Array const getIyy() const { return this->operator[](this->getTable()->getShapeKey().getIyy()); } ndarray::Array const getIxy() const { return this->operator[](this->getTable()->getShapeKey().getIxy()); } /// @brief @copydoc BaseColumnView::make template static SourceColumnViewT make(PTR(Table) const & table, InputIterator first, InputIterator last) { return SourceColumnViewT(BaseColumnView::make(table, first, last)); } protected: explicit SourceColumnViewT(BaseColumnView const & base) : ColumnViewT(base) {} }; typedef SourceColumnViewT SourceColumnView; #ifndef SWIG
    464 dbc20e58 - DEFINE_FLUX_GETTERS(`Psf')
    ? ^ ^^
    404 0c8edce7 + DEFINE_SLOT_GETTERS(`Psf', `Flux')
    ? ^ ^^ ++++++++
    465 dbc20e58 - DEFINE_FLUX_GETTERS(`Model')
    ? ^ ^^
    405 0c8edce7 + DEFINE_SLOT_GETTERS(`Model', `Flux')
    ? ^ ^^ ++++++++
    466 dbc20e58 - DEFINE_FLUX_GETTERS(`Ap')
    ? ^ ^^
    406 0c8edce7 + DEFINE_SLOT_GETTERS(`Ap', `Flux')
    ? ^ ^^ ++++++++
    467 dbc20e58 - DEFINE_FLUX_GETTERS(`Inst')
    ? ^ ^^
    407 0c8edce7 + DEFINE_SLOT_GETTERS(`Inst', `Flux')
    ? ^ ^^ ++++++++
    408 0c8edce7 + DEFINE_SLOT_GETTERS(`', `Centroid')
    409 0c8edce7 + DEFINE_SLOT_GETTERS(`', `Shape')
    468 62ae3464 - DEFINE_FLUX_GETTERS(`Calib')
    469 dbc20e58 - DEFINE_CENTROID_GETTERS
    470 dbc20e58 - DEFINE_SHAPE_GETTERS
    inline RecordId SourceRecord::getParent() const { return get(SourceTable::getParentKey()); } inline void SourceRecord::setParent(RecordId id) { set(SourceTable::getParentKey(), id); }
    474 3e1f9e0b -
    475 6581586d - inline double SourceRecord::getX() const { return get(getTable()->getCentroidKey().getX()); }
    476 6581586d - inline double SourceRecord::getY() const { return get(getTable()->getCentroidKey().getY()); }
    477 6581586d -
    478 9539ab2c - inline double SourceRecord::getIxx() const { return get(getTable()->getShapeKey().getIxx()); }
    479 9539ab2c - inline double SourceRecord::getIyy() const { return get(getTable()->getShapeKey().getIyy()); }
    480 9539ab2c - inline double SourceRecord::getIxy() const { return get(getTable()->getShapeKey().getIxy()); }
    413 5e98dbb9 + inline double SourceRecord::getX() const {
    414 cf817499 + return get(getTable()->getCentroidKey().getX());
    415 5e98dbb9 + }
    416 5e98dbb9 + inline double SourceRecord::getY() const {
    417 e1fc4de2 + return get(getTable()->getCentroidKey().getY());
    418 5e98dbb9 + }
    419 5e98dbb9 + inline double SourceRecord::getIxx() const {
    420 e1fc4de2 + return get(getTable()->getShapeKey().getIxx());
    421 5e98dbb9 + }
    422 5e98dbb9 + inline double SourceRecord::getIyy() const {
    423 e1fc4de2 + return get(getTable()->getShapeKey().getIyy());
    424 5e98dbb9 + }
    425 5e98dbb9 + inline double SourceRecord::getIxy() const {
    426 e1fc4de2 + return get(getTable()->getShapeKey().getIxy());
    427 5e98dbb9 + }
    #endif // !SWIG }}} // namespace lsst::afw::table #endif // !AFW_TABLE_Source_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3e1f9e0b

    commit 3e1f9e0b78f337ea33e6fef04ba5e24c2eb5a47f
    Author: Jim Bosch 
    Date:   Wed Jan 11 16:58:43 2012 -0500
    
        added configurable canonical fields to SourceTable/SourceRecord, renamed Shape tag class to Moments to avoid collisions with long-standing measurement names.
    

    734f09be

    commit 734f09be4debdb9de1f521141c6a128e6ed96f8c
    Author: Jim Bosch 
    Date:   Tue Aug 28 16:01:27 2012 -0400
    
        improve doxygen comments for SourceTable::define(string)
    

    36b29961

    commit 36b2996182c10928602622e87542fbf7d0d6a2ec
    Author: Jim Bosch 
    Date:   Wed Nov 21 17:09:31 2012 -0500
    
        Make all afw::table covariance matrices single-precision.
        
        It's a good idea in general (see #1998), and it also frees up space for other field types inside boost::variant's unfortunate 20-type limit (it'd be nice to get rid of that; maybe C++11 would help?)
        
        FITS reading is backwards compatible in that double-precision covariance fields previously saved to FITS will be read in as single precision.
    

    62ae3464

    commit 62ae3464e75d4dbd7f7ee3e3ddcc9b3a941f880c
    Author: Jim Bosch 
    Date:   Mon Dec 8 21:19:28 2014 -0500
    
        Add Source slot for calibration fluxes: CalibFlux
    

    2063bd97

    commit 2063bd97bc6beceb2509ce1606c63c7d0d5e8d0c
    Author: Jim Bosch 
    Date:   Fri Jun 29 16:59:50 2012 -0400
    
        allow table slots to be partially defined (only measurement key is required)
    

    4ce9656b

    commit 4ce9656bc5d7ec5c4612f98f33ca2a5288e38383
    Author: Jim Bosch 
    Date:   Wed May 22 12:17:01 2013 -0400
    
        Add column getters for flux slot error fields (#2889).
    

    9539ab2c

    commit 9539ab2c1305c07ef4c180bc50e923e51612dcc1
    Author: Jim Bosch 
    Date:   Thu Feb 2 11:52:46 2012 -0500
    
        renamed getIXX, etc. to getIxx in Quadrupole and new Source to match old Source and naming standards
    

    2cf33503

    commit 2cf33503feb13b45c362d6b1d9fc16e74eafc9df
    Author: Jim Bosch 
    Date:   Fri Jan 20 18:31:39 2012 -0500
    
        added Angle and Coord field types, reworked Source measurement slots
    

    03ea6486

    commit 03ea6486684bf284f7428c2f7cec0fc15b7c6172
    Author: Jim Bosch 
    Date:   Thu Jan 26 18:11:15 2012 -0500
    
        afw now building successfully, but with limited SWIG for table and corresponding unit test failures
    

    d6480e01

    commit d6480e01cf98ec6e6ebea9b7f58d2d9dcef6beef
    Author: Jim Bosch 
    Date:   Sun Feb 5 23:11:25 2012 -0500
    
        lots of documentation, and a little refactoring to improve readability
    

    447cb7df

    commit 447cb7df271bd7e661769156ed26b4a140fe50fc
    Author: Jim Bosch 
    Date:   Fri Dec 23 13:29:41 2011 -0800
    
        added SourceTable/Record (still needs footprint serialization)
    

    dbc20e58

    commit dbc20e585ec07b70b8c9dc3bbf9707ee3c200480
    Author: Jim Bosch 
    Date:   Wed Jan 25 20:07:49 2012 -0500
    
        lots of shuffling code around.  FITS table support now much better organized
    

    6581586d

    commit 6581586d25bea008aadd57a10968ca6c9fb72677
    Author: Jim Bosch 
    Date:   Mon Jan 30 01:09:10 2012 -0500
    
        fixed bug in schema key-based lookups, added flag fields to standard measurements
    

    Commits in /Users/nate/repos_lsst/afw/

    cf817499

    commit cf81749982b5994bcd65320573e3449cba9eafeb
    Author: pgee 
    Date:   Tue Jul 15 14:57:10 2014 -0700
    
        Changes for DM-936, using functor keys for compound slot fields
        
        Changes the return types of getCentroidKey, getCentroidErrKey, getShapeKey, getShapeErrKey to functor keys.
        Constructs functor keys from normal field keys for version 0 tables.
        Get rid of defineSlot calls which take keys as parameters.  Only defineSlot(std::string name) can be used.
        Slot must now have the same base name for all fields which comprise the slot.
        Change default table type in BaseTable from version 0 to version 1 (this is for testing
    

    e5f4f916

    commit e5f4f9164b6b652de70260d8e361c390f545c0ad
    Author: Jim Bosch 
    Date:   Thu Sep 4 21:02:04 2014 -0400
    
        Doc fixes from review of DM-419.
    

    21b6c7c5

    commit 21b6c7c558fbaefefc57b876facf02fe6bd98bf0
    Author: Perry Gee 
    Date:   Thu Apr 24 19:58:36 2014 -0500
    
        Code for slots using new flattened table structure.  This is still without functorKeys.
    

    5e98dbb9

    commit 5e98dbb9508b4a0a6b3578d6bf9572b8f6380c5c
    Author: Perry Gee 
    Date:   Fri Apr 25 19:33:24 2014 -0500
    
        New unit test for DM-433.
        Fix unit tests to work with new table versioning system.
        Note:  these old tests just setVersion(0) for now.
    

    2063bd97

    commit 2063bd97bc6beceb2509ce1606c63c7d0d5e8d0c
    Author: Jim Bosch 
    Date:   Fri Jun 29 16:59:50 2012 -0400
    
        allow table slots to be partially defined (only measurement key is required)
    

    af38dfb3

    commit af38dfb301ac07e9a48bfdcaf28140d730eb650c
    Author: Jim Bosch 
    Date:   Fri Nov 21 16:00:24 2014 -0600
    
        Disconnect aliases from minimal schemas
        
        Aliases are shared when Schemas are copied, which is usually desirable,
        but the makeMinimalSchema need to return new Schemas with a fresh set
        of aliases, or we end up with a lot of confusing behavior as one piece
        of code tries to set an alias and affects a completely different one,
        via a shared AliasMap they both got from the minimal schema.
    

    0c8edce7

    commit 0c8edce7dfb2db4539497ac18187e75d2494f4e4
    Author: Jim Bosch 
    Date:   Mon Aug 25 01:48:39 2014 -0400
    
        Switch to new slot definition classes, using aliases for version>0
    

    2cf33503

    commit 2cf33503feb13b45c362d6b1d9fc16e74eafc9df
    Author: Jim Bosch 
    Date:   Fri Jan 20 18:31:39 2012 -0500
    
        added Angle and Coord field types, reworked Source measurement slots
    

    73c4ab11

    commit 73c4ab11ebea2fcff4194194d461119d6aa35dbb
    Author: Jim Bosch 
    Date:   Fri Jan 13 15:37:05 2012 -0500
    
        added default ctor to Tables, some doc fixes in Source
    

    fbe6dc40

    commit fbe6dc4041a65f8b7fb0d57c1bd7e3d24a2b57c1
    Author: pgee 
    Date:   Mon Jul 21 08:14:14 2014 -0700
    
        Fix problem with SWIG types when Source.h routines return functorKeys.  Also, remove extra /* from a previous checkin.
    

    4633b1d0

    commit 4633b1d0f6816262e2957b3fb1e3e5e0c373173b
    Author: Perry Gee 
    Date:   Thu May 8 15:59:02 2014 -0500
    
        Temporary change to getCentroid to use peak on error
    

    e1fc4de2

    commit e1fc4de2138439c6b6e81ef34b15b92da48d3566
    Author: Jim Bosch 
    Date:   Mon Aug 18 16:58:07 2014 -0400
    
        Remove old slot definers from SourceTable
    

    3375f4f0

    commit 3375f4f00ea16c21651157fd1e3d49aaf5e448f5
    Author: Jim Bosch 
    Date:   Tue Sep 2 17:06:08 2014 -0400
    
        Improved documentation for slots
    

    Return to list

    python/lsst/afw/geom/LinearTransform.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    %{
                    #include "lsst/afw/geom/LinearTransform.h"
                    %}
                    
                    %declareNumPyConverters(lsst::afw::geom::LinearTransform::ParameterVector);
                    %declareNumPyConverters(lsst::afw::geom::LinearTransform::Matrix);
                    %declareNumPyConverters(Eigen::Vector2d);
                    %declareNumPyConverters(Eigen::Matrix2d);
                    %declareNumPyConverters(Eigen::Matrix3d);
                    
                    %shared_ptr(lsst::afw::geom::LinearTransform);
                    
                    %rename(__mul__) lsst::afw::geom::LinearTransform::operator*;
                    %ignore lsst::afw::geom::LinearTransform::operator[];
                    %ignore lsst::afw::geom::LinearTransform::dTransform;
                    %ignore lsst::afw::geom::LinearTransform::operator=;
                    
                    %copyctor lsst::afw::geom::LinearTransform;
                    %newobject lsst::afw::geom::LinearTransform::makeRotation;
                    %newobject lsst::afw::geom::LinearTransform::makeScaling;
                    %newobject lsst::afw::geom::LinearTransform::invert;
                    
                    %include "lsst/afw/geom/Angle.i"
                    %include "lsst/afw/geom/LinearTransform.h"
                    
                    %extend lsst::afw::geom::LinearTransform {    
                        void set(double xx, double yx, double xy, double yy) {
                            (*self)[lsst::afw::geom::LinearTransform::XX] = xx;
                            (*self)[lsst::afw::geom::LinearTransform::XY] = xy;        
                            (*self)[lsst::afw::geom::LinearTransform::YX] = yx; 
                            (*self)[lsst::afw::geom::LinearTransform::YY] = yy;       
                        }
                        
                        %feature("shadow") _setitem_nochecking %{
                            def __setitem__(self, k, v):
                                if k < 0 or k > 3: raise IndexError
                                $action(self, k, v)
                        %} 
                        void _setitem_nochecking(int i, double value) {
                            self->operator[](i) = value;
                        }
                    
                            
                        %feature("shadow") _getitem_nochecking %{
                            def __getitem__(self, k):
                                try:
                                    i,j = k
                                    if i < 0 or i > 1: raise IndexError
                                    if j < 0 or j > 1: raise IndexError
                                    return $action(self, i,j)
                                except TypeError:
                                    if k < 0 or k > 3: raise IndexError
                                    return $action(self, k)
                    
                        %}
                        double _getitem_nochecking(int row, int col) {
                            return (self->getMatrix())(row, col);
                        }
                        double _getitem_nochecking(int i) {
                            return self->operator[](i);
                        }   
                             
    
    86 95d17565 - %pythoncode {
    86 81c3bd10 + %pythoncode %{
    ? + def __str__(self): return str(self.getMatrix()) def __reduce__(self): return (LinearTransform, (self.getMatrix(),)) def __repr__(self): return "LinearTransform(\n%r\n)" % (self.getMatrix(),)
    93 95d17565 - }
    93 81c3bd10 + %}
    ? + }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    95d17565

    commit 95d1756551e9b95838e816f351f3f425a06cfc47
    Author: dubcovsky 
    Date:   Wed Mar 17 22:02:57 2010 +0000
    
        #1169 merged to trunk
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    src/table/io/Persistable.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    #include 
                    
                    #include "lsst/base/ModuleImporter.h"
                    #include "lsst/afw/table/io/Persistable.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/table/io/InputArchive.h"
                    #include "lsst/afw/fits.h"
                    
                    namespace lsst { namespace afw { namespace table { namespace io {
                    
                    // ----- Persistable ----------------------------------------------------------------------------------------
                    
                    void Persistable::writeFits(fits::Fits & fitsfile) const {
                        OutputArchive archive;
                        archive.put(this);
                        archive.writeFits(fitsfile);
                    }
                    
                    void Persistable::writeFits(std::string const & fileName, std::string const & mode) const {
                        fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
                        writeFits(fitsfile);
                    }
                    
                    void Persistable::writeFits(fits::MemFileManager & manager, std::string const & mode) const {
                        fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
                        writeFits(fitsfile);
                    }
                    
                    std::string Persistable::getPersistenceName() const { return std::string(); }
                    
                    std::string Persistable::getPythonModule() const { return std::string(); }
                    
                    void Persistable::write(OutputArchiveHandle &) const {
                        assert(!isPersistable());
                        throw LSST_EXCEPT(
    
    38 4aaa02e3 - pex::exceptions::LogicErrorException,
    ? ---------
    38 21597d88 + pex::exceptions::LogicError,
    "afw::table-based persistence is not supported for this object." ); } PTR(Persistable) Persistable::_readFits(std::string const & fileName, int hdu) { fits::Fits fitsfile(fileName, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); fitsfile.setHdu(hdu); return _readFits(fitsfile); } PTR(Persistable) Persistable::_readFits(fits::MemFileManager & manager, int hdu) { fits::Fits fitsfile(manager, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); fitsfile.setHdu(hdu); return _readFits(fitsfile); } PTR(Persistable) Persistable::_readFits(fits::Fits & fitsfile) { InputArchive archive = InputArchive::readFits(fitsfile); return archive.get(1); // the first object saved always has id=1 } // ----- PersistableFactory --------------------------------------------------------------------------------- namespace { typedef std::map RegistryMap; RegistryMap & getRegistry() { static RegistryMap instance; return instance; } } // anonymous PersistableFactory::PersistableFactory(std::string const & name) { getRegistry()[name] = this; } PersistableFactory const & PersistableFactory::lookup(std::string const & name, std::string const & module) { RegistryMap::const_iterator i = getRegistry().find(name); if (i == getRegistry().end()) { if (!module.empty()) { bool success = base::ModuleImporter::import(module); if (!success) { throw LSST_EXCEPT(
    84 69c970f2 - pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    84 21597d88 + pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("PersistableFactory with name '%s' not found, and import of module " "'%s' failed (possibly because Python calls were not available from C++).") % name % module).str() ); } i = getRegistry().find(name); if (i == getRegistry().end()) { throw LSST_EXCEPT(
    93 69c970f2 - pex::exceptions::LogicErrorException,
    ? ---------
    93 21597d88 + pex::exceptions::LogicError,
    (boost::format("PersistableFactory with name '%s' not found even after successful import " "of module '%s'. Please report this as a bug in the persistence " "implementation for this object.") % name % module).str() ); } } else { throw LSST_EXCEPT(
    102 69c970f2 - pex::exceptions::LogicErrorException,
    ? ---------
    102 21597d88 + pex::exceptions::LogicError,
    (boost::format("PersistableFactory with name '%s' not found, and no Python module to import " "was provided. Please report this as a bug in the persistence implementation " "for this object.") % name).str() ); } } return *i->second; } }}}} // namespace lsst::afw::table::io

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4aaa02e3

    commit 4aaa02e3e38d04136492c4fcaed39ee875d98edd
    Author: Jim Bosch 
    Date:   Thu Dec 6 19:41:40 2012 -0500
    
        New interface for table-based persistence.
    

    69c970f2

    commit 69c970f2db8cc67e647263211621fc0e0353cbae
    Author: Jim Bosch 
    Date:   Fri Mar 1 14:49:02 2013 +0900
    
        Save Python module names so we can import them to populate the registry in table persistence.
        
        Fix typos in PersistableFactory lookup exceptions.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    doc/table.dox

    Diff:

                    // -*- lsst-c++ -*-
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    /**
                     *  @page afwTable Tables
                     *
                     *  @section afwTableBasicUsage Basic Usage
                     *
                     *  In C++:
                     *  @code
                     *  #include "lsst/afw/table.h"
                     *  using namespace lsst::afw::table;
                     *  Schema schema;
                     *  Key k1 = schema.addField("f1", "doc for f1");
                     *  Key k2 = schema.addField("f2", "doc for f2", "units for f2");
                     *  Key< Array > k3 = schema.addField< Array >("f3", "doc for f3", "units for f2", 5);
                     *  BaseCatalog catalog(schema);
                     *  for (int i = 1; i <= 3; ++i) {
                     *      PTR(BaseRecord) record = catalog.addNew();
                     *      record->set(k1, i);
                     *      record->set(k2, i*3.14);
                     *      ndarray::Array a3 = (*record)[k3]; // operator[] allows in-place edits for some fields
                     *      a3.asEigen().setRandom();
                     *      a3.deep() += i;
                     *  }
                     *  BaseColumnView columns = catalog.getColumnView();
                     *  std::cout << columns[k1] << ", " << columns[k2] << ", " << columns[k3];
                     *  @endcode
                     *
                     *  In Python:
                     *  @code
                     *  from lsst.afw.table import *
                     *  schema = Schema()
                     *  k1 = schema.addField("f1", type=int, doc="doc for f1")
                     *  k2 = schema.addField("f2", type=numpy.float32, "doc for f2", units="units for f2")
                     *  k3 = schema.addField("f3", type="ArrayD", doc="doc for f3", units="units for f2", size=5)
                     *  catalog = BaseCatalog(schema)
                     *  for i in (1, 2, 3):
                     *      record = catalog.addNew()
                     *      record.set(k1, i)
                     *      record.set(k2, i * 3.14)
                     *      record[k3] = numpy.random.rand(5) + i # ndarray::Array == numpy.ndarray in Python
                     *  print catalog[k1], catalog[k2], catalog[k3]   # in Python, can access columns directly from the catalog
                     *  @endcode
                     *
                     *  @section afwTableOverview Overview
                     *  The primary objects users will interact with in the table library are
                     *  Schemas, Fields, Keys, Tables, Records, Catalogs, and ColumnViews.  Schema
                     *  is a concrete class that defines the columns of a table; it behaves like a
                     *  heterogeneous container of SchemaItem objects, which are in turn composed
                     *  of Field and Key objects.  A Field contains name, documentation, and units,
                     *  while the Key object is a lightweight opaque object used to actually access
                     *  elements of the table.  Using keys for access allows reads and writes to
                     *  compile down to little (if any) more than a pointer offset and dereference.
                     *  String field names can be used instead of keys in Python (though this is
                     *  less efficient), but this is not possible in C++.
                     *
                     *  Record and table classes are defined in pairs; each record class has a
                     *  1-to-1 correspondence with a table class.  A record at its simplest is just
                     *  a row in a table, though both classes are polymorphic and derived classes
                     *  can add additional functionality (such as the SourceRecord and SourceTable
                     *  classes, for instance).  A table acts as a factory for records; all record
                     *  creating (even cloning) goes through a table member function.  This is
                     *  because the underlying data for records is allocated in multi-record blocks
                     *  by the table.  Records thus hold a shared_ptr back to their table, as well
                     *  as a pointer to their memory block, and data members that are shared by
                     *  multiple records (such as the Schema) are accessed through the table rather
                     *  than held separately in each record.  A table does not hold pointers to the
                     *  records it is associated with, however, or provide ways to iterate over
                     *  records.
                     *
                     *  Instead, we have a separate concept of a container class, which holds a
                     *  single table pointer and multiple records, and is usually just a wrapper
                     *  around an STL container of record shared_ptrs.  While we've left open the
                     *  possibility of additional containers in the future, the CatalogT and
                     *  SimpleCatalogT implementations (better known by the BaseCatalog,
                     *  SimpleCatalog, and SourceCatalog typedefs) will be the most commonly used.
                     *  Catalogs are based on a std::vector of record shared_ptrs, but provided
                     *  accessors and iterators that yield record references, so you can use
                     *  iter->method instead of (**iter).method.  Most Catalog operations are
                     *  analogous to std::vector operations, though they often provide support for
                     *  both deep and shallow copies, and the SimpleCatalogT class adds sorting and
                     *  lookups based on unique IDs.  Future derived classes of BaseRecord and
                     *  BaseTable will hopefully be able to just use one of the existing catalog
                     *  templates and provide a new typedef rather than require a new catalog class.
                     *  Catalogs have a significantly different interface in Python, where they
                     *  mimic a (limited) Python list instead of a C++ vector (see the Python
                     *  in-line help).
                     *
                     *  ColumnView (i.e. BaseColumnView) objects can be created from Catalogs, and
                     *  provide views into columns of the catalog as ndarray::Array objects (in C++)
                     *  or numpy.ndarray objects (in Python).  In Python, columns can be directly
                     *  accessed from a Catalog (using a private ColumnView under the hood).  Not
                     *  all records are allocated in contiguous memory, however (as discussed
                     *  below), and only contiguous records can be viewed as columns.  To get
                     *  columns from a non-contiguous Catalog, you need to do a deep copy of it,
                     *  which will automatically ensure the new catalog is contiguous.  In Python,
                     *  that looks like this:
                     *  @code
                     *  newCat = oldCat.copy(deep=True)
                     *  @endcode
                     *
                     *  @section afwTableMemory Memory and Copy Semantics
                     *  Tables and records are noncopyable, and are always allocated in shared_ptrs.  Both can be
                     *  deep copied, however - tables have a clone() member function, and records can be copied
                     *  by calling copyRecord() on the table.  Records are also default constructable, in the sense
                     *  that a table must always be able to create a record with no additional arguments besides
                     *  what the table itself can provide (SourceTable, for instance, sets the ID of default-constructed
                     *  records using an internal IdFactory object).
                     *
                     *  The memory in a table is allocated in blocks, as in most implementations of the C++ STL's deque.
                     *  When the capacity of the most recent block is exhausted, a new block will be allocated for future
                     *  records.  The pointers to records themselves are not pointers into these blocks (record instances
                     *  are allocated as usual with new or make_shared) - the block memory is accessed via a void pointer
                     *  in the BaseRecord class, and derived record classes shouldn't have to deal with it at all.
                     *
                     *  One of the advantages of this approach is that most - but not all - records will be close to
                     *  their neighbors in memory.  More importantly, unlike std::vector, the whole table is never
                     *  silently reallocated.  Finally, if a sequence of records have been allocated from the same block,
                     *  their columns may be accessed as strided ndarray objects (and hency NumPy arrays in Python) using
                     *  ColumnView.
                     *
                     *  @section afwTableFits FITS I/O
                     *  Records can be saved/loaded to/from FITS binary tables using the writeFits and readFits member
                     *  functions on the library's container classes.  Not all FITS binary table column types are supported,
                     *  but the most common ones are (notable exceptions are strings, complex numbers, and variable-length
                     *  arrays).  As long as a FIT binary table contains only allowed column types, it should be possible
                     *  to read it into an afw/table container, though FITS tables from external sources will not be able
                     *  to tell our FITS reader to use specialized field types like Point or Covariance - any multi-element
                     *  column will be read in as an array unless special keys are present in the FITS header.
                     *
                     *  The FITS I/O functionally is implemented in the io::FitsReader and io::FitsWriter classes, which inherit
                     *  from the more general io::Reader and io::Writer classes.  New types of serialization for tables
                     *  should follow the same pattern and create new subclasses of io::Reader and io::Writer.  In addition,
                     *  new table/record types will usually want to implement a new FitsWriter and FitsReader subclass
                     *  (which can delegate most of the work to the base classes) to save derived-class data members and
                     *  ensure loaded objects have the correct type.
                     *
                     *  Each Table derived class can also define the interpretation of a set of bitflags that can be used
                     *  to control the details of how catalogs are saved and loaded.  For instance, SourceTable uses these
                     *  to determine whether to read or write Footprints with each source, and if so, whether to read or
                     *  write HeavyFootprints as regular Footprints (see SourceFitsFlags).  All Catalog FITS I/O routines
                     *  accept a flags argument, even if the underlying table object will ignore it.
                     *
                     *  @section afwTableSchema Schemas
                     *  Schema objects are append-only objects - you can add new fields, but you can never remove them.
                     *  This is because the schema creates and returns keys to fields as they are added, and removing
                     *  a field from the schema would invalidate not only the key for that field, but also keys for any
                     *  fields that were added after it.  Copying a schema and adding new records to the copy will
                     *  allow keys created from the original to work with tables and records that use the copy; we can
                     *  consider the original in this case to be a subset of the original schema, and we can test for this
                     *  using Schema::contains.  Containment tests and the Schema equality comparison operators only
                     *  consider the position, type and length of fields (in other words, in the information contained
                     *  in a Key) - you can renam a field in a schema without invalidating keys or changing how it is
                     *  compared to other schemas.  (Note that one schema being a subset or superset of another is
                     *  completely unrelated to the SubSchema class, which is used to implement the dotted namespaces
                     *  discussed below).
                     *
                     *  @section afwTableFieldNames Field Names
                     *  By convention, field names are all lowercase and have '.'-separated elements.  Only letters, numbers
                     *  and periods should be used.  These rules are not enforced, but names that do not meet these requirements
                     *  may not round-trip correctly in FITS (periods are converted to underscores in the FITS persistence
                     *  layer, so we cannot distinguish between the two when we read tables from FITS).
                     *  Schema provides extra functionality for names with period-separated elements; these elements can
                     *  be accessed separately individually with the bracket operators.  More information on schema namespaces
                     *  can be found in the Schema and SubSchema class documentation, and the testSchema.py unit test may
                     *  also be a useful example.
                     *
                     *  Other field strings (documentation and units) are essentially arbitrary, but should not contain
                     *  single quotes, as these may also confuse FITS parsers (even when escaped).
                     *
                     *  @section afwTableVariableLengthArrays Variable-Length Arrays
                     *
                     *  Variable-length array fields (@c Array fields with a size of @c 0) work in a fundamentally different
                     *  way from all other types - instead of using some of the contiguous memory block that other fields
                     *  occupy, these fields are simply a reference-counted pointer and size to separately-allocated
                     *  memory.  That means it's impossible to get column views for them, and there's a bit more overhead
                     *  for each one.  Whenever an array size can be known in advance, it's better to use a fixed-length
                     *  array field instead.
                     *
                     *  Variable-length array fields also behave slightly differently when assigned to, as compared to
    
    183 0b745ec6 - * fixed-length array fields: using @c BaseRecord.set() to assign a new array to a variable-length
    183 8389ad13 + * fixed-length array fields: using @c BaseRecord.set() to assign assign a new array to a variable-length
    ? +++++++ * field will replace the old value entirely with a reference to the new array, without copying any * values ("shallow assignment"), while assigning to a fixed-length array field will copy the values * into the record's memory block ("deep assignment"). In order to copy values into a variable-length * array, retrieve a reference to the array using square bracket [] operators, then assign to that. * In code, if @c key is a @c Key to a variable-length array field, * @code * record.set(key, array); // shallow: doesn't copy values, just reset pointers, size can change * record[key] = array; // deep: copies values, doesn't modify pointers, sizes must match * @endcode * * @section afwTableFieldTypes Field Types * In C++, field types are defined by the template arguments to Key and Field (among others). Empty * tag templates (Array, Point, Moments, Covariance) are used for compound fields. In Python, strings * are used to set field types. The Key and Field classes for each type can be accessed through * dictionaries (e.g. Key["F"]), but usually these type strings are only explicitly written * when passed as the 'type' argument of Schema.addField. Some Python types can also be used * in place of type strings for fields (e.g. int, afw.coord.Coord). Note that Python type strings * with angle brackets do not have the extra spaces that are necessary when writing templates in C++98. * * Some field types require a size argument to be passed to the Field constructor or Schema::addField; * while this size can be set at compile time, all records must have the same size. * * Not all field types support all types of data access. All field types support atomic access to * the entire field at once through BaseRecord::get and BaseRecord::set. Some field types support * square bracket access to references or reference-like objects (i.e. ndarray::ArrayRef) as well. * Only scalar and array fields support column access through ColumnView. * * A Key for an individual element of a compound field can also be obtained from the compound Key * object or (for 'named subfields') from the Schema directly (see Schema and the KeyBase specializations). * Element keys can be used just like any other scalar Key, and hence provide access to column views. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    C++ TypePython Type StringPython Aliases TypesC++ Value (get/set) TypeReference AccessColumnView SupportDynamic SizeNamed SubfieldsNotes
    Flag "Flag" boolNo Yes No Stored internally as a single bit
    boost::int32_t "I" int, numpy.int32 boost::int32_tYes Yes No
    boost::int64_t "L" long, numpy.int64 boost::int64_tYes Yes No
    float "F" numpy.float32 floatYes Yes No
    double "D" float, numpy.float64 doubleYes Yes No
    Angle "Angle" afw.geom.Angle afw::geom::AngleYes Yes No ColumnView access in Python returns an array of numpy.float64 (in radians).
    Coord "Coord" afw.coord.Coord, afw.coord.IcrsCoordafw::coord::IcrsCoordNo No No ra, dec Can assign any Coord, but always stored as ICRS
    std::string "String" str std::stringNo No Yes Strings are fixed-size; sizes must be declared at schema-creation time as with arrays.
    Point "PointI" afw.geom.Point2I afw::geom::Point2INo No No x, y
    Point "PointD" afw.geom.Point2D afw::geom::Point2DNo No No x, y
    Moments "MomentsD" afw.geom.ellipses.Quadrupoleafw::geom::ellipses::QuadrupoleNo No No xx, yy, xy
    Array "ArrayI" ndarray::ArrayYes Yes Yes operator[] returns an ndarray::ArrayRef
    Array "ArrayF" ndarray::ArrayYes Yes Yes operator[] returns an ndarray::ArrayRef
    Array "ArrayD" ndarray::ArrayYes Yes Yes operator[] returns an ndarray::ArrayRef
    Covariance "CovF" Eigen::MatrixXfNo No Yes symmetric matrix is stored packed (size*(size+1)/2 elements)
    Covariance< Point > "CovPointF" Eigen::Matrix2fNo No No symmetric matrix is stored packed (3 elements)
    Covariance< Moments > "CovMomentsF" Eigen::Matrix3fNo No No symmetric matrix is stored packed (6 elements)
    */ }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0b745ec6

    commit 0b745ec681de903b911691c49f07f3ebc52c692f
    Author: Jim Bosch 
    Date:   Mon Dec 1 13:46:03 2014 -0500
    
        Add variable-length array fields to afw::table
        
        We use Array with a size of zero to indicate variable-length fields.
        It'd probably be better to use a completely different tag type, but
        Boost.Variant puts an upper limit on how many tags we have, so until
        we rewrite afw::table to avoid it, we need to limit how many we use.
    

    Commits in /Users/nate/repos_lsst/afw/

    8389ad13

    commit 8389ad136cfab250ccee9de4e697acdd7e3e43b0
    Author: Jim Bosch 
    Date:   Fri Nov 21 17:18:04 2014 -0500
    
        Add variable-length array fields to afw::table
        
        We use Array with a size of zero to indicate variable-length fields.
        It'd probably be better to use a completely different tag type, but
        Boost.Variant puts an upper limit on how many tags we have, so until
        we rewrite afw::table to avoid it, we need to limit how many we use.
        
        Conflicts:
            include/lsst/afw/table/FieldBase.h
            src/table/Schema.cc
            tests/testSimpleTable.py
    

    Return to list

    tests/coord.py

    Diff:

    1 737686e9 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 62e64036 + from __future__ import absolute_import, division, print_function
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # # -*- python -*- """ Tests for Coord Run with: python Coord.py or python >>> import Coord >>> Coord.run() """ import math import unittest import lsst.afw.geom as afwGeom import lsst.afw.coord as afwCoord import lsst.utils.tests as utilsTests import lsst.daf.base as dafBase import lsst.pex.exceptions as pexEx # todo: see if we can give an Fk5 and an ecliptic at a different epoch and get the right answer # todo: make sure ICrs stuff works ###################################### # main body of code ###################################### class CoordTestCase(unittest.TestCase): def setUp(self): # define some arbitrary values self.ra, self.raKnown = "10:00:00.00", 10.0 self.dec, self.decKnown = "-02:30:00.00", -2.5 self.l = 100.0 self.b = 30.0 # a handy list of coords we want to test self.coordList = [ [afwCoord.Fk5Coord, afwCoord.FK5, afwCoord.cast_Fk5, "FK5"], [afwCoord.IcrsCoord, afwCoord.ICRS, afwCoord.cast_Icrs, "ICRS"], [afwCoord.GalacticCoord, afwCoord.GALACTIC, afwCoord.cast_Galactic, "GALACTIC"], [afwCoord.EclipticCoord, afwCoord.ECLIPTIC, afwCoord.cast_Ecliptic, "ECLIPTIC"], # we can't factory an Topocentric ... Observatory must be specified. # [afwCoord.TopocentricCoord, afwCoord.TOPOCENTRIC] ]
    71 4d62652f +
    72 4d62652f + def coordIter(self, includeCoord=True):
    73 4d62652f + """Return a collection of coords, one per class
    74 4d62652f +
    75 4d62652f + @param[in] includeCoord if True then include lsst.afw.coord.Coord (the base class)
    76 4d62652f + in the list of classes instantiated
    77 4d62652f + """
    78 4d62652f + if includeCoord:
    79 4d62652f + yield afwCoord.Coord(self.l * afwGeom.degrees, self.b * afwGeom.degrees)
    80 4d62652f +
    81 4d62652f + for coordClass, enum, cast, stringName in self.coordList:
    82 4d62652f + yield coordClass(self.l * afwGeom.degrees, self.b * afwGeom.degrees)
    83 4d62652f +
    84 4d62652f + obs = afwCoord.Observatory(-74.659 * afwGeom.degrees, 40.384 * afwGeom.degrees, 100.0) # peyton
    85 4d62652f + obsDate = dafBase.DateTime(2010, 3, 3, 0, 0, 0, dafBase.DateTime.TAI)
    86 4d62652f + epoch = obsDate.get(dafBase.DateTime.EPOCH)
    87 4d62652f + yield afwCoord.TopocentricCoord(
    88 4d62652f + 23.4 * afwGeom.degrees,
    89 4d62652f + 45.6 * afwGeom.degrees,
    90 4d62652f + epoch,
    91 4d62652f + obs,
    92 4d62652f + )
    93 4d62652f +
    def testFormat(self): """Test formatting""" # make an arbitrary coord with the string constructor. # check that calling the getFooStr() accessors gets back what we started with. equ = afwCoord.Fk5Coord(self.ra, self.dec) ## FIXME -- hours here? self.assertAlmostEqual(equ.getRa().asHours(), self.raKnown) self.assertAlmostEqual(equ.getDec().asDegrees(), self.decKnown)
    80 b388a66d - print "Format: %s %s" % (equ.getRaStr(afwGeom.hours), self.ra)
    ? ^
    104 62e64036 + print("Format: %s %s" % (equ.getRaStr(afwGeom.hours), self.ra))
    ? ^ + self.assertEqual(equ.getRaStr(afwGeom.hours), self.ra) def testFactory(self): """Test the Factory function makeCoord()""" # make a (eg galactic) coord with the constructor, and with the factory # and see if they agree. for constructor, enum, cast, stringName in self.coordList: con = constructor(self.l * afwGeom.degrees, self.b * afwGeom.degrees) factories = [] factories.append(afwCoord.makeCoord(enum, self.l * afwGeom.degrees, self.b * afwGeom.degrees)) factories.append(afwCoord.makeCoord(afwCoord.makeCoordEnum(stringName), self.l * afwGeom.degrees, self.b * afwGeom.degrees)) factories.append(afwCoord.makeCoord(enum, afwGeom.Point2D(self.l, self.b), afwGeom.degrees))
    96 ad9e652d - print "Factory: "
    ? ^
    120 62e64036 + print("Factory: ")
    ? ^ + for fac in factories: self.assertAlmostEqual(con[0], fac[0]) self.assertAlmostEqual(con[1], fac[1])
    100 5b7a0990 - s = (" tried ", fac[0], fac[1],
    ? ^^^^
    124 62e64036 + print(" tried ", fac[0], fac[1],
    ? ^^^^^ "(expected ", con[0], con[1], ")")
    102 35a9ec57 - print s
    # can we create an empty coord, and use reset() to fill it? c = afwCoord.makeCoord(enum) c.reset(1.0 * afwGeom.degrees, 1.0 * afwGeom.degrees, 2000.0) myCoord = cast(c) self.assertEqual(myCoord.getLongitude().asDegrees(), 1.0) self.assertEqual(myCoord.getLatitude().asDegrees(), 1.0) # verify that makeCoord throws when given an epoch for an epochless system
    114 b5487454 - self.assertRaises(pexEx.LsstCppException,
    ? -------
    137 6fc1c3d1 + self.assertRaises(pexEx.Exception,
    lambda: afwCoord.makeCoord(afwCoord.GALACTIC, self.l * afwGeom.degrees, self.b * afwGeom.degrees, 2000.0))
    116 b5487454 - self.assertRaises(pexEx.LsstCppException,
    ? -------
    139 6fc1c3d1 + self.assertRaises(pexEx.Exception,
    lambda: afwCoord.makeCoord(afwCoord.ICRS, self.l * afwGeom.degrees, self.b * afwGeom.degrees, 2000.0)) def testCoordEnum(self): """Verify that makeCoordEnum throws an exception for non-existant systems."""
    122 29df7008 - self.assertRaises(pexEx.LsstCppException, lambda: afwCoord.makeCoordEnum("FOO"))
    ? -------
    145 6fc1c3d1 + self.assertRaises(pexEx.Exception, lambda: afwCoord.makeCoordEnum("FOO"))
    146 4d62652f +
    147 4d62652f +
    148 4d62652f + def testGetClassName(self):
    149 4d62652f + """Test getClassName, including after cloning
    150 4d62652f + """
    151 4d62652f + for coord in self.coordIter():
    152 4d62652f + className = type(coord).__name__
    153 4d62652f + self.assertEqual(coord.getClassName(), className)
    154 4d62652f + self.assertEqual(coord.clone().getClassName(), className)
    155 4d62652f +
    156 4d62652f +
    157 a5a62a17 + def testIter(self):
    158 a5a62a17 + """Test iteration
    159 a5a62a17 + """
    160 a5a62a17 + for coord in self.coordIter():
    161 a5a62a17 + for c in (coord, coord.clone()):
    162 a5a62a17 + self.assertEqual(len(c), 2)
    163 a5a62a17 + self.assertEqual(c[0], c.getLongitude())
    164 a5a62a17 + self.assertEqual(c[1], c.getLatitude())
    165 a5a62a17 +
    166 62e64036 + # raise if we ask for too many values
    167 62e64036 + self.assertRaises(Exception, c.__getitem__, 2)
    168 62e64036 +
    169 a5a62a17 +
    170 4d62652f + def testStrRepr(self):
    171 4d62652f + """Test __str__ and __repr__
    172 4d62652f + """
    173 4d62652f + for coord in self.coordIter():
    174 62e64036 + print("str(coord) = %s; repr(coord) = %r" % (coord, coord))
    175 4d62652f + className = type(coord).__name__
    176 4d62652f + coordStr = str(coord)
    177 4d62652f + coordRepr = repr(coord)
    178 4d62652f + self.assertEqual(coordStr, str(coord.clone()))
    179 4d62652f + self.assertEqual(coordRepr, repr(coord.clone()))
    180 4d62652f + self.assertTrue(coordStr.startswith("%s(" % (className,)))
    181 4d62652f + self.assertFalse("degrees" in coordStr)
    182 4d62652f + self.assertTrue(coordRepr.startswith("%s(" % (className,)))
    183 4d62652f + self.assertTrue("degrees" in coordRepr)
    184 4d62652f + numArgs = {
    185 62e64036 + "IcrsCoord": 2, # long, lat
    186 62e64036 + "GalacticCoord": 2, # long, lat
    187 62e64036 + "TopocentricCoord": 5, # long, lat, epoch, Observatory (which has 3 arguments)
    188 62e64036 + }.get(className, 3) # default to long, lat, epoch
    189 4d62652f + self.assertEqual(len(coordStr.split(",")), numArgs)
    190 4d62652f + self.assertEqual(len(coordRepr.split(",")), numArgs)
    def testPosition(self): """Test the getPosition() method""" # make a coord and verify that the DEGREES, RADIANS, and HOURS enums get the right things equ = afwCoord.Fk5Coord(self.ra, self.dec) # make sure we get what we asked for pDeg = equ.getPosition() self.assertAlmostEqual(equ.getRa().asDegrees(), pDeg.getX()) self.assertAlmostEqual(equ.getDec().asDegrees(), pDeg.getY()) pRad = equ.getPosition(afwGeom.radians) self.assertAlmostEqual(equ.getRa().asRadians(), pRad.getX()) self.assertAlmostEqual(equ.getDec().asRadians(), pRad.getY()) pHrs = equ.getPosition(afwGeom.hours) self.assertAlmostEqual(equ.getRa().asHours(), pHrs.getX()) self.assertAlmostEqual(equ.getDec().asDegrees(), pHrs.getY()) # make sure we construct with the type we ask for equ1 = afwCoord.Fk5Coord(pDeg, afwGeom.degrees) self.assertAlmostEqual(equ1.getRa().asRadians(), equ.getRa().asRadians()) equ2 = afwCoord.Fk5Coord(pRad, afwGeom.radians) self.assertAlmostEqual(equ2.getRa().asRadians(), equ.getRa().asRadians()) equ3 = afwCoord.Fk5Coord(pHrs, afwGeom.hours) self.assertAlmostEqual(equ3.getRa().asRadians(), equ.getRa().asRadians()) def testVector(self): """Test the getVector() method, and make sure the constructors take Point3D""" # try the axes: vernal equinox should equal 1, 0, 0; ... north pole is 0, 0, 1; etc coordList = [] coordList.append([(0.0, 0.0), (1.0, 0.0, 0.0)]) coordList.append([(90.0, 0.0), (0.0, 1.0, 0.0)]) coordList.append([(0.0, 90.0), (0.0, 0.0, 1.0)]) for equ, p3dknown in coordList: # convert to p3d p3d = afwCoord.Fk5Coord(equ[0] * afwGeom.degrees, equ[1] * afwGeom.degrees).getVector()
    168 d304da93 - print "Point3d: ", p3d, p3dknown
    ? ^
    236 62e64036 + print("Point3d: ", p3d, p3dknown)
    ? ^ + for i in range(3): self.assertAlmostEqual(p3d[i], p3dknown[i]) # convert back equBack = afwCoord.Fk5Coord(p3d)
    174 b388a66d - s = ("Vector (back): ", equBack.getRa().asDegrees(), equ[0],
    ? ^^^^
    242 62e64036 + print("Vector (back): ", equBack.getRa().asDegrees(), equ[0],
    ? ^^^^^ equBack.getDec().asDegrees(), equ[1])
    176 d304da93 - print s
    self.assertAlmostEqual(equBack.getRa().asDegrees(), equ[0]) self.assertAlmostEqual(equBack.getDec().asDegrees(), equ[1]) # and try some un-normalized ones too coordList = [] # too long coordList.append([(0.0, 0.0), (1.3, 0.0, 0.0)]) coordList.append([(90.0, 0.0), (0.0, 1.2, 0.0)]) coordList.append([(0.0, 90.0), (0.0, 0.0, 2.3)]) # too short coordList.append([(0.0, 0.0), (0.5, 0.0, 0.0)]) coordList.append([(90.0, 0.0), (0.0, 0.7, 0.0)]) coordList.append([(0.0, 90.0), (0.0, 0.0, 0.9)]) for equKnown, p3d in coordList: # convert to Coord epoch = 2000.0 norm = True c = afwCoord.Fk5Coord(afwGeom.Point3D(p3d[0], p3d[1], p3d[2]), epoch, norm) ra, dec = c.getRa().asDegrees(), c.getDec().asDegrees()
    199 5040cf2e - print "Un-normed p3d: ", p3d, "-->", equKnown, ra, dec
    ? ^
    266 62e64036 + print("Un-normed p3d: ", p3d, "-->", equKnown, ra, dec)
    ? ^ + self.assertAlmostEqual(equKnown[0], ra) self.assertAlmostEqual(equKnown[1], dec) def testTicket1761(self): """Ticket 1761 found that non-normalized inputs caused failures. """ c = afwCoord.Coord(afwGeom.Point3D(0,1,0)) dfltLong = 0.0 * afwGeom.radians norm = False c1 = afwCoord.Coord(afwGeom.Point3D(0.1, 0.1, 0.1), 2000.0, norm, dfltLong) c2 = afwCoord.Coord(afwGeom.Point3D(0.6, 0.6 ,0.6), 2000.0, norm, dfltLong) sep1 = c.angularSeparation(c1).asDegrees() sep2 = c.angularSeparation(c2).asDegrees() known1 = 45.286483672428574 known2 = 55.550098012046512
    217 5040cf2e - print "sep: ", sep1, sep2, known1, known2
    ? ^
    284 62e64036 + print("sep: ", sep1, sep2, known1, known2)
    ? ^ + # these weren't normalized, and should get the following *incorrect* answers self.assertAlmostEqual(sep1, known1) self.assertAlmostEqual(sep2, known2) ###################### # normalize and sep1, sep2 should both equal 54.7356 norm = True c1 = afwCoord.Coord(afwGeom.Point3D(0.1, 0.1, 0.1), 2000.0, norm, dfltLong) c2 = afwCoord.Coord(afwGeom.Point3D(0.6, 0.6 ,0.6), 2000.0, norm, dfltLong) sep1 = c.angularSeparation(c1).asDegrees() sep2 = c.angularSeparation(c2).asDegrees() known = 54.735610317245339
    231 5040cf2e - print "sep: ", sep1, sep2, known
    ? ^
    298 62e64036 + print("sep: ", sep1, sep2, known)
    ? ^ + # these weren't normalized, and should get the following *incorrect* answers self.assertAlmostEqual(sep1, known) self.assertAlmostEqual(sep2, known) def testNames(self): """Test the names of the Coords (Useful with Point2D form)""" # verify that each coordinate type can tell you what its components are called. radec1, known1 = afwCoord.Coord(self.ra, self.dec).getCoordNames(), ["RA", "Dec"] radec3, known3 = afwCoord.Fk5Coord(self.ra, self.dec).getCoordNames(), ["RA", "Dec"] radec4, known4 = afwCoord.IcrsCoord(self.ra, self.dec).getCoordNames(), ["RA", "Dec"] lb, known5 = afwCoord.GalacticCoord(self.ra, self.dec).getCoordNames(), ["L", "B"] lambet, known6 = afwCoord.EclipticCoord(self.ra, self.dec).getCoordNames(), ["Lambda", "Beta"] altaz, known7 = afwCoord.TopocentricCoord(self.ra, self.dec, 2000.0, afwCoord.Observatory(0 * afwGeom.degrees, 0 * afwGeom.degrees, 0)).getCoordNames(), ["Az", "Alt"] pairs = [ [radec1, known1], [radec3, known3], [radec4, known4], [lb, known5], [lambet, known6], [altaz, known7], ] for pair, known in (pairs): self.assertEqual(pair[0], known[0]) self.assertEqual(pair[1], known[1]) def testConvert(self): """Verify that the generic convert() method works""" # Pollux alpha, delta = "07:45:18.946", "28:01:34.26" pollux = afwCoord.Fk5Coord(alpha, delta) # bundle up a list of coords created with the specific and generic converters coordList = [ [pollux.toFk5(), pollux.convert(afwCoord.FK5)], [pollux.toIcrs(), pollux.convert(afwCoord.ICRS)], [pollux.toGalactic(), pollux.convert(afwCoord.GALACTIC)], [pollux.toEcliptic(), pollux.convert(afwCoord.ECLIPTIC)], ] # go through the list and see if specific and generic produce the same result ... they should!
    278 5b7a0990 - print "Convert: "
    ? ^
    345 62e64036 + print("Convert: ")
    ? ^ + for specific, generic in coordList: # note that operator[]/__getitem__ is overloaded. It gets the internal (radian) values # ... the same as getPosition(afwGeom.radians) long1, lat1 = specific[0].asRadians(), specific[1].asRadians() long2, lat2 = generic.getPosition(afwGeom.radians)
    284 5b7a0990 - print "(specific) %.8f %.8f (generic) %.8f %.8f" % (long1, lat1, long2, lat2)
    ? ^
    351 62e64036 + print("(specific) %.8f %.8f (generic) %.8f %.8f" % (long1, lat1, long2, lat2))
    ? ^ + self.assertEqual(long1, long2) self.assertEqual(lat1, lat2) def testEcliptic(self): """Verify Ecliptic Coordinate Transforms""" # Pollux alpha, delta = "07:45:18.946", "28:01:34.26" # known ecliptic coords (example from Meeus, Astro algorithms, pg 95) lamb, beta = 113.215629, 6.684170 # Try converting pollux Ra,Dec to ecliptic and check that we get the right answer polluxEqu = afwCoord.Fk5Coord(alpha, delta) polluxEcl = polluxEqu.toEcliptic() s = ("Ecliptic (Pollux): ", polluxEcl.getLambda().asDegrees(), polluxEcl.getBeta().asDegrees(), lamb, beta)
    302 d304da93 - print s
    ? ^
    369 62e64036 + print(s)
    ? ^ + # verify to precision of known values self.assertAlmostEqual(polluxEcl.getLambda().asDegrees(), lamb, 6) self.assertAlmostEqual(polluxEcl.getBeta().asDegrees(), beta, 6) # make sure it transforms back (machine precision) self.assertAlmostEqual(polluxEcl.toFk5().getRa().asDegrees(), polluxEqu.getRa().asDegrees(), 13) self.assertAlmostEqual(polluxEcl.toFk5().getDec().asDegrees(), polluxEqu.getDec().asDegrees(), 13) def testGalactic(self): """Verify Galactic coordinate transforms""" # Try converting Sag-A to galactic and make sure we get the right answer # Sagittarius A (very nearly the galactic center) sagAKnownEqu = afwCoord.Fk5Coord("17:45:40.04","-29:00:28.1") sagAKnownGal = afwCoord.GalacticCoord(359.94432 * afwGeom.degrees, -0.04619 * afwGeom.degrees) sagAGal = sagAKnownEqu.toGalactic()
    324 f937c469 - s = ("Galactic (Sag-A): (transformed) %.5f %.5f (known) %.5f %.5f\n" %
    ? ^^^^
    391 62e64036 + print("Galactic (Sag-A): (transformed) %.5f %.5f (known) %.5f %.5f\n" %
    ? ^^^^^ (sagAGal.getL().asDegrees(), sagAGal.getB().asDegrees(), sagAKnownGal.getL().asDegrees(), sagAKnownGal.getB().asDegrees()))
    327 f937c469 - print s
    # verify ... to 4 places, the accuracy of the galactic pole in Fk5 self.assertAlmostEqual(sagAGal.getL().asDegrees(), sagAKnownGal.getL().asDegrees(), 4) self.assertAlmostEqual(sagAGal.getB().asDegrees(), sagAKnownGal.getB().asDegrees(), 4) # make sure it transforms back ... to machine precision self.assertAlmostEqual(sagAGal.toFk5().getRa().asDegrees(), sagAKnownEqu.getRa().asDegrees(), 12) self.assertAlmostEqual(sagAGal.toFk5().getDec().asDegrees(), sagAKnownEqu.getDec().asDegrees(), 12) def testTopocentric(self): """Verify Altitude/Azimuth coordinate transforms""" # try converting the RA,Dec of Sedna (on the specified date) to Alt/Az # sedna (from jpl) for 2010-03-03 00:00 UT ra, dec = "03:26:42.61", "+06:32:07.1" az, alt = 231.5947, 44.3375 obs = afwCoord.Observatory(-74.659 * afwGeom.degrees, 40.384 * afwGeom.degrees, 100.0) # peyton obsDate = dafBase.DateTime(2010, 3, 3, 0, 0, 0, dafBase.DateTime.TAI) epoch = obsDate.get(dafBase.DateTime.EPOCH) sedna = afwCoord.Fk5Coord(ra, dec, epoch) altaz = sedna.toTopocentric(obs, obsDate)
    353 ebfdd282 - s = "Topocentric (Sedna): ", \
    ? ^^^^ --
    419 62e64036 + print("Topocentric (Sedna): ",
    ? ^^^^^^
    354 ebfdd282 - altaz.getAltitude().asDegrees(), altaz.getAzimuth().asDegrees(), alt, az
    420 62e64036 + altaz.getAltitude().asDegrees(), altaz.getAzimuth().asDegrees(), alt, az)
    ? +
    355 47fd8d77 - print s
    # precision is low as we don't account for as much as jpl (abberation, nutation, etc) self.assertAlmostEqual(altaz.getAltitude().asDegrees(), alt, 1) self.assertAlmostEqual(altaz.getAzimuth().asDegrees(), az, 1) # convert back to RA,Dec to check the roundtrip sedna2 = altaz.toFk5(epoch) ra2, dec2 = sedna2.getRa().asDegrees(), sedna2.getDec().asDegrees()
    365 ebfdd282 - s = "Topocentric roundtrip (Sedna): ", \
    ? ^^^^ --
    430 62e64036 + print("Topocentric roundtrip (Sedna): ",
    ? ^^^^^^
    366 ebfdd282 - sedna.getRa().asDegrees(), ra2, sedna.getDec().asDegrees(), dec2
    431 62e64036 + sedna.getRa().asDegrees(), ra2, sedna.getDec().asDegrees(), dec2)
    ? +
    367 ebfdd282 - print s
    self.assertAlmostEqual(sedna.getRa().asDegrees(), ra2) self.assertAlmostEqual(sedna.getDec().asDegrees(), dec2) def testPrecess(self): """Test precession calculations in different coordinate systems""" # Try precessing in the various coordinate systems, and check the results. ### Fk5 ### # example 21.b Meeus, pg 135, for Alpha Persei ... with proper motion alpha0, delta0 = "2:44:11.986", "49:13:42.48" # proper motions per year dAlphaS, dDeltaAS = 0.03425, -0.0895 # Angle/yr dAlpha, dDelta = (dAlphaS*15.) * afwGeom.arcseconds, (dDeltaAS) * afwGeom.arcseconds # get for 2028, Nov 13.19 epoch = dafBase.DateTime(2028, 11, 13, 4, 33, 36, dafBase.DateTime.TAI).get(dafBase.DateTime.EPOCH) # the known final answer # - actually 41.547214, 49.348483 (suspect precision error in Meeus) alphaKnown, deltaKnown = 41.547236, 49.348488 alphaPer0 = afwCoord.Fk5Coord(alpha0, delta0) alpha1 = alphaPer0.getRa() + dAlpha*(epoch - 2000.0) delta1 = alphaPer0.getDec() + dDelta*(epoch - 2000.0) alphaPer = afwCoord.Fk5Coord(alpha1, delta1).precess(epoch)
    401 b388a66d - print "Precession (Alpha-Per): %.6f %.6f (known) %.6f %.6f" % (alphaPer.getRa().asDegrees(),
    ? ^
    465 62e64036 + print("Precession (Alpha-Per): %.6f %.6f (known) %.6f %.6f" % (alphaPer.getRa().asDegrees(),
    ? ^ alphaPer.getDec().asDegrees(),
    403 737686e9 - alphaKnown, deltaKnown)
    467 62e64036 + alphaKnown, deltaKnown))
    ? + # precision 6 (with 1 digit fudged in the 'known' answers) self.assertAlmostEqual(alphaPer.getRa().asDegrees(), alphaKnown, 6) self.assertAlmostEqual(alphaPer.getDec().asDegrees(), deltaKnown, 6) # verify that toFk5(epoch) also works as precess alphaPer2 = afwCoord.Fk5Coord(alpha1, delta1).toFk5(epoch) self.assertEqual(alphaPer[0], alphaPer2[0]) self.assertEqual(alphaPer[1], alphaPer2[1]) ### Galactic ### # make sure Galactic throws an exception. As there's no epoch, there's no precess() method. gal = afwCoord.GalacticCoord(self.l * afwGeom.degrees, self.b * afwGeom.degrees) epochNew = 2010.0 self.assertRaises(AttributeError, lambda: gal.precess(epochNew)) ### Icrs ### # make sure Icrs throws an exception. As there's no epoch, there's no precess() method. icrs = afwCoord.IcrsCoord(self.l * afwGeom.degrees, self.b * afwGeom.degrees) epochNew = 2010.0 self.assertRaises(AttributeError, lambda: icrs.precess(epochNew)) ### Ecliptic ### # test for ecliptic with venus (example from meeus, pg 137) lamb2000, beta2000 = 149.48194, 1.76549 # known values for -214, June 30.0 # they're actually 118.704, 1.615, but I suspect discrepancy is a rounding error in Meeus # -- we use double precision, he carries 7 places only. # originally 214BC, but that broke the DateTime # It did work previously, so for the short term, I've taken the answer it # returns for 1920, and used that as the 'known answer' for future tests. #year = -214 #lamb214bc, beta214bc = 118.704, 1.606 year = 1920 lamb214bc, beta214bc = 148.37119237032144, 1.7610036104147864 venus2000 = afwCoord.EclipticCoord(lamb2000 * afwGeom.degrees, beta2000 * afwGeom.degrees, 2000.0) ep = dafBase.DateTime(year, 6, 30, 0, 0, 0, dafBase.DateTime.TAI).get(dafBase.DateTime.EPOCH) venus214bc = venus2000.precess(ep)
    452 d304da93 - s = ("Precession (Ecliptic, Venus): %.4f %.4f (known) %.4f %.4f" %
    ? ^^^^
    516 62e64036 + print("Precession (Ecliptic, Venus): %.4f %.4f (known) %.4f %.4f" %
    ? ^^^^^ (venus214bc.getLambda().asDegrees(), venus214bc.getBeta().asDegrees(), lamb214bc, beta214bc))
    455 d304da93 - print s
    # 3 places precision (accuracy of our controls) self.assertAlmostEqual(venus214bc.getLambda().asDegrees(), lamb214bc, 3) self.assertAlmostEqual(venus214bc.getBeta().asDegrees(), beta214bc, 3) # verify that toEcliptic(ep) does the same as precess(ep) venus214bc2 = venus2000.toEcliptic(ep) self.assertEqual(venus214bc[0], venus214bc2[0]) self.assertEqual(venus214bc[1], venus214bc2[1]) def testAngularSeparation(self): """Test measure of angular separation between two coords""" # test from Meeus, pg 110 spica = afwCoord.Fk5Coord(201.2983 * afwGeom.degrees, -11.1614 * afwGeom.degrees) arcturus = afwCoord.Fk5Coord(213.9154 * afwGeom.degrees, 19.1825 * afwGeom.degrees) knownDeg = 32.7930 deg = spica.angularSeparation(arcturus).asDegrees()
    477 737686e9 - print "Separation (Spica/Arcturus): %.6f (known) %.6f" % (deg, knownDeg)
    ? ^
    540 62e64036 + print("Separation (Spica/Arcturus): %.6f (known) %.6f" % (deg, knownDeg))
    ? ^ + # verify to precision of known self.assertAlmostEqual(deg, knownDeg, 4) # verify small angles ... along a constant ra, add an arcsec to spica dec epsilon = 1.0 * afwGeom.arcseconds spicaPlus = afwCoord.Fk5Coord(spica.getRa(), spica.getDec() + epsilon) deg = spicaPlus.angularSeparation(spica).asDegrees()
    487 b388a66d - print "Separation (Spica+epsilon): %.8f (known) %.8f" % (deg, epsilon.asDegrees())
    ? ^
    550 62e64036 + print("Separation (Spica+epsilon): %.8f (known) %.8f" % (deg, epsilon.asDegrees()))
    ? ^ + # machine precision self.assertAlmostEqual(deg, epsilon.asDegrees()) def testTicket1394(self): """Ticket #1394 bug: coord within epsilon of RA=0 leads to negative RA and fails bounds check. """ # the problem was that the coordinate is < epsilon close to RA==0 # and bounds checking was getting a -ve RA. c = afwCoord.makeCoord(afwCoord.ICRS, afwGeom.Point3D(0.6070619982, -1.264309928e-16, 0.7946544723)) self.assertEqual(c[0], 0.0) def testRotate(self): """Verify rotation of coord about a user provided axis.""" # try rotating about the equatorial pole (ie. along a parallel) longitude = 90.0 latitudes = [0.0, 30.0, 60.0] arcLen = 10.0 pole = afwCoord.Fk5Coord(0.0 * afwGeom.degrees, 90.0 * afwGeom.degrees) for latitude in latitudes: c = afwCoord.Fk5Coord(longitude * afwGeom.degrees, latitude * afwGeom.degrees) c.rotate(pole, arcLen * afwGeom.degrees) lon = c.getLongitude() lat = c.getLatitude()
    518 b388a66d - print "Rotate along a parallel: %.10f %.10f %.10f %.10f" % (lon.asDegrees(), lat.asDegrees(),
    ? ^
    581 62e64036 + print("Rotate along a parallel: %.10f %.10f %.10f %.10f" % (lon.asDegrees(), lat.asDegrees(),
    ? ^
    519 05252a8f - longitude+arcLen, latitude)
    582 62e64036 + longitude+arcLen, latitude))
    ? + self.assertAlmostEqual(lon.asDegrees(), longitude + arcLen) self.assertAlmostEqual(lat.asDegrees(), latitude) # try with pole = vernal equinox and rotate up a meridian pole = afwCoord.Fk5Coord(0.0 * afwGeom.degrees, 0.0 * afwGeom.degrees) for latitude in latitudes: c = afwCoord.Fk5Coord(longitude * afwGeom.degrees, latitude * afwGeom.degrees) c.rotate(pole, arcLen * afwGeom.degrees) lon = c.getLongitude() lat = c.getLatitude()
    532 b388a66d - print "Rotate along a meridian: %.10f %.10f %.10f %.10f" % (lon.asDegrees(), lat.asDegrees(),
    ? ^
    595 62e64036 + print("Rotate along a meridian: %.10f %.10f %.10f %.10f" % (lon.asDegrees(), lat.asDegrees(),
    ? ^
    533 05252a8f - longitude, latitude+arcLen)
    596 62e64036 + longitude, latitude+arcLen))
    ? + self.assertAlmostEqual(lon.asDegrees(), longitude) self.assertAlmostEqual(lat.asDegrees(), latitude + arcLen) def testOffset(self): """Verify offset of coord along a great circle.""" lon0 = 90.0 lat0 = 0.0 # These tests only work from the equator arcLen = 10.0 # lon, lat phi, arcLen, expLong, expLat, expPhi2 trials = [ [lon0, lat0, 0.0, arcLen, lon0+arcLen, lat0, 0.0], # along celestial equator [lon0, lat0, 90.0, arcLen, lon0, lat0+arcLen, 90.0], # along a meridian [lon0, lat0, 45.0, 180.0, lon0+180.0, -lat0, -45.0], # 180 arc (should go to antip. pt) [lon0, lat0, 45.0, 90.0, lon0+90.0, lat0+45.0, 0.0], # [0.0, 90.0, 0.0, 90.0, 90.0, 0.0, -90.0], # from pole, phi=0 [0.0, 90.0, 90.0, 90.0, 180.0, 0.0, -90.0], # from pole, phi=90 ] for trial in trials: lon0, lat0, phi, arc, longExp, latExp, phi2Exp = trial c = afwCoord.Fk5Coord(lon0 * afwGeom.degrees, lat0 * afwGeom.degrees) c1 = afwCoord.Fk5Coord(longExp * afwGeom.degrees, latExp * afwGeom.degrees) offset = c.getOffsetFrom(c1) phi2 = c.offset(phi * afwGeom.degrees, arc * afwGeom.degrees) lon = c.getLongitude().asDegrees() lat = c.getLatitude().asDegrees()
    566 3730a45b - print "Offset: %.10f %.10f %.10f %.10f %.10f %.10f" % (lon, lat, phi2, longExp, latExp, phi2Exp)
    ? ^
    629 62e64036 + print("Offset: %.10f %.10f %.10f %.10f %.10f %.10f" % (lon, lat, phi2, longExp, latExp, phi2Exp))
    ? ^ +
    567 80f56614 - print ("Measured: %.10f %.10f %.10f %.10f" %
    ? -
    630 62e64036 + print("Measured: %.10f %.10f %.10f %.10f" %
    (offset[0].asDegrees(), offset[1].asDegrees(), phi, arc)) self.assertAlmostEqual(lon, longExp, 12) self.assertAlmostEqual(lat, latExp, 12) self.assertAlmostEqual(phi2.asDegrees(), phi2Exp, 12) if arc != 180.0: # in that case, angle doesn't matter self.assertAlmostEqual(offset[0].asDegrees() + 180.0, phi, 12) self.assertAlmostEqual(offset[1].asDegrees(), arc, 12) def testOffsetTangentPlane(self): """Testing of offsets on a tangent plane (good for small angles)""" c0 = afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees) for dRa in (0.0123, 0.0, -0.0321): for dDec in (0.0543, 0.0, -0.0987): c1 = afwCoord.Coord(dRa*afwGeom.degrees, dDec*afwGeom.degrees) offset = c0.getTangentPlaneOffset(c1) # This more-or-less works for small angles because c0 is 0,0 expE = math.degrees(math.tan(math.radians(dRa))) expN = math.degrees(math.tan(math.radians(dDec)))
    591 80f56614 - print "TP: ", dRa, dDec, offset[0].asDegrees(), offset[1].asDegrees(), expE, expN
    ? ^
    654 62e64036 + print("TP: ", dRa, dDec, offset[0].asDegrees(), offset[1].asDegrees(), expE, expN)
    ? ^ + self.assertAlmostEqual(offset[0].asDegrees(), expE) self.assertAlmostEqual(offset[1].asDegrees(), expN) def testVirtualGetName(self): gal = afwCoord.GalacticCoord(0.0 * afwGeom.radians, 0.0 * afwGeom.radians) clone = gal.clone() gal_names = gal.getCoordNames() # ("L", "B") clone_names = clone.getCoordNames() #("Ra", "Dec") self.assertEqual(gal_names[0], clone_names[0]) self.assertEqual(gal_names[1], clone_names[1]) def testTicket2915(self): """SegFault in construction of Coord from strings"""
    608 4cb93054 - self.assertRaises(pexEx.LsstCppException, afwCoord.IcrsCoord, "79.891963", "-10.110075")
    ? -------
    671 6fc1c3d1 + self.assertRaises(pexEx.Exception, afwCoord.IcrsCoord, "79.891963", "-10.110075")
    609 4cb93054 - self.assertRaises(pexEx.LsstCppException, afwCoord.IcrsCoord, "01:23", "45:67")
    ? -------
    672 6fc1c3d1 + self.assertRaises(pexEx.Exception, afwCoord.IcrsCoord, "01:23", "45:67")
    def testTicket3093(self): """Declination -1 < delta < 0 always prints positive as a string""" # from how-to-reproduce code reported on 3093 ticket ra = 26.468676561631767*afwGeom.degrees decl = -0.6684668814164008 # also make sure we didn't break the original functionality # Test above/below +/-1 declIn = [ decl, -1.0*decl, decl - 1.0, -decl + 1.0] declKnown = ["-00:40:06.48", "00:40:06.48", "-01:40:06.48", "01:40:06.48"] for i in range(len(declIn)): printableCoord = afwCoord.IcrsCoord(ra, declIn[i]*afwGeom.degrees).getDecStr() # With bug, this prints e.g. '00:40:06.48. It should be '-00:40:06.48'
    627 6ee559f1 - print "Decl 0 to -1 bug:", printableCoord
    ? ^
    690 62e64036 + print("Decl 0 to -1 bug:", printableCoord)
    ? ^ + self.assertEqual(printableCoord, declKnown[i])
    631 6c184547 - def testIterable(self):
    ? ^ ^^^^^^
    694 15efb07a + def testEquality(self):
    ? ^^^^^^ ^
    695 15efb07a + # (In)equality is determined by value, not identity. See DM-2347, -2465.
    696 15efb07a + c1 = afwCoord.IcrsCoord(self.ra, self.dec)
    697 15efb07a + self.assertTrue(c1 == c1)
    698 15efb07a + self.assertFalse(c1 != c1)
    632 737686e9 -
    633 6c184547 - for ctor,enum,cast,sname in self.coordList:
    634 6c184547 - c = ctor(self.ra, self.dec)
    635 6c184547 - ra, dec = c
    636 6c184547 - print "Iterable: ", type(c), c, ra, dec
    637 6c184547 - self.assertEqual(ra, c[0])
    638 6c184547 - self.assertEqual(dec, c[1])
    640 6c184547 - # make sure we raise if we ask for too many args
    641 6c184547 - def three(c):
    642 6c184547 - ra, dec, menudo = c
    643 6c184547 - self.assertRaises(ValueError, three, c)
    700 15efb07a + c2 = afwCoord.IcrsCoord(self.ra.replace('1', '2'), self.dec)
    701 15efb07a + self.assertFalse(c2 == c1)
    702 15efb07a + self.assertTrue(c2 != c1)
    703 15efb07a +
    704 15efb07a + c3 = afwCoord.IcrsCoord(self.ra, self.dec)
    705 15efb07a + self.assertTrue(c3 == c1)
    706 15efb07a + self.assertFalse(c3 != c1)
    ################################################################# # Test suite boiler plate ################################################################# def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(CoordTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    80f56614

    commit 80f566140f8a6d8a1a6dea87b475246882ff6787
    Author: Paul Price 
    Date:   Tue Sep 11 14:16:08 2012 -0400
    
        getOffsetFrom() now returns a pair of angles suitable for use with the old offset() method.
        
        This allows us to scrap the tangent-plane-based offset() method which I'm suspicious of.
        The old getOffsetFrom() method (operating in the tangent plane) is renamed getTangentPlaneOffset().
        
        Refactored some for code reuse.
    

    3730a45b

    commit 3730a45b2102302f4745f7b35d5be4af47597bd1
    Author: bick 
    Date:   Tue Aug 3 17:14:22 2010 +0000
    
        #1397 changed Coord::offset() to return position angle at new coordinate.
    

    b388a66d

    commit b388a66d6de5dff93b3e6d1cd388e01b7dcc63f3
    Author: dstn 
    Date:   Fri May 6 16:43:01 2011 +0000
    
        one unit test passes -- ship Service Pack 1!
    

    ebfdd282

    commit ebfdd282df2b18b8e10606ee2c5dfe6b9f3b4144
    Author: Steven Bickerton 
    Date:   Mon Apr 23 17:06:27 2012 -0500
    
        trivial bug fixes in topocentric-to-fk5 transform + new test.
    

    ad9e652d

    commit ad9e652d37eb8a8caf2feae975152f1a9c80d473
    Author: bick 
    Date:   Thu Mar 11 18:32:40 2010 +0000
    
        Added factory functions.
    

    4cb93054

    commit 4cb9305439f117bb6a04e225650d71d23e0c7a06
    Author: Paul Price 
    Date:   Mon Jun 3 09:23:05 2013 -0400
    
        add test for #2915
    

    d304da93

    commit d304da93ccf6b9879ea8a52bd737816b61d5eca6
    Author: bick 
    Date:   Thu Mar 11 23:55:19 2010 +0000
    
        Added point3d.
    

    5040cf2e

    commit 5040cf2ea802c7e345d3b6a1003aeaadd6822a08
    Author: bick 
    Date:   Fri Sep 9 22:20:51 2011 +0000
    
        #1761 added option to normalize Point3D input for Coord.
    

    f937c469

    commit f937c46927985aa5aa9ac63d238e991b37a112f9
    Author: bick 
    Date:   Sat Mar 13 23:04:39 2010 +0000
    
        more work on DateTime calls
    

    29df7008

    commit 29df7008c846afeffa2dea8c96e9923903ed8c86
    Author: bick 
    Date:   Thu Mar 25 22:48:33 2010 +0000
    
        #1188 Inlined some accessors.  Added exception for makeCoordEnum.
    

    05252a8f

    commit 05252a8fdd6ea59deb84da8264589f6a31e3a018
    Author: bick 
    Date:   Thu Jul 29 23:47:38 2010 +0000
    
        #1397 basic working code plus test and example.
    

    5b7a0990

    commit 5b7a0990e31d2075db774907d8b5ca7670fae77e
    Author: bick 
    Date:   Sun Mar 21 20:52:09 2010 +0000
    
        Added generic convert() method.  More tests.
    

    6c184547

    commit 6c1845474f28f528a95190eeb88f095b11999078
    Author: Steven Bickerton 
    Date:   Mon Feb 17 18:18:11 2014 +0900
    
        Check in #3092 (iterable coord) directly on master (due to accidental branch #3092 from #3093)
    

    6ee559f1

    commit 6ee559f1cc181d7213bbd4b80416a051a7b49b6d
    Author: Steven Bickerton 
    Date:   Sat Jan 4 14:38:04 2014 +0900
    
        correcting and testing a new bug introduced accidentally in #3093 bug fix.
    

    47fd8d77

    commit 47fd8d7755cc49e59d9e7519aa6a5ea8f72d7d13
    Author: bick 
    Date:   Wed Mar 24 14:51:04 2010 +0000
    
        #1188 Changed AltAz to Topocentric.  Added coord.h which includes deps.
    

    737686e9

    commit 737686e982a00f0b9d9d8e021d45b4e90f3cc4ea
    Author: bick 
    Date:   Sat Mar 6 01:53:37 2010 +0000
    
        check-in for basic coord tools.  Much editing yet to do.
    

    35a9ec57

    commit 35a9ec57e5f57f7381870d9dc25eb1d55bf1a63f
    Author: bick 
    Date:   Fri Mar 19 21:30:35 2010 +0000
    
        Cleaned-up tranformation api (everything through Fk5).
    

    b5487454

    commit b54874549a26c43dd8d462562e35c20c98a7428d
    Author: bick 
    Date:   Wed Mar 24 18:38:03 2010 +0000
    
        #1188 removed Equatorial class, added epochless factory functions.
    

    Commits in /Users/nate/repos_lsst/afw/

    a5a62a17

    commit a5a62a17d64209eed8759beeb9224c13af441af3
    Author: Russell Owen 
    Date:   Thu Apr 23 06:13:06 2015 -0700
    
        Improve Coord iteration in Python
        
        Add Coord.__len__ to Coord and subclasses
        Implement iteration for TopocentricCoord
    

    4d62652f

    commit 4d62652fa86a1c53d99c71ca845d3ea3af63565f
    Author: Russell Owen 
    Date:   Wed Apr 22 16:57:18 2015 -0700
    
        Improved string representations of Coords
        
        Improved os << Coord (in C++) and Coord.__str__ and __repr__ in Python
        for Coord and all subclasses, as follows:
        - The coordinate system is shown, even for clones (without the need to cast)
        - Positions are in degrees, instead of radians
        - IcrsCoord and GalacticCoord do not show the epoch
        - TopocentricCoord now has string representations, and the data includes Observatory
        - Coord.__str__ now uses C++ os << Coord, for simplicity and uniformity
        - Coord.__repr__ shows numbers (except observatory to full precision
          (except for observatory data for TopocentricCoord, since it didn't seem worth the extra clutter).
        - Coord.__repr__ omits the leading "afwCoord."
        
        Note: I would prefer to make Coord.__repr__ the same as __str__
        but it was more detailed so I left that feature.
        
        Make Coord.__str__ use << and add observatory information for topo
    

    15efb07a

    commit 15efb07ad418eb92d4b0d5dc9e4ef1617b2e2d37
    Author: John Swinbank 
    Date:   Wed Mar 18 11:49:42 2015 -0400
    
        Use value equality for coords.
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    62e64036

    commit 62e64036190f3533ebadf9ded426511a8826e409
    Author: Russell Owen 
    Date:   Fri Apr 24 13:07:18 2015 -0700
    
        Change tests/coord.py to use print as a function
        
        Updated coord.py to use from __future__ import print_function
        and updated print statements accordingly.
        Also there were a number of cases where "s" was being set to a string,
        which was then printed; I modified the code to just print the string
        without setting it to a temporary variable.
    

    Return to list

    examples/spatialCellExample.py

    Diff:

                    #!/usr/bin/env python
                    
                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    
                    """
                    An example using SpatialCells
                    
                    Run with:
                       python SpatialCellExample.py
                    or
                       python
                       >>> import SpatialCellExample; SpatialCellExample.run()
                    """
                    
                    import os
                    import sys
                    
    
    38 7f098229 - import eups
    38 7cbb2bb9 + import lsst.utils
    import lsst.afw.detection as afwDetect import lsst.afw.image.imageLib as afwImage import lsst.afw.math.mathLib as afwMath import lsst.afw.geom as afwGeom import lsst.afw.display.ds9 as ds9 import testSpatialCellLib try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def readImage(filename=None): """Read an image and background subtract it""" if not filename:
    57 7f098229 - dataDir = eups.productDir("afwdata")
    58 7f098229 - if not dataDir:
    57 7cbb2bb9 + try:
    58 7cbb2bb9 + afwDataDir = lsst.utils.getPackageDir("afwdata")
    59 7cbb2bb9 + except Exception:
    raise RuntimeError("You must provide a filename or setup afwdata to run these examples")
    61 7f098229 - filename = os.path.join(eups.productDir("afwdata"), "CFHT", "D4", "cal-53535-i-797722_1")
    ? ^^^^^^^^^^^ -----------
    62 7cbb2bb9 + filename = os.path.join(afwDataDir, "CFHT", "D4", "cal-53535-i-797722_1")
    ? ^^^^^ + bbox = afwGeom.Box2I(afwGeom.Point2I(270, 2530), afwGeom.Extent2I(512, 512)) else: bbox = None mi = afwImage.MaskedImageF(filename, 0, None, bbox, afwImage.LOCAL) mi.setXY0(afwGeom.Point2I(0, 0)) # # Subtract the background. We'd use a canned procedure, but that's in meas/utils/sourceDetection.py. We # can't fix those pesky cosmic rays either, as that's in a dependent product (meas/algorithms) too # bctrl = afwMath.BackgroundControl(afwMath.Interpolate.NATURAL_SPLINE) bctrl.setNxSample(int(mi.getWidth()/256) + 1) bctrl.setNySample(int(mi.getHeight()/256) + 1) sctrl = bctrl.getStatisticsControl() sctrl.setNumSigmaClip(3.0) sctrl.setNumIter(2) im = mi.getImage() try: backobj = afwMath.makeBackground(im, bctrl) except Exception, e: print >> sys.stderr, e, bctrl.setInterpStyle(afwMath.Interpolate.CONSTANT) backobj = afwMath.makeBackground(im, bctrl) im -= backobj.getImageF() # # Find sources # threshold = afwDetect.Threshold(5, afwDetect.Threshold.STDEV) npixMin = 5 # we didn't smooth fs = afwDetect.FootprintSet(mi, threshold, "DETECTED", npixMin) grow, isotropic = 1, False fs = afwDetect.FootprintSet(fs, grow, isotropic) fs.setMask(mi.getMask(), "DETECTED") return mi, fs #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def SpatialCellSetDemo(filename=None): """A demonstration of the use of a SpatialCellSet""" im, fs = readImage(filename) if display: ds9.mtv(im, frame=0, title="Input") # # Create an (empty) SpatialCellSet # cellSet = afwMath.SpatialCellSet(afwGeom.Box2I(afwGeom.Point2I(0, 0), im.getDimensions()), 260, 200) if display: for i in range(len(cellSet.getCellList())): cell = cellSet.getCellList()[i] ds9.line([(cell.getBBox().getMinX(), cell.getBBox().getMinY()), (cell.getBBox().getMinX(), cell.getBBox().getMaxY()), (cell.getBBox().getMaxX(), cell.getBBox().getMaxY()), (cell.getBBox().getMaxX(), cell.getBBox().getMinY()), (cell.getBBox().getMinX(), cell.getBBox().getMinY()), ], frame=0) ds9.dot(cell.getLabel(), (cell.getBBox().getMinX() + cell.getBBox().getMaxX())/2, (cell.getBBox().getMinY() + cell.getBBox().getMaxY())/2) # # Populate cellSet # for foot in fs.getFootprints(): bbox = foot.getBBox() xc = (bbox.getMinX() + bbox.getMaxX())/2.0 yc = (bbox.getMinY() + bbox.getMaxY())/2.0 tc = testSpatialCellLib.ExampleCandidate(xc, yc, im, bbox) cellSet.insertCandidate(tc) # # OK, the SpatialCellList is populated. Let's do something with it # visitor = testSpatialCellLib.ExampleCandidateVisitor() cellSet.visitCandidates(visitor) print "There are %d candidates" % (visitor.getN()) ctypes = ["red", "yellow", "cyan", ] for i in range(cellSet.getCellList().size()): cell = cellSet.getCellList()[i] cell.visitCandidates(visitor) j = 0 for cand in cell: # # Swig doesn't know that we're a SpatialCellImageCandidate; all it knows is that we have # a SpatialCellCandidate so we need an explicit (dynamic) cast # cand = testSpatialCellLib.cast_ExampleCandidate(cand) w, h = cand.getBBox().getDimensions() if w*h < 75: #print "%d %5.2f %5.2f %d" % (i, cand.getXCenter(), cand.getYCenter(), w*h) cand.setStatus(afwMath.SpatialCellCandidate.BAD) if display: ds9.dot("o", cand.getXCenter(), cand.getYCenter(), size=4, ctype=ctypes[i%len(ctypes)]) else: if display: ds9.dot("%s:%d" % (cand.getId(), j), cand.getXCenter(), cand.getYCenter(), size=4, ctype=ctypes[i%len(ctypes)]) j += 1 im = cand.getMaskedImage() if 0 and display: ds9.mtv(im, title="Candidate", frame=1) # # Now count the good and bad candidates # for i in range(len(cellSet.getCellList())): cell = cellSet.getCellList()[i] cell.visitCandidates(visitor) cell.setIgnoreBad(False) # include BAD in cell.size() print "%s nobj=%d N_good=%d NPix_good=%d" % \ (cell.getLabel(), cell.size(), visitor.getN(), visitor.getNPix()) cellSet.setIgnoreBad(True) # don't visit BAD candidates cellSet.visitCandidates(visitor) print "There are %d good candidates" % (visitor.getN()) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def run(): """Run the tests""" SpatialCellSetDemo() if __name__ == "__main__": run()

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7f098229

    commit 7f09822926b0747b1c1ced7c089fb9c65bc1e679
    Author: rhl 
    Date:   Wed Dec 30 22:30:52 2009 +0000
    
        Added ability of visit all the candidates in a SpatialCell (not just a SpatialCellSet);  started working on an example to be part of the documentation
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    tests/sipterms.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #define BOOST_TEST_DYN_LINK
                    #define BOOST_TEST_MODULE sipterms
                     
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/test/unit_test.hpp"
                    #pragma clang diagnostic pop
                    
                    using namespace std;
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    #include "boost/shared_ptr.hpp"
                    #include "Eigen/Core"
                    
                    #include "lsst/afw/image/TanWcs.h"
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/geom/Angle.h"
                    #include "lsst/afw/math/FunctionLibrary.h"
                    #include "lsst/afw/coord/Coord.h"
    
    45 742ec6fa - #include "lsst/afw/coord/Utils.h"
    namespace math = lsst::afw::math; namespace afwImg = lsst::afw::image; namespace afwGeom = lsst::afw::geom; namespace afwCoord = lsst::afw::coord; double calculateDistortion( Eigen::MatrixXd sip, double u, double v) { ///Computes all terms in the matrix, which the sip standard tells you not to do. ///At least the standard says they are not used. Does this mean set to zero or not ///computed? assert(sip.rows() == sip.cols()); int i, j; int size = sip.rows(); double distort=0; for(i=0; itoFk5(); afwCoord::Fk5Coord sip = sipWcs.pixelToSky(x0+u, y0+v)->toFk5(); if(1) { printf("\n%.1f %.1f : %.3f\n", u, v, distortX); printf("%.7f %.7f \n", lin.getRa().asDegrees(), lin.getDec().asDegrees()); printf("%.7f %.7f \n", sip.getRa().asDegrees(), sip.getDec().asDegrees()); printf("Diff: %.7f %.7f \n", sip.getRa().asDegrees() - lin.getRa().asDegrees(), \ sip.getDec().asDegrees() - lin.getDec().asDegrees()); } BOOST_CHECK_CLOSE(lin.getRa().asDegrees(), sip.getRa().asDegrees(), 1e-7); BOOST_CHECK_CLOSE(lin.getDec().asDegrees(), sip.getDec().asDegrees(), 1e-7); v+=step; } u+=step; } } void testSipP(afwImg::TanWcs &linWcs, afwImg::TanWcs &sipWcs, Eigen::MatrixXd sipAp, Eigen::MatrixXd sipBp) { //Test the reverse coefficients. //Given sipAp, sipBp, and a position, calculate the expected distortion. Check the linearWcs //at position+distortion gives the same answer as sipWcs at position double range=.25; double step=.0625; afwGeom::Point2D xy0 = linWcs.getPixelOrigin(); afwCoord::Fk5Coord raDec0 = linWcs.getSkyOrigin()->toFk5(); double ra = raDec0.getRa().asDegrees() - range; double raUpr = raDec0.getRa().asDegrees() + range; while(ra<= raUpr) { double dec = raDec0.getDec().asDegrees() - range; double decUpr = raDec0.getDec().asDegrees() + range; while(dec<= decUpr) { afwCoord::Coord::Ptr rd = afwCoord::makeCoord(afwCoord::FK5, ra * afwGeom::degrees, dec * afwGeom::degrees); afwGeom::Point2D xy = linWcs.skyToPixel(*rd); afwGeom::Point2D xySip = sipWcs.skyToPixel(*rd); //Get pixel origin returns crpix in fits coords, so we convert to //lsst coords before using (hence the -1) double u = xy[0] - xy0[0]; double v = xy[1] - xy0[1]; double distortX = calculateDistortion(sipAp, u, v); double distortY = calculateDistortion(sipBp, u, v); { printf("\ntestSipP()\n%.7f %.7f\n", ra, dec); printf("%.4f %.4f : %.4f %.4f\n", u, v, distortX, distortY); printf("%.4f %.4f \n", xy[0], xy[1]); printf("%.4f %.4f \n", xySip[0], xySip[1]); printf("Diff: %.4f %.4f \n", xySip[0]-xy[0], xySip[1]-xy[1]); } BOOST_CHECK_CLOSE(xy[0] + distortX, xySip[0], 1e-4); BOOST_CHECK_CLOSE(xy[1] + distortY, xySip[1], 1e-4); dec+=step; } ra+=step; } } BOOST_AUTO_TEST_CASE(basic) { afwGeom::Point2D crval = afwGeom::Point2D(45.,45.); afwGeom::Point2D crpix = afwGeom::Point2D(10,10); Eigen::MatrixXd CD(2,2); double arcsecPerPixel = 0.000277777777777778; CD(0,0) = arcsecPerPixel; CD(0,1) = 0; CD(1,0) = 0; CD(1,1) = arcsecPerPixel; Eigen::Matrix3d sipA; Eigen::Matrix3d sipB; Eigen::Matrix3d sipAp; Eigen::Matrix3d sipBp; //zero the sips for(int i=0; i<3; ++i) { for(int j=0; j<3; ++j) { sipA(i, j) = 0; sipB(i, j) = 0; sipAp(i, j) = 0; sipBp(i, j) = 0; } } afwImg::TanWcs linWcs(crval, crpix, CD); //Test x direction // printf("Quadratic in x\n"); //quadratic in x direction sipA(2,0) = 1e-4; afwImg::TanWcs sipWcs1(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSip(linWcs, sipWcs1, sipA, sipB); sipA(2,0) = 0; //Quadratic in y printf("Quadratic in y\n"); sipA(0,2) = 1e-4; afwImg::TanWcs sipWcs2(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSip(linWcs, sipWcs2, sipA, sipB); sipA(0,2) = 0; //Cross term printf("Cross terms\n"); sipA(1,1) = 1e-4; afwImg::TanWcs sipWcs3(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSip(linWcs, sipWcs3, sipA, sipB); sipA(1,1) = 0; //test y direction // printf("Quadratic in y\n"); sipB(2,0) = 1e-4; afwImg::TanWcs sipWcs4(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSip(linWcs, sipWcs4, sipA, sipB); sipB(2,0) = 0; //Quadratic in y printf("Quadratic in x(y)\n"); sipA(0,2) = 1e-4; afwImg::TanWcs sipWcs5(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSip(linWcs, sipWcs5, sipA, sipB); sipA(0,2) = 0; //Cross term printf("x' = f(x,y)\n"); sipA(1,1) = 1e-4; afwImg::TanWcs sipWcs6(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSip(linWcs, sipWcs6, sipA, sipB); sipA(1,1) = 0; /// //Test reverse coeff. /// printf("inverse 1\n"); sipAp(2,0) = 1.e-4; afwImg::TanWcs sipWcs7(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSipP(linWcs, sipWcs7, sipAp, sipBp); sipAp(2,0) = 0; //The linear term is allowed in the reverse matrix printf("inverse 2\n"); sipAp(1,0) = 1.e-4; afwImg::TanWcs sipWcs8(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSipP(linWcs, sipWcs8, sipAp, sipBp); sipAp(1,0) = 0; printf("inverse 3\n"); sipBp(2,0) = 1.e-4; afwImg::TanWcs sipWcs9(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSipP(linWcs, sipWcs9, sipAp, sipBp); sipBp(2,0) = 0; //The linear term is allowed in the reverse matrix printf("inverse 4\n"); sipBp(1,0) = 1.e-4; afwImg::TanWcs sipWcs10(crval, crpix, CD, sipA, sipB, sipAp, sipBp); testSipP(linWcs, sipWcs10, sipAp, sipBp); sipBp(1,0) = 0; } // // ****************************************************************************************************** // void createSipTests(afwImg::TanWcs &wcs1, afwImg::TanWcs &wcs2) { afwGeom::Point2D xy = wcs1.getPixelOrigin(); double x0 = xy[0]-1; double y0 = xy[1]-1; double range=1000; double step=1000; double u = -1*range; //Relative pixel coord in x while(u<= range) { double v=-1*range; while(v<= range) { afwCoord::Fk5Coord pos1 = wcs1.pixelToSky(x0+u, y0+v)->toFk5(); afwCoord::Fk5Coord pos2 = wcs2.pixelToSky(x0+u, y0+v)->toFk5(); printf("\n%.1f %.1f \n", u, v); printf("%.7f %.7f \n", pos1.getRa().asDegrees(), pos1.getDec().asDegrees()); printf("%.7f %.7f \n", pos2.getRa().asDegrees(), pos2.getDec().asDegrees()); BOOST_CHECK_CLOSE(pos1.getRa().asDegrees(), pos2.getRa().asDegrees(), 1e-7); BOOST_CHECK_CLOSE(pos1.getDec().asDegrees(), pos2.getDec().asDegrees(), 1e-7); v+=step; } u+=step; } }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    742ec6fa

    commit 742ec6fa6cea7a062c1e14dd51c096885fe7c637
    Author: fergal 
    Date:   Tue Jun 15 21:27:29 2010 +0000
    
        Check that TanWcs is correctly calculating distortion given a sip matrix.
    

    Commits in /Users/nate/repos_lsst/afw/

    Return to list

    include/lsst/afw/geom/CoordinateExpr.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief A boolean pair class used to express the output of spatial predicates on Point and Extent.
                     */
                    #ifndef LSST_AFW_GEOM_COORDINATEEXPR_H
                    #define LSST_AFW_GEOM_COORDINATEEXPR_H
                    
                    #include "lsst/afw/geom/CoordinateBase.h"
                    
                    namespace lsst { namespace afw { namespace geom {
                    
                    /**
                     *  \brief A boolean coordinate.
                     *
                     *  CoordinateExpr is intended to be used as a temporary in coordinate comparisons:
                     *  \code
                     *  Point2D a(3.5,1.2);
                     *  Point2D b(-1.5,4.3);
                     *  std::cout << all(a.lt(b)) << std::endl;  // false
                     *  std::cout << any(a.lt(b)) << std::endl;  // true
                     *  \endcode
                     *  
                     *  CoordinateExpr is not a true lazy-evaluation expression template, as that seems unnecessary when
                     *  the object is typically only two bools large (smaller than the raw pointers necessary to implement
                     *  a lazy solution).  The consequence is that there's no short-circuiting of logical operators, but I don't
                     *  think that will even remotely matter for most use cases.  The any() and all() functions do support
                     *  short-circuiting.
                     */
                    template
                    class CoordinateExpr : public CoordinateBase,bool,N> {
                        typedef CoordinateBase,bool,N> Super;
                    public:
                    
                        /// \brief Construct a CoordinateExpr with all elements set to the same scalar value.
                        explicit CoordinateExpr(bool val=false) : Super(val) {}
                    
                        /// \brief Construct a CoordinateExpr from an Eigen vector.
                        template 
                        explicit CoordinateExpr(Eigen::MatrixBase const & vector) : Super(vector) {}
                    
                        /**
                         *  @name Logical operators
                         *
                         *  These operators do not provide interoperability with scalars.
                         */
                        //@{
                        CoordinateExpr and_(CoordinateExpr const & rhs) const;
                        CoordinateExpr or_(CoordinateExpr const & rhs) const;
                        CoordinateExpr not_() const;
                        //@}
                    
                    };
                    
                    /// \brief Return true if all elements are true.
                    template 
                    inline bool all(CoordinateExpr const & expr) {
    
    81 a8e2a7e9 - for (register int n=0; n ? ---------
    81 51a67dff + for (int n=0; n return true; } /// \brief Return true if any elements are true. template inline bool any(CoordinateExpr const & expr) {
    88 7ccf406e - for (register int n=0; n ? ---------
    88 51a67dff + for (int n=0; n return false; } typedef CoordinateExpr<2> CoordinateExpr2; typedef CoordinateExpr<3> CoordinateExpr3; }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7ccf406e

    commit 7ccf406eabf8ad8f018a7d66cf517ddeaa94d9e1
    Author: jbosch 
    Date:   Mon Dec 14 19:43:59 2009 +0000
    
        afw/892:
         - implementations for geom (all but Box now done)
         - fixed compilation errors in ellipses and tests for ellipses
         - merged updates from trunk in (fixed an obvious typo introduced in math::offsetImage by the merge)
    

    a8e2a7e9

    commit a8e2a7e9666f30c2384ae6bb3557181f65684db7
    Author: jbosch 
    Date:   Mon Dec 21 23:37:41 2009 +0000
    
        afw/#1095 - swig wrappers, some tests for BoxI and BoxD.
    

    Commits in /Users/nate/repos_lsst/afw/

    51a67dff

    commit 51a67dff1f2d5067d66ad025fe1efee37aeca339
    Author: Russell Owen 
    Date:   Tue Oct 14 12:50:44 2014 -0700
    
        Remove use of deprecated C++ keyword "register"
    

    Return to list

    python/lsst/afw/display/SConscript

    Diff:

                    # -*- python -*-
                    from lsst.sconsUtils import scripts
    
    3 16cfe977 - scripts.BasicSConscript.python(['displayLib', 'xpa'],
    ? -------
    3 f6a3296b + scripts.BasicSConscript.python(['displayLib'],
    4 f49676d7 - swigSrc={"displayLib": ["saturated.cc", "scaling.cc", "simpleFits.cc"]})
    ? --------------
    4 7e2503b6 + swigSrc={"displayLib": ["saturated.cc", "simpleFits.cc"]})

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    16cfe977

    commit 16cfe9776e35798afb73eab2a10ce798ab25dcca
    Author: Robert Lupton the Good 
    Date:   Mon Mar 16 18:01:42 2015 -0400
    
        Initial port/rewrite from afw_extensions_rgb
        
        With changes from code reviews squashed in
    

    f49676d7

    commit f49676d7f1348f9de8ca21ee633e0c25473251ae
    Author: Robert Lupton the Good 
    Date:   Sun Apr 19 10:50:17 2015 -0300
    
        Implemented Linear and ZScale transformations, HSC-1206
        
        Linear was already available with Q=0, but this way is clearer; the default is to use min/max limits.
        
        I also added AsinhZScaleMapping which uses the zscale code to set the stretch.
        
        I did not port the log mappings, as the C++ is not really something I'd like to see in the long-term stack (e.g. reinterpret_casts between ints and doubles).
        It would be easy to add a LogMapper in pure python, and if this is needed please open a new issue.
        
        The ZScale code comes from Mineo-san's fitsthumb, but doesn't give quite the same upper limit as ds9.  I'm not sure where the discrepancy is, but I don't think it matters.
    

    Commits in /Users/nate/repos_lsst/afw/

    7e2503b6

    commit 7e2503b6b492a50a007c974e9a05a2cc64fd0138
    Author: Robert Lupton the Good 
    Date:   Mon Mar 16 18:01:42 2015 -0400
    
        Initial port/rewrite from afw_extensions_rgb
        
        With changes from code reviews squashed in
    

    f6a3296b

    commit f6a3296b0ba9d6efe64f8d0087a8d4323e2811a8
    Author: Russell Owen 
    Date:   Thu May 14 15:37:48 2015 -0700
    
        Remove vestiges of xpa
        
        Remove another instance of xpa
    

    Return to list

    examples/simpleConvolve.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    #include 
                    
    
    27 1192e949 - #include "lsst/daf/base.h"
    27 a9aec7fc + #include "lsst/utils/Utils.h"
    28 a9aec7fc + #include "lsst/pex/exceptions.h"
    #include "lsst/pex/logging/Trace.h"
    29 1192e949 - #include "lsst/afw/math/FunctionLibrary.h"
    ? ----------------
    30 a9aec7fc + #include "lsst/afw/math.h"
    30 1192e949 - #include "lsst/afw/image/Image.h"
    ? ------
    31 a9aec7fc + #include "lsst/afw/image.h"
    31 f8edfe90 - #include "lsst/afw/image/MaskedImage.h"
    32 1192e949 - #include "lsst/afw/math/Kernel.h"
    33 1192e949 - #include "lsst/afw/math/KernelFunctions.h"
    35 09aeac64 - using namespace std;
    36 52012c0a - const std::string outFile("scOut");
    ? ^^^
    33 a9aec7fc + const std::string outImagePath("scOut.fits");
    ? ^^^^ ++++ +++++ namespace afwImage = lsst::afw::image; namespace afwMath = lsst::afw::math; int main(int argc, char **argv) { typedef afwMath::Kernel::Pixel Pixel; unsigned int kernelCols = 6; unsigned int kernelRows = 5; lsst::pex::logging::Trace::setDestination(std::cout); lsst::pex::logging::Trace::setVerbosity("lsst.afw.kernel", 5); const double DefSigma = 2.0;
    50 8c6c0d93 - std::string mimg;
    ? ^^
    47 a9aec7fc + std::string inImagePath;
    ? +++ ^ +++++ if (argc < 2) {
    52 8c6c0d93 - std::string afwdata = getenv("AFWDATA_DIR");
    53 8c6c0d93 - if (afwdata.empty()) {
    49 a9aec7fc + try {
    50 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
    51 a9aec7fc + inImagePath = dataDir + "/data/small.fits";
    52 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    54 8c6c0d93 - std::cerr << "Usage: simpleConvolve fitsFile [sigma]" << std::endl;
    53 a9aec7fc + std::cerr << "Usage: simpleConvolve [fitsFile [sigma]]" << std::endl;
    ? + +
    55 8c6c0d93 - std::cerr << "fitsFile excludes the \"_img.fits\" suffix" << std::endl;
    54 a9aec7fc + std::cerr << "fitsFile is the path to a masked image" << std::endl;
    std::cerr << "sigma (default " << DefSigma << ") is the width of the gaussian kernel, in pixels" << std::endl;
    58 8c6c0d93 - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << std::endl;
    59 8c6c0d93 - std::cerr << "Is afwdata set up?\n" << std::endl;
    ? ^ ^^^^
    57 a9aec7fc + std::cerr << "\nError: setup afwdata or specify fitsFile.\n" << std::endl;
    ? ^^^^^^^^^ ++++ +++ + +++++++ ^^^^^^ exit(EXIT_FAILURE);
    61 8c6c0d93 - } else {
    62 8c6c0d93 - mimg = afwdata + "/small_MI";
    63 8c6c0d93 - std::cerr << "Using " << mimg << std::endl;
    } } else {
    66 8c6c0d93 - mimg = std::string(argv[1]);
    ? ^^
    61 a9aec7fc + inImagePath = std::string(argv[1]);
    ? +++ ^ +++++
    62 52012c0a + }
    63 a9aec7fc + std::cerr << "Convolving masked image " << inImagePath << std::endl;
    64 52012c0a +
    65 a9aec7fc + double sigma = DefSigma;
    66 a9aec7fc + if (argc > 2) {
    67 a9aec7fc + std::istringstream(argv[2]) >> sigma;
    }
    69 9ad1f322 - { // block in which to allocate and deallocate memory
    70 a9aec7fc + // read in fits file
    71 a9aec7fc + afwImage::MaskedImage mImage(inImagePath);
    71 9ad1f322 - double sigma = DefSigma;
    72 9ad1f322 - if (argc > 2) {
    73 7642fd70 - std::istringstream(argv[2]) >> sigma;
    74 9ad1f322 - }
    75 9ad1f322 -
    76 9ad1f322 - // read in fits file
    77 8c6c0d93 - afwImage::MaskedImage mImage(mimg);
    78 9ad1f322 -
    79 9ad1f322 - // construct kernel
    ? ----
    73 a9aec7fc + // construct kernel
    80 f1382d6d - afwMath::GaussianFunction2 gaussFunc(sigma, sigma, 0);
    ? ----
    74 a9aec7fc + afwMath::GaussianFunction2 gaussFunc(sigma, sigma, 0);
    81 f8edfe90 - afwMath::AnalyticKernel kernel(kernelCols, kernelRows, gaussFunc);
    ? ----
    75 a9aec7fc + afwMath::AnalyticKernel kernel(kernelCols, kernelRows, gaussFunc);
    82 52012c0a -
    83 9ad1f322 - // convolve
    84 068759b9 - afwImage::MaskedImage resMaskedImage(mImage.getDimensions());
    85 4d9957d5 - afwMath::convolve(resMaskedImage, mImage, kernel, true);
    86 52012c0a -
    87 9ad1f322 - // write results
    88 9ad1f322 - resMaskedImage.writeFits(outFile);
    89 9ad1f322 - }
    77 a9aec7fc + // convolve
    78 a9aec7fc + afwImage::MaskedImage resMaskedImage(mImage.getDimensions());
    79 a9aec7fc + afwMath::convolve(resMaskedImage, mImage, kernel, true);
    80 a9aec7fc +
    81 a9aec7fc + // write results
    82 a9aec7fc + resMaskedImage.writeFits(outImagePath);
    83 a9aec7fc + std::cerr << "Wrote convolved image " << outImagePath << std::endl;
    91 9ad1f322 - //
    92 9ad1f322 - // Check for memory leaks
    93 9ad1f322 - //
    94 17b33433 - if (lsst::daf::base::Citizen::census(0) != 0) {
    95 9ad1f322 - std::cerr << "Leaked memory blocks:" << std::endl;
    96 17b33433 - lsst::daf::base::Citizen::census(std::cerr);
    97 9ad1f322 - }
    98 9ad1f322 -
    }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    068759b9

    commit 068759b9de5ac7caee50d816e7ff6d2c468b4867
    Author: rowen 
    Date:   Mon Sep 28 21:26:58 2009 +0000
    
        Changed Kernel's PixelT to Pixel and PtrT to Ptr
        Added Kernel::ConstPtr
        Renamed KernelList specializations to remove final D (except KernelList itself,
        alas, because I could not make that work).
        Renamed some math .i files to the proper convention.
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    8c6c0d93

    commit 8c6c0d93eaf03478cc6379a16055c3ae6119aa35
    Author: bick 
    Date:   Fri Jan 8 21:49:43 2010 +0000
    
        #1113 Changed examples to default to afwdata fits files with no arguments.
    

    9ad1f322

    commit 9ad1f3223e6e245d1311ff76ad39324eb3c3eb4d
    Author: rowen 
    Date:   Fri Aug 17 23:20:15 2007 +0000
    
        Merged ticket 123: python interface and test cases for Kernel and Function classes
    

    09aeac64

    commit 09aeac6456ff16d14f85af8ee6e092214337bb85
    Author: rallsman 
    Date:   Wed Sep 19 21:11:54 2007 +0000
    
        Merged revisions 2415-2441,2444-2516 via svnmerge from
        svn+ssh://rallsman@svn.lsstcorp.org/DC2/fw/tickets/146
        
        ........
          r2415 | rallsman | 2007-09-10 11:46:18 -0700 (Mon, 10 Sep 2007) | 1 line
        
          Coordinating fw to mwi ticket:146
        ........
          r2417 | rallsman | 2007-09-10 12:52:03 -0700 (Mon, 10 Sep 2007) | 8 lines
        
          Updated a clone of fw.trunk (fw/tickets/146) to compile with mwi-1.2 .
        
          fw/tests execute OK but that's extent of validation.
        
          Switched all throws of generic mwi::Exception to Runtime;
          Switched all catches of generic mwi::Exception to ExceptionStack
        ........
          r2440 | rallsman | 2007-09-11 16:17:44 -0700 (Tue, 11 Sep 2007) | 2 lines
        
          Repaired code which failed when 'using namespace std;' was removed from headers.
        ........
    

    52012c0a

    commit 52012c0a4be0641b9758c479a033b2ca7a6b5f86
    Author: rowen 
    Date:   Wed Jul 25 00:17:53 2007 +0000
    
        Merge ticket25 to the trunk
    

    17b33433

    commit 17b3343327cfb0f07f6e5c86d173117c4d42a359
    Author: rowen 
    Date:   Mon Mar 31 21:17:42 2008 +0000
    
        afw reorg:
        - Adapted to new daf/base classes
        - Removed some unused includes
        - Added some missing or implied includes
        - Removed many instances of "using" from formatter header files
        - Started process of renaming WCS class to Wcs (still need to move one or two files)
    

    4d9957d5

    commit 4d9957d519bf0293a85fdd5585bf071afb38dd4b
    Author: rowen 
    Date:   Thu Jun 4 00:18:53 2009 +0000
    
        Implemented ticket #806: improve setting of edge pixels in convolve function.
        Note that this is an API change:
        - the convolve and convolveLinear functions have lost their edgeBit arguments
        - convolved edge pixels are now (NaN, EDGE, info) for MaskedImage and NaN for Image
        All unit tests and examples have been updated accordingly.
        
        Also added the following subroutines to lsst.afw.image.testUtils:
          imagesDiffer, masksDiffer and maskedImagesDiffer
        and modified the following tests to use them:
          ConvolveImage_1.py, ConvolveMaskedImage_1.py and warpExposure_1.py
    

    f1382d6d

    commit f1382d6d8aa2f1cd7290edd0a5c0d08f900f3d7a
    Author: rowen 
    Date:   Wed Nov 18 01:39:26 2009 +0000
    
        First cut. Haven't finished testing it.
    

    1192e949

    commit 1192e9492b9dfbc05ab4c1de8827e39fbecc14a8
    Author: rowen 
    Date:   Tue Jun 24 19:53:51 2008 +0000
    
        Merge in ticket 350.
        (Note: this was done using rsync because I couldn't get
        svnmerge.py to merge any files -- it ran but did nothing).
        
        See ticket 350 for details, but the basics are:
        - Added SeparableKernel, and associated specialized convolution code
        - Modified Kernel::computeImage, Kernel::computeNewImage
          such that doNormalize comes before x, y arguments
          and has no default value (ticket 191).
          Warning: existing code may compile but give wrong answers!
        - Modified convolve such that doNormalize has no default value (ticket 191).
        - Globally modified include paths to use "" instead of <>
          for lsst and 3rd party packages (as per new standard)
        - Added Function::get/setParameter methods
        - Added Kernel::setCtrCol/Row methods
        - Removed radial lanczos from function library;
          only the separable version is now present.
    

    7642fd70

    commit 7642fd707104f68b4bf054c73e5e25e247d66bc2
    Author: rowen 
    Date:   Wed Sep 12 21:42:49 2007 +0000
    
        Merged ticket 157 (fix namespace issues; reported by Robyn)
    

    Commits in /Users/nate/repos_lsst/afw/

    52012c0a

    commit 52012c0a4be0641b9758c479a033b2ca7a6b5f86
    Author: rowen 
    Date:   Wed Jul 25 00:17:53 2007 +0000
    
        Merge ticket25 to the trunk
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    src/math/LeastSquares.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010, 2011 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    #include "Eigen/Eigenvalues"
                    #include "Eigen/SVD"
                    #include "Eigen/Cholesky"
                    #include "boost/format.hpp"
                    #include "boost/make_shared.hpp"
                    
                    #include "lsst/afw/math/LeastSquares.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging.h"
                    
                    namespace lsst { namespace afw { namespace math {
                    
                    class LeastSquares::Impl {
                    public:
                    
                        enum StateFlags { 
                            LOWER_FISHER_MATRIX     = 0x001,
                            FULL_FISHER_MATRIX      = 0x002,
                            RHS_VECTOR              = 0x004,
                            SOLUTION_ARRAY          = 0x008,
                            COVARIANCE_ARRAY        = 0x010,
                            DIAGNOSTIC_ARRAY        = 0x020,
                            DESIGN_AND_DATA         = 0x040
                        };
                    
                        int state;
                        int dimension;
                        int rank;
                        Factorization factorization;
                        Factorization whichDiagnostic;
                        double threshold;
                    
                        Eigen::MatrixXd design;
                        Eigen::VectorXd data;
                        Eigen::MatrixXd fisher;
                        Eigen::VectorXd rhs;
                    
                        ndarray::Array solution;
                        ndarray::Array covariance;
                        ndarray::Array diagnostic;
                    
                        pex::logging::Debug log;
                    
                        template 
                        void setRank(Eigen::MatrixBase const & values) {
                            double cond = threshold * values[0];
                            if (cond <= 0.0) {
                                rank = 0;
                            } else {
                                for (rank = dimension; (rank > 1) && (values[rank-1] < cond); --rank);
                            }
                        }
                    
                        void ensure(int desired) {
                            if (state & FULL_FISHER_MATRIX) state |= LOWER_FISHER_MATRIX;
                            if (desired & FULL_FISHER_MATRIX) desired |= LOWER_FISHER_MATRIX;
                            int toAdd = ~state & desired;
                            if (toAdd & LOWER_FISHER_MATRIX) {
                                assert(state & DESIGN_AND_DATA);
                                fisher = Eigen::MatrixXd::Zero(design.cols(), design.cols());
                                fisher.selfadjointView().rankUpdate(design.adjoint());
                            }
                            if (toAdd & FULL_FISHER_MATRIX) {
                                fisher.triangularView() = fisher.adjoint();
                            }
                            if (toAdd & RHS_VECTOR) {
                                assert(state & DESIGN_AND_DATA);
                                rhs = design.adjoint() * data;
                            }
                            if (toAdd & SOLUTION_ARRAY) {
                                if (solution.isEmpty()) solution = ndarray::allocate(dimension);
                                updateSolution();
                            }
                            if (toAdd & COVARIANCE_ARRAY) {
                                if (covariance.isEmpty()) covariance = ndarray::allocate(dimension, dimension);
                                updateCovariance();
                            }
                            if (toAdd & DIAGNOSTIC_ARRAY) {
                                if (diagnostic.isEmpty()) diagnostic = ndarray::allocate(dimension);
                                updateDiagnostic();
                            }
                            state |= toAdd;
                        }
                    
                        virtual void factor() = 0;
                    
                        virtual void updateRank() = 0;
                    
                        virtual void updateSolution() = 0;
                        virtual void updateCovariance() = 0;
                    
                        virtual void updateDiagnostic() = 0;
                    
                        Impl(int dimension_, double threshold_=std::numeric_limits::epsilon()) : 
                            state(0), dimension(dimension_), rank(dimension_), threshold(threshold_), 
                            log("afw.math.LeastSquares")
                            {}
                    
                        virtual ~Impl() {}
                    };
                    
                    namespace {
                    
                    class EigensystemSolver : public LeastSquares::Impl {
                    public:
                    
                        explicit EigensystemSolver(int dimension) :
                            Impl(dimension), _eig(dimension), _svd(), _tmp(dimension)
                        {}
                        
                        virtual void factor() {
                            ensure(LOWER_FISHER_MATRIX | RHS_VECTOR);
                            _eig.compute(fisher);
                            if (_eig.info() == Eigen::Success) {
                                setRank(_eig.eigenvalues().reverse());
                                log.debug<5>("SelfAdjointEigenSolver succeeded: dimension=%d, rank=%d", dimension, rank);
                            } else {
                                // Note that the fallback is using SVD of the Fisher to compute the Eigensystem, because those
                                // are the same for a symmetric matrix; this is very different from doing a direct SVD of
                                // the design matrix.
                                ensure(FULL_FISHER_MATRIX);
                                _svd.compute(fisher, Eigen::ComputeFullU); // Matrix is symmetric, so V == U == eigenvectors
                                setRank(_svd.singularValues());
                                log.debug<5>(
                                    "SelfAdjointEigenSolver failed; falling back to equivalent SVD: dimension=%d, rank=%d",
                                    dimension, rank
                                );
                            }
                        }
                    
                        virtual void updateRank() {
                            if (_eig.info() == Eigen::Success) {
                                setRank(_eig.eigenvalues().reverse());
                            } else {
                                setRank(_svd.singularValues());
                            }
                        }
                    
                        virtual void updateDiagnostic() {
                            if (whichDiagnostic == LeastSquares::NORMAL_CHOLESKY) {
                                throw LSST_EXCEPT(
    
    166 cd48db28 - pex::exceptions::LogicErrorException,
    ? ---------
    166 21597d88 + pex::exceptions::LogicError,
    "Cannot compute NORMAL_CHOLESKY diagnostic from NORMAL_EIGENSYSTEM factorization." ); } if (_eig.info() == Eigen::Success) { diagnostic.asEigen() = _eig.eigenvalues().reverse(); } else { diagnostic.asEigen() = _svd.singularValues(); } if (whichDiagnostic == LeastSquares::DIRECT_SVD) { diagnostic.asEigen() = diagnostic.asEigen().sqrt(); } } virtual void updateSolution() { if (rank == 0) { solution.asEigen().setZero(); return; } if (_eig.info() == Eigen::Success) { _tmp.head(rank) = _eig.eigenvectors().rightCols(rank).adjoint() * rhs; _tmp.head(rank).array() /= _eig.eigenvalues().tail(rank).array(); solution.asEigen() = _eig.eigenvectors().rightCols(rank) * _tmp.head(rank); } else { _tmp.head(rank) = _svd.matrixU().leftCols(rank).adjoint() * rhs; _tmp.head(rank).array() /= _svd.singularValues().head(rank).array(); solution.asEigen() = _svd.matrixU().leftCols(rank) * _tmp.head(rank); } } virtual void updateCovariance() { if (rank == 0) { covariance.asEigen().setZero(); return; } if (_eig.info() == Eigen::Success) { covariance.asEigen() = _eig.eigenvectors().rightCols(rank) * _eig.eigenvalues().tail(rank).array().inverse().matrix().asDiagonal() * _eig.eigenvectors().rightCols(rank).adjoint(); } else { covariance.asEigen() = _svd.matrixU().leftCols(rank) * _svd.singularValues().head(rank).array().inverse().matrix().asDiagonal() * _svd.matrixU().leftCols(rank).adjoint(); } } private: Eigen::SelfAdjointEigenSolver _eig; Eigen::JacobiSVD _svd; // only used if Eigendecomposition fails, should be very rare Eigen::VectorXd _tmp; }; class CholeskySolver : public LeastSquares::Impl { public: explicit CholeskySolver(int dimension) : Impl(dimension, 0.0), _ldlt(dimension) {} virtual void factor() { ensure(LOWER_FISHER_MATRIX | RHS_VECTOR); _ldlt.compute(fisher); } virtual void updateRank() {} virtual void updateDiagnostic() { if (whichDiagnostic != LeastSquares::NORMAL_CHOLESKY) { throw LSST_EXCEPT(
    235 cd48db28 - pex::exceptions::LogicErrorException,
    ? ---------
    235 21597d88 + pex::exceptions::LogicError,
    "Can only compute NORMAL_CHOLESKY diagnostic from NORMAL_CHOLESKY factorization." ); } diagnostic.asEigen() = _ldlt.vectorD(); } virtual void updateSolution() { solution.asEigen() = _ldlt.solve(rhs); } virtual void updateCovariance() { ndarray::EigenView cov(covariance); cov.setIdentity(); cov = _ldlt.solve(cov); } private: Eigen::LDLT _ldlt; }; class SvdSolver : public LeastSquares::Impl { public: explicit SvdSolver(int dimension) : Impl(dimension), _svd(), _tmp(dimension) {} virtual void factor() { if (!(state & DESIGN_AND_DATA)) { throw LSST_EXCEPT(
    262 31d17169 - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    262 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Cannot initialize DIRECT_SVD solver with normal equations." ); } _svd.compute(design, Eigen::ComputeThinU | Eigen::ComputeThinV); setRank(_svd.singularValues()); log.debug<5>("Using direct SVD method; dimension=%d, rank=%d", dimension, rank); } virtual void updateRank() { setRank(_svd.singularValues()); } virtual void updateDiagnostic() { switch (whichDiagnostic) { case LeastSquares::NORMAL_EIGENSYSTEM: diagnostic.asEigen() = _svd.singularValues().array().square(); break; case LeastSquares::NORMAL_CHOLESKY: throw LSST_EXCEPT(
    280 cd48db28 - pex::exceptions::LogicErrorException,
    ? ---------
    280 21597d88 + pex::exceptions::LogicError,
    "Can only compute NORMAL_CHOLESKY diagnostic from DIRECT_SVD factorization." ); case LeastSquares::DIRECT_SVD: diagnostic.asEigen() = _svd.singularValues(); break; } } virtual void updateSolution() { if (rank == 0) { solution.asEigen().setZero(); return; } _tmp.head(rank) = _svd.matrixU().leftCols(rank).adjoint() * data; _tmp.head(rank).array() /= _svd.singularValues().head(rank).array(); solution.asEigen() = _svd.matrixV().leftCols(rank) * _tmp.head(rank); } virtual void updateCovariance() { if (rank == 0) { covariance.asEigen().setZero(); return; } covariance.asEigen() = _svd.matrixV().leftCols(rank) * _svd.singularValues().head(rank).array().inverse().square().matrix().asDiagonal() * _svd.matrixV().leftCols(rank).adjoint(); } private: Eigen::JacobiSVD _svd; Eigen::VectorXd _tmp; }; } // anonymous void LeastSquares::setThreshold(double threshold) { _impl->threshold = threshold; _impl->state &= ~Impl::SOLUTION_ARRAY; _impl->state &= ~Impl::COVARIANCE_ARRAY; _impl->updateRank(); } double LeastSquares::getThreshold() const { return _impl->threshold; } ndarray::Array LeastSquares::getSolution() { _impl->ensure(Impl::SOLUTION_ARRAY); return _impl->solution; } ndarray::Array LeastSquares::getCovariance() { _impl->ensure(Impl::COVARIANCE_ARRAY); return _impl->covariance; } ndarray::Array LeastSquares::getFisherMatrix() { _impl->ensure(Impl::FULL_FISHER_MATRIX); // Wrap the Eigen::MatrixXd in an ndarray::Array, using _impl as the reference-counted owner. // Doesn't matter if we swap strides, because it's symmetric. return ndarray::external( _impl->fisher.data(), ndarray::makeVector(_impl->dimension, _impl->dimension), ndarray::makeVector(_impl->dimension, 1), _impl ); } ndarray::Array LeastSquares::getDiagnostic(Factorization factorization) { if (_impl->whichDiagnostic != factorization) { _impl->state &= ~Impl::DIAGNOSTIC_ARRAY; _impl->whichDiagnostic = factorization; } _impl->ensure(Impl::DIAGNOSTIC_ARRAY); return _impl->diagnostic; } int LeastSquares::getDimension() const { return _impl->dimension; } int LeastSquares::getRank() const { return _impl->rank; } LeastSquares::Factorization LeastSquares::getFactorization() const { return _impl->factorization; } LeastSquares::LeastSquares(Factorization factorization, int dimension) { switch (factorization) { case NORMAL_EIGENSYSTEM: _impl = boost::make_shared(dimension); break; case NORMAL_CHOLESKY: _impl = boost::make_shared(dimension); break; case DIRECT_SVD: _impl = boost::make_shared(dimension); break; } _impl->factorization = factorization; } LeastSquares::~LeastSquares() {} Eigen::MatrixXd & LeastSquares::_getDesignMatrix() { return _impl->design; } Eigen::VectorXd & LeastSquares::_getDataVector() { return _impl->data; } Eigen::MatrixXd & LeastSquares::_getFisherMatrix() { return _impl->fisher; } Eigen::VectorXd & LeastSquares::_getRhsVector() { return _impl->rhs; } void LeastSquares::_factor(bool haveNormalEquations) { if (haveNormalEquations) { if (_getFisherMatrix().rows() != _impl->dimension) { throw LSST_EXCEPT(
    390 982404ec - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    390 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Number of rows of Fisher matrix (%d) does not match" " dimension of LeastSquares solver.") % _getFisherMatrix().rows() % _impl->dimension).str() ); } if (_getFisherMatrix().cols() != _impl->dimension) { throw LSST_EXCEPT(
    398 982404ec - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    398 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Number of columns of Fisher matrix (%d) does not match" " dimension of LeastSquares solver.") % _getFisherMatrix().cols() % _impl->dimension).str() ); } if (_getRhsVector().size() != _impl->dimension) { throw LSST_EXCEPT(
    406 982404ec - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    406 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Number of elements in RHS vector (%d) does not match" " dimension of LeastSquares solver.") % _getRhsVector().size() % _impl->dimension).str() ); } _impl->state = Impl::RHS_VECTOR | Impl::FULL_FISHER_MATRIX | Impl::LOWER_FISHER_MATRIX; } else { if (_getDesignMatrix().cols() != _impl->dimension) { throw LSST_EXCEPT(
    416 982404ec - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    416 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Number of columns of design matrix does not match dimension of LeastSquares solver." ); } if (_getDesignMatrix().rows() != _getDataVector().size()) { throw LSST_EXCEPT(
    422 982404ec - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    422 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Number of rows of design matrix (%d) does not match number of " "data points (%d)") % _getDesignMatrix().rows() % _getDataVector().size() ).str() ); } if (_getDesignMatrix().cols() > _getDataVector().size()) { throw LSST_EXCEPT(
    430 d0bbcfe2 - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    430 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Number of columns of design matrix (%d) must be smaller than number of " "data points (%d)") % _getDesignMatrix().cols() % _getDataVector().size() ).str() ); } _impl->state = Impl::DESIGN_AND_DATA; } _impl->factor(); } }}} // namespace lsst::afw::math

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    982404ec

    commit 982404ec5956dd7bf0fcd623d778f2b5e8f78b85
    Author: Jim Bosch 
    Date:   Fri Mar 30 18:31:18 2012 -0400
    
        implemented Eigensystem-based LeastSquares solver; removed computeChiSq from API (not compatible with initialization by normal equations)
    

    d0bbcfe2

    commit d0bbcfe2745ddd4f7dd1c4758d71e2a80ccdd676
    Author: Jim Bosch 
    Date:   Mon Apr 2 01:40:29 2012 -0400
    
        Unit tests and lots of fixes for LeastSquares
    

    cd48db28

    commit cd48db2899f35fbf9f79bff28e380382940c3538
    Author: Jim Bosch 
    Date:   Mon Apr 16 14:17:56 2012 -0400
    
        replace LeastSquares::getCondition() with getDiagnostic as discussed in code review for #1997
    

    31d17169

    commit 31d17169e632066581c28fec0fdd32542deb241f
    Author: Jim Bosch 
    Date:   Mon Apr 2 14:12:57 2012 -0400
    
        added and tested lazy evaluation in LeastSquares; renamed member functions
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/testLeastSquares.py

    Diff:

    1 d0bbcfe2 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for math.LeastSquares Run with: ./testLeastSquares.py or python >>> import testLeastSquares; testLeastSquares.run() """ import unittest import numpy import sys import lsst.utils.tests as utilsTests import lsst.pex.exceptions import lsst.pex.logging from lsst.afw.math import LeastSquares numpy.random.seed(500) lsst.pex.logging.getDefaultLog().setThresholdFor("afw.math.LeastSquares", -10) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class LeastSquaresTestCase(unittest.TestCase): def assertClose(self, a, b, rtol=1E-5, atol=1E-8): self.assert_(numpy.allclose(a, b, rtol=rtol, atol=atol), "\n%s\n!=\n%s" % (a, b)) def assertNotClose(self, a, b, rtol=1E-5, atol=1E-8): self.assert_(not numpy.allclose(a, b, rtol=rtol, atol=atol), "\n%s\n==\n%s" % (a, b)) def check(self, solver, solution, rank, fisher, cov, sv): self.assertEqual(solver.getRank(), rank) self.assertEqual(solver.getDimension(), solution.shape[0]) self.assertClose(solver.getSolution(), solution) self.assertClose(solver.getFisherMatrix(), fisher) self.assertClose(solver.getCovariance(), cov) if solver.getFactorization() != LeastSquares.NORMAL_CHOLESKY: self.assertClose(solver.getDiagnostic(LeastSquares.NORMAL_EIGENSYSTEM), sv**2) diagnostic = solver.getDiagnostic(solver.getFactorization()) rcond = diagnostic[0] * solver.getThreshold() self.assert_(diagnostic[rank-1] > rcond) if rank < solver.getDimension(): self.assert_(diagnostic[rank] < rcond) else: self.assertClose(numpy.multiply.reduce(solver.getDiagnostic(LeastSquares.NORMAL_CHOLESKY)), numpy.multiply.reduce(sv**2)) def testFullRank(self): dimension = 10 nData = 500 design = numpy.random.randn(dimension, nData).transpose() data = numpy.random.randn(nData) fisher = numpy.dot(design.transpose(), design) rhs = numpy.dot(design.transpose(), data) solution, residues, rank, sv = numpy.linalg.lstsq(design, data) cov = numpy.linalg.inv(fisher) s_svd = LeastSquares.fromDesignMatrix(design, data, LeastSquares.DIRECT_SVD) s_design_eigen = LeastSquares.fromDesignMatrix(design, data, LeastSquares.NORMAL_EIGENSYSTEM) s_design_cholesky = LeastSquares.fromDesignMatrix(design, data, LeastSquares.NORMAL_CHOLESKY) s_normal_eigen = LeastSquares.fromNormalEquations(fisher, rhs, LeastSquares.NORMAL_EIGENSYSTEM) s_normal_cholesky = LeastSquares.fromNormalEquations(fisher, rhs, LeastSquares.NORMAL_CHOLESKY) self.check(s_svd, solution, rank, fisher, cov, sv) self.check(s_design_eigen, solution, rank, fisher, cov, sv) self.check(s_design_cholesky, solution, rank, fisher, cov, sv) self.check(s_normal_eigen, solution, rank, fisher, cov, sv) self.check(s_normal_cholesky, solution, rank, fisher, cov, sv) # test updating solver in-place with the same kind of inputs design = numpy.random.randn(dimension, nData).transpose() data = numpy.random.randn(nData) fisher = numpy.dot(design.transpose(), design) rhs = numpy.dot(design.transpose(), data) solution, residues, rank, sv = numpy.linalg.lstsq(design, data) cov = numpy.linalg.inv(fisher) s_svd.setDesignMatrix(design, data) s_design_eigen.setDesignMatrix(design, data) s_design_cholesky.setDesignMatrix(design, data) s_normal_eigen.setNormalEquations(fisher, rhs) s_normal_cholesky.setNormalEquations(fisher, rhs) self.check(s_svd, solution, rank, fisher, cov, sv) self.check(s_design_eigen, solution, rank, fisher, cov, sv) self.check(s_design_cholesky, solution, rank, fisher, cov, sv) self.check(s_normal_eigen, solution, rank, fisher, cov, sv) self.check(s_normal_cholesky, solution, rank, fisher, cov, sv) # test updating solver in-place with the opposite kind of inputs design = numpy.random.randn(dimension, nData).transpose() data = numpy.random.randn(nData) fisher = numpy.dot(design.transpose(), design) rhs = numpy.dot(design.transpose(), data) solution, residues, rank, sv = numpy.linalg.lstsq(design, data) cov = numpy.linalg.inv(fisher) s_normal_eigen.setDesignMatrix(design, data) s_normal_cholesky.setDesignMatrix(design, data) s_design_eigen.setNormalEquations(fisher, rhs) s_design_cholesky.setNormalEquations(fisher, rhs) self.check(s_design_eigen, solution, rank, fisher, cov, sv) self.check(s_design_cholesky, solution, rank, fisher, cov, sv) self.check(s_normal_eigen, solution, rank, fisher, cov, sv) self.check(s_normal_cholesky, solution, rank, fisher, cov, sv) def testSingular(self): dimension = 10 nData = 100 svIn = (numpy.random.randn(dimension) + 1.0)**2 + 1.0 svIn = numpy.sort(svIn)[::-1] svIn[-1] = 0.0 svIn[-2] = svIn[0] * 1E-4 # Just use SVD to get a pair of orthogonal matrices; we'll use our own singular values # so we can control the stability of the matrix. u, s, vt = numpy.linalg.svd(numpy.random.randn(dimension, nData), full_matrices=False) design = numpy.dot(u * svIn, vt).transpose() data = numpy.random.randn(nData) fisher = numpy.dot(design.transpose(), design) rhs = numpy.dot(design.transpose(), data) threshold = 10 * sys.float_info.epsilon solution, residues, rank, sv = numpy.linalg.lstsq(design, data, rcond=threshold) self.assertClose(svIn, sv) cov = numpy.linalg.pinv(fisher, rcond=threshold) s_svd = LeastSquares.fromDesignMatrix(design, data, LeastSquares.DIRECT_SVD) s_design_eigen = LeastSquares.fromDesignMatrix(design, data, LeastSquares.NORMAL_EIGENSYSTEM) s_normal_eigen = LeastSquares.fromNormalEquations(fisher, rhs, LeastSquares.NORMAL_EIGENSYSTEM) self.check(s_svd, solution, rank, fisher, cov, sv) self.check(s_design_eigen, solution, rank, fisher, cov, sv) self.check(s_normal_eigen, solution, rank, fisher, cov, sv) s_svd.setThreshold(1E-3) s_design_eigen.setThreshold(1E-6) s_normal_eigen.setThreshold(1E-6) self.assertEqual(s_svd.getRank(), dimension - 2) self.assertEqual(s_design_eigen.getRank(), dimension - 2) self.assertEqual(s_normal_eigen.getRank(), dimension - 2) # Just check that solutions are different from before, but consistent with each other; # I can't figure out how get numpy.lstsq to deal with the thresholds appropriately to # test against that. self.assertNotClose(s_svd.getSolution(), solution) self.assertNotClose(s_design_eigen.getSolution(), solution) self.assertNotClose(s_normal_eigen.getSolution(), solution) self.assertClose(s_svd.getSolution(), s_design_eigen.getSolution()) self.assertClose(s_svd.getSolution(), s_normal_eigen.getSolution()) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(LeastSquaresTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d0bbcfe2

    commit d0bbcfe2745ddd4f7dd1c4758d71e2a80ccdd676
    Author: Jim Bosch 
    Date:   Mon Apr 2 01:40:29 2012 -0400
    
        Unit tests and lots of fixes for LeastSquares
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    python/lsst/afw/display/Rgb.h

    Diff:

    1 f49676d7 - /**
    2 f49676d7 - * \file
    3 f49676d7 - *
    4 f49676d7 - * Support RGB and grey-scale images
    5 f49676d7 - */
    #if !defined(LSST_AFW_DISPLAY_RGB_H) #define LSST_AFW_DISPLAY_RGB_H 1 namespace lsst { namespace afw { namespace display { template void replaceSaturatedPixels(ImageT & rim, //< R image (e.g. i) ImageT & gim, //< G image (e.g. r) ImageT & bim, //< B image (e.g. g) int borderWidth = 2, //< width of border used to estimate colour of saturated regions float saturatedPixelValue = 65535 //< the brightness of a saturated pixel, once fixed );
    20 f49676d7 -
    21 f49676d7 - /**
    22 f49676d7 - * Calculate an IRAF/ds9-style zscaling.
    23 f49676d7 - *
    24 f49676d7 - * To quote Frank Valdes (http://iraf.net/forum/viewtopic.php?showtopic=134139)
    25 f49676d7 - *
    26 f49676d7 - ZSCALE ALGORITHM
    27 f49676d7 -
    28 f49676d7 - The zscale algorithm is designed to display the image values near
    29 f49676d7 - the median image value without the time consuming process of
    30 f49676d7 - computing a full image histogram. This is particularly useful for
    31 f49676d7 - astronomical images which generally have a very peaked histogram
    32 f49676d7 - corresponding to the background sky in direct imaging or the
    33 f49676d7 - continuum in a two dimensional spectrum.
    34 f49676d7 -
    35 f49676d7 - The sample of pixels, specified by values greater than zero in the
    36 f49676d7 - sample mask zmask or by an image section, is selected up to a
    37 f49676d7 - maximum of nsample pixels. If a bad pixel mask is specified by the
    38 f49676d7 - bpmask parameter then any pixels with mask values which are greater
    39 f49676d7 - than zero are not counted in the sample. Only the first pixels up
    40 f49676d7 - to the limit are selected where the order is by line beginning from
    41 f49676d7 - the first line. If no mask is specified then a grid of pixels with
    42 f49676d7 - even spacing along lines and columns that make up a number less
    43 f49676d7 - than or equal to the maximum sample size is used.
    44 f49676d7 -
    45 f49676d7 - If a contrast of zero is specified (or the zrange flag is used and
    46 f49676d7 - the image does not have a valid minimum/maximum value) then the
    47 f49676d7 - minimum and maximum of the sample is used for the intensity mapping
    48 f49676d7 - range.
    49 f49676d7 -
    50 f49676d7 - If the contrast is not zero the sample pixels are ranked in
    51 f49676d7 - brightness to form the function I(i) where i is the rank of the
    52 f49676d7 - pixel and I is its value. Generally the midpoint of this function
    53 f49676d7 - (the median) is very near the peak of the image histogram and there
    54 f49676d7 - is a well defined slope about the midpoint which is related to the
    55 f49676d7 - width of the histogram. At the ends of the I(i) function there are
    56 f49676d7 - a few very bright and dark pixels due to objects and defects in the
    57 f49676d7 - field. To determine the slope a linear function is fit with
    58 f49676d7 - iterative rejection;
    59 f49676d7 -
    60 f49676d7 -
    61 f49676d7 - I(i) = intercept + slope * (i - midpoint)
    62 f49676d7 -
    63 f49676d7 -
    64 f49676d7 - If more than half of the points are rejected then there is no well
    65 f49676d7 - defined slope and the full range of the sample defines z1 and z2.
    66 f49676d7 - Otherwise the endpoints of the linear function are used (provided
    67 f49676d7 - they are within the original range of the sample):
    68 f49676d7 -
    69 f49676d7 -
    70 f49676d7 - z1 = I(midpoint) + (slope / contrast) * (1 - midpoint)
    71 f49676d7 - z2 = I(midpoint) + (slope / contrast) * (npoints - midpoint)
    72 f49676d7 -
    73 f49676d7 -
    74 f49676d7 - As can be seen, the parameter contrast may be used to adjust the
    75 f49676d7 - contrast produced by this algorithm.
    76 f49676d7 - *
    77 f49676d7 - */
    78 f49676d7 - template
    79 f49676d7 - std::pair
    80 f49676d7 - getZScale(image::Image const& image, ///< The image we wish to stretch
    81 f49676d7 - int const nSamples=1000, ///< Number of samples to use
    82 f49676d7 - double const contrast=0.25 ///< Stretch parameter; see description
    83 f49676d7 - );
    }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f49676d7

    commit f49676d7f1348f9de8ca21ee633e0c25473251ae
    Author: Robert Lupton the Good 
    Date:   Sun Apr 19 10:50:17 2015 -0300
    
        Implemented Linear and ZScale transformations, HSC-1206
        
        Linear was already available with Q=0, but this way is clearer; the default is to use min/max limits.
        
        I also added AsinhZScaleMapping which uses the zscale code to set the stretch.
        
        I did not port the log mappings, as the C++ is not really something I'd like to see in the long-term stack (e.g. reinterpret_casts between ints and doubles).
        It would be easy to add a LogMapper in pure python, and if this is needed please open a new issue.
        
        The ZScale code comes from Mineo-san's fitsthumb, but doesn't give quite the same upper limit as ds9.  I'm not sure where the discrepancy is, but I don't think it matters.
    

    Commits in /Users/nate/repos_lsst/afw/

    Return to list

    src/formatters/DecoratedImageFormatter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    /** @file
                     * @brief Implementation of DecoratedImageFormatter class
                     *
                     * @author $Author: ktlim $
                     * @version $Revision: 2151 $
                     * @date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * @ingroup afw
                     */
                    
                    #ifndef __GNUC__
                    #  define __attribute__(x) /*NOTHING*/
                    #endif
                    static char const* SVNid __attribute__((unused)) =
                        "$Id$";
                    
                    #include "boost/scoped_ptr.hpp"
                    #include "boost/serialization/shared_ptr.hpp"
                    #include "boost/serialization/binary_object.hpp"
                    #include "boost/serialization/nvp.hpp"
                    #include 
                    #include 
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/formatters/DecoratedImageFormatter.h"
                    #include "lsst/afw/image/Image.h"
                    
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.DecoratedImageFormatter", level, s);
                    }
                    
                    using boost::serialization::make_nvp;
                    using lsst::daf::base::Persistable;
                    using lsst::daf::persistence::BoostStorage;
                    using lsst::daf::persistence::XmlStorage;
                    using lsst::daf::persistence::FitsStorage;
                    using lsst::daf::persistence::Storage;
                    using lsst::afw::image::DecoratedImage;
                    
                    namespace lsst {
                    namespace afw {
                    namespace formatters {
                    
                    template 
                    class DecoratedImageFormatterTraits {
                    public:
                        static std::string name();
                    };
                    
                    template<> std::string DecoratedImageFormatterTraits::name() {
                        static std::string name = "DecoratedImageU";
                        return name;
                    }
                    template<> std::string DecoratedImageFormatterTraits::name() {
                        static std::string name = "DecoratedImageI";
                        return name;
                    }
                    template<> std::string DecoratedImageFormatterTraits::name() {
                        static std::string name = "DecoratedImageF";
                        return name;
                    }
                    template<> std::string DecoratedImageFormatterTraits::name() {
                        static std::string name = "DecoratedImageD";
                        return name;
                    }
                    template<> std::string DecoratedImageFormatterTraits::name() {
                        static std::string name = "DecoratedImageL";
                        return name;
                    }
                    
                    template 
                    lsst::daf::persistence::FormatterRegistration DecoratedImageFormatter::registration(
                        DecoratedImageFormatterTraits::name(),
                        typeid(DecoratedImage),
                        createInstance);
                    
                    template 
                    DecoratedImageFormatter::DecoratedImageFormatter(
                            lsst::pex::policy::Policy::Ptr
                                                                                 )
                        : lsst::daf::persistence::Formatter(typeid(this))
                    {
                    }
                    
                    template 
                    DecoratedImageFormatter::~DecoratedImageFormatter(void) {
                    }
                    
                    template 
                    void DecoratedImageFormatter::write(
                            Persistable const* persistable,
                            Storage::Ptr storage,
                            lsst::daf::base::PropertySet::Ptr
                                                                    )
                    {
                        execTrace("DecoratedImageFormatter write start");
                        DecoratedImage const* ip = dynamic_cast const*>(persistable);
                        if (ip == 0) {
    
    130 7c76c508 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Persisting non-DecoratedImage");
    ? ---------
    130 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Persisting non-DecoratedImage");
    } if (typeid(*storage) == typeid(BoostStorage)) { execTrace("DecoratedImageFormatter write BoostStorage"); BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & *ip; execTrace("DecoratedImageFormatter write end"); return; } else if (typeid(*storage) == typeid(XmlStorage)) { execTrace("DecoratedImageFormatter write XmlStorage"); XmlStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & make_nvp("img", *ip); execTrace("DecoratedImageFormatter write end"); return; } else if (typeid(*storage) == typeid(FitsStorage)) { execTrace("DecoratedImageFormatter write FitsStorage"); FitsStorage* fits = dynamic_cast(storage.get()); typedef DecoratedImage DecoratedImage; ip->writeFits(fits->getPath()); // \todo Do something with these fields? // int _X0; // int _Y0; execTrace("DecoratedImageFormatter write end"); return; }
    156 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    156 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Unrecognized Storage for DecoratedImage"); } template Persistable* DecoratedImageFormatter::read( Storage::Ptr storage, lsst::daf::base::PropertySet::Ptr ) { execTrace("DecoratedImageFormatter read start"); if (typeid(*storage) == typeid(BoostStorage)) { execTrace("DecoratedImageFormatter read BoostStorage"); BoostStorage* boost = dynamic_cast(storage.get()); DecoratedImage* ip = new DecoratedImage; boost->getIArchive() & *ip; execTrace("DecoratedImageFormatter read end"); return ip; } else if (typeid(*storage) == typeid(XmlStorage)) { execTrace("DecoratedImageFormatter read XmlStorage"); XmlStorage* boost = dynamic_cast(storage.get()); DecoratedImage* ip = new DecoratedImage; boost->getIArchive() & make_nvp("img", *ip); execTrace("DecoratedImageFormatter read end"); return ip; } else if(typeid(*storage) == typeid(FitsStorage)) { execTrace("DecoratedImageFormatter read FitsStorage"); FitsStorage* fits = dynamic_cast(storage.get()); DecoratedImage* ip = new DecoratedImage(fits->getPath(), fits->getHdu()); // \todo Do something with these fields? // int _X0; // int _Y0; execTrace("DecoratedImageFormatter read end"); return ip; }
    193 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    193 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Unrecognized Storage for DecoratedImage"); } template void DecoratedImageFormatter::update( lsst::daf::base::Persistable*, lsst::daf::persistence::Storage::Ptr, lsst::daf::base::PropertySet::Ptr ) {
    204 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    204 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Unexpected call to update for DecoratedImage"); } template template void DecoratedImageFormatter::delegateSerialize( Archive&, int const, Persistable* persistable ) { execTrace("DecoratedImageFormatter delegateSerialize start"); DecoratedImage* ip = dynamic_cast*>(persistable); if (ip == 0) {
    218 7c76c508 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Serializing non-DecoratedImage");
    ? ---------
    218 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Serializing non-DecoratedImage");
    }
    220 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    220 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "DecoratedImage serialization not yet implemented"); } template lsst::daf::persistence::Formatter::Ptr DecoratedImageFormatter::createInstance( lsst::pex::policy::Policy::Ptr policy ) { return lsst::daf::persistence::Formatter::Ptr(new DecoratedImageFormatter(policy)); } #define InstantiateFormatter(ImagePixelT) \ template class DecoratedImageFormatter; \ template void DecoratedImageFormatter::delegateSerialize(boost::archive::text_oarchive&, int const, Persistable*); \ template void DecoratedImageFormatter::delegateSerialize(boost::archive::text_iarchive&, int const, Persistable*); \ template void DecoratedImageFormatter::delegateSerialize(boost::archive::binary_oarchive&, int const, Persistable*); \ template void DecoratedImageFormatter::delegateSerialize(boost::archive::binary_iarchive&, int const, Persistable*); InstantiateFormatter(boost::uint16_t); InstantiateFormatter(int); InstantiateFormatter(float); InstantiateFormatter(double); InstantiateFormatter(boost::uint64_t); #undef InstantiateFormatter }}} // namespace lsst::afw::formatters

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7a6ea5ce

    commit 7a6ea5ce178494cb61090089847aacd809082e36
    Author: bick 
    Date:   Wed Jan 6 20:50:58 2010 +0000
    
        #1113 sundry style corrections on afw.
    

    7c76c508

    commit 7c76c5081ac37893b23bcf179b4a22ea1c00337e
    Author: ktlim 
    Date:   Thu Mar 12 23:38:27 2009 +0000
    
        Add DecoratedImageFormatter.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/table/Match.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #ifndef LSST_AFW_TABLE_MATCH_H
                    #define LSST_AFW_TABLE_MATCH_H
                    
                    #include 
                    
    
    30 3252a40a - #include "lsst/pex/config.h"
    #include "lsst/afw/table/fwd.h" #include "lsst/afw/table/BaseRecord.h" #include "lsst/afw/table/Simple.h" #include "lsst/afw/table/Source.h" #include "lsst/afw/table/Catalog.h" #include "lsst/afw/geom/Angle.h" namespace lsst { namespace afw { namespace table {
    40 b7624bb3 - /**
    41 3252a40a - * @class MatchControl
    42 3252a40a - * @brief Pass parameters to algorithms that match list of sources
    43 3252a40a - */
    44 3252a40a - class MatchControl {
    45 3252a40a - public:
    46 3252a40a - MatchControl()
    47 3252a40a - : findOnlyClosest(true),
    48 3252a40a - symmetricMatch(true),
    49 3252a40a - includeMismatches(false)
    50 3252a40a - { }
    51 3252a40a - LSST_CONTROL_FIELD(findOnlyClosest, bool, "Return only the closest match if more than one is found " \
    52 3252a40a - "(default: true)");
    53 3252a40a - LSST_CONTROL_FIELD(symmetricMatch, bool, "Produce symmetric matches (default: true):\n" \
    54 3252a40a - "i.e. if (s1, s2, d) is reported, then so is (s2, s1, d)");
    55 3252a40a - LSST_CONTROL_FIELD(includeMismatches, bool, "Include failed matches (i.e. one 'match' is NULL) " \
    56 3252a40a - "(default: false)");
    57 3252a40a - };
    58 3252a40a -
    /** * @brief Lightweight representation of a geometric match between two records. * * This is a template so it can hold derived record classes without a lot of * casting and properly use Angle for the distance when we do spherical coordinate * matches. */ template struct Match { PTR(Record1) first; PTR(Record2) second; double distance; // may be pixels or radians Match() : first(), second(), distance(0.0) {} Match(PTR(Record1) const & r1, PTR(Record2) const & r2, double dist) : first(r1), second(r2), distance(dist) {} template Match(Match const & other) : first(other.first), second(other.second), distance(other.distance) {} }; typedef Match SimpleMatch; typedef Match ReferenceMatch; typedef Match SourceMatch; typedef std::vector SimpleMatchVector; typedef std::vector ReferenceMatchVector; typedef std::vector SourceMatchVector; /** * Compute all tuples (s1,s2,d) where s1 belings to @a cat1, s2 belongs to @a cat2 and * d, the distance between s1 and s2, in pixels, is at most @a radius. If cat1 and
    93 3252a40a - * cat2 are identical, then this call is equivalent to @c matchXy(cat1,radius).
    73 4c363d4e + * cat2 are identical, then this call is equivalent to @c matchXy(cat1,radius,true).
    ? +++++ * The match is performed in pixel space (2d cartesian).
    95 3252a40a - */
    96 3252a40a - SourceMatchVector matchXy(
    97 3252a40a - SourceCatalog const &cat1, ///< first catalog
    98 3252a40a - SourceCatalog const &cat2, ///< second catalog
    99 3252a40a - double radius, ///< match radius (pixels)
    100 3252a40a - MatchControl const& mc=MatchControl() ///< how to do the matching (obeys MatchControl::findOnlyClosest)
    101 3252a40a - );
    102 3252a40a -
    103 3252a40a - /**
    104 3252a40a - * Compute all tuples (s1,s2,d) where s1 != s2, s1 and s2 both belong to @a cat,
    105 3252a40a - * and d, the distance between s1 and s2, in pixels, is at most @a radius. The
    106 3252a40a - * match is performed in pixel space (2d cartesian).
    107 3252a40a - */
    108 3252a40a - SourceMatchVector matchXy(
    109 3252a40a - SourceCatalog const &cat, ///< the catalog to self-match
    110 3252a40a - double radius, ///< match radius (pixels)
    111 3252a40a - MatchControl const& mc=MatchControl() ///< how to do the matching (obeys MatchControl::symmetricMatch)
    112 3252a40a - );
    113 3252a40a -
    114 3252a40a - /**
    115 3252a40a - * Compute all tuples (s1,s2,d) where s1 belings to @a cat1, s2 belongs to @a cat2 and
    116 3252a40a - * d, the distance between s1 and s2, in pixels, is at most @a radius. If cat1 and
    117 3252a40a - * cat2 are identical, then this call is equivalent to @c matchXy(cat1,radius).
    118 3252a40a - * The match is performed in pixel space (2d cartesian).
    119 3252a40a - *
    120 3252a40a - * @deprecated Please use the matchXy(..., MatchControl const&) API
    * * @param[in] cat1 first catalog * @param[in] cat2 second catalog * @param[in] radius match radius (pixels) * @param[in] closest if true then just return the closest match */ SourceMatchVector matchXy(
    82 4c363d4e + SourceCatalog const &cat1, SourceCatalog const &cat2,
    83 4c363d4e + double radius, bool closest=true
    128 3252a40a - SourceCatalog const &cat1,
    129 3252a40a - SourceCatalog const &cat2,
    130 3252a40a - double radius,
    131 3252a40a - bool closest
    ); /** * Compute all tuples (s1,s2,d) where s1 != s2, s1 and s2 both belong to @a cat, * and d, the distance between s1 and s2, in pixels, is at most @a radius. The * match is performed in pixel space (2d cartesian). *
    139 3252a40a - * @deprecated Please use the matchXy(..., MatchControl const&) API
    140 3252a40a - *
    * @param[in] cat the catalog to self-match * @param[in] radius match radius (pixels) * @param[in] symmetric if cat to @c true symmetric matches are produced: i.e. * if (s1, s2, d) is reported, then so is (s2, s1, d). */
    146 3252a40a - SourceMatchVector matchXy(SourceCatalog const &cat, double radius, bool symmetric);
    96 4c363d4e + SourceMatchVector matchXy(SourceCatalog const &cat, double radius, bool symmetric = true);
    ? +++++++ #ifndef SWIG // swig will be confused by the nested names below; repeated with typedefs in match.i
    150 3252a40a - /************************************************************************************************************/
    /** * Compute all tuples (s1,s2,d) where s1 belings to @a cat1, s2 belongs to @a cat2 and * d, the distance between s1 and s2, is at most @a radius. If cat1 and
    154 3252a40a - * cat2 are identical, then this call is equivalent to @c matchRaDec(cat1,radius).
    103 4c363d4e + * cat2 are identical, then this call is equivalent to @c matchRaDec(cat1,radius,true).
    ? +++++ * The match is performed in ra, dec space.
    156 4900a14b - *
    157 3252a40a - * This is instantiated for Simple-Simple, Simple-Source, and Source-Source catalog combinations.
    158 3252a40a - */
    159 3252a40a - template
    160 3252a40a - std::vector< Match< typename Cat1::Record, typename Cat2::Record> > matchRaDec(
    161 3252a40a - Cat1 const & cat1, ///< first catalog
    162 3252a40a - Cat2 const & cat2, ///< second catalog
    163 3252a40a - Angle radius, ///< match radius
    164 3252a40a - MatchControl const& mc=MatchControl() ///< how to do the matching (obeys MatchControl::findOnlyClosest)
    165 3252a40a - );
    166 3252a40a -
    167 3252a40a - /*
    168 3252a40a - * Compute all tuples (s1,s2,d) where s1 != s2, s1 and s2 both belong to @a cat,
    169 3252a40a - * and d, the distance between s1 and s2, is at most @a radius. The
    170 3252a40a - * match is performed in ra, dec space.
    171 3252a40a - *
    172 3252a40a - * This is instantiated for Simple and Source catalogs.
    173 3252a40a - */
    174 3252a40a - template
    175 3252a40a - std::vector< Match< typename Cat::Record, typename Cat::Record> > matchRaDec(
    176 3252a40a - Cat const & cat, ///< the catalog to self-match
    177 3252a40a - Angle radius, ///< match radius
    178 3252a40a - MatchControl const& mc=MatchControl() ///< how to do the matching (obeys MatchControl::symmetricMatch)
    179 3252a40a - );
    180 3252a40a -
    181 3252a40a - /************************************************************************************************************/
    182 3252a40a - /**
    183 3252a40a - * Compute all tuples (s1,s2,d) where s1 belings to @a cat1, s2 belongs to @a cat2 and
    184 3252a40a - * d, the distance between s1 and s2, is at most @a radius. If cat1 and
    185 3252a40a - * cat2 are identical, then this call is equivalent to @c matchRaDec(cat1,radius).
    186 3252a40a - * The match is performed in ra, dec space.
    187 3252a40a - *
    188 3252a40a - * @deprecated. Use the matchRaDec(..., MatchControl) version
    * * @param[in] cat1 first catalog * @param[in] cat2 second catalog * @param[in] radius match radius * @param[in] closest if true then just return the closest match * * This is instantiated for Simple-Simple, Simple-Source, and Source-Source catalog combinations. */ template std::vector< Match< typename Cat1::Record, typename Cat2::Record> > matchRaDec( Cat1 const & cat1, Cat2 const & cat2,
    201 3252a40a - Angle radius, bool closest
    117 4c363d4e + Angle radius, bool closest = true
    ? +++++++ ); /* * Compute all tuples (s1,s2,d) where s1 != s2, s1 and s2 both belong to @a cat, * and d, the distance between s1 and s2, is at most @a radius. The * match is performed in ra, dec space.
    208 4900a14b - *
    209 3252a40a - * @deprecated. Use the matchRaDec(..., MatchControl) version
    * * @param[in] cat the catalog to self-match * @param[in] radius match radius * @param[in] symmetric if cat to @c true symmetric matches are produced: i.e. * if (s1, s2, d) is reported, then so is (s2, s1, d). * @param[in] key key used to extract the center * * This is instantiated for Simple and Source catalogs. */ template std::vector< Match< typename Cat::Record, typename Cat::Record> > matchRaDec( Cat const & cat, Angle radius,
    223 3252a40a - bool symmetric
    137 4c363d4e + bool symmetric = true
    ? +++++++ ); /** * @brief Return a table representation of a MatchVector that can be used to persist it. * * The schema of the returned object has "first" (RecordId), "second" (RecordID), and "distance" * (double) fields. * * @param[in] matches A std::vector of Match objects to convert to table form. */ template BaseCatalog packMatches(std::vector< Match > const & matches); /** * @brief Reconstruct a MatchVector from a BaseCatalog representation of the matches * and a pair of catalogs. * * @note The first and second catalog arguments must be sorted in ascending ID order on input; this will * allow us to use binary search algorithms to find the records referred to by the match * table. * * If an ID cannot be found in the given tables, that pointer will be set to null * in the returned match vector. * * @param[in] matches A normalized BaseCatalog representation, as produced by packMatches. * @param[in] cat1 A CatalogT containing the records used on the 'first' side of the match, * sorted by ascending ID. * @param[in] cat2 A CatalogT containing the records used on the 'second' side of the match, * sorted by ascending ID. May be the same as first. * * This is instantiated for Simple-Simple, Simple-Source, and Source-Source catalog combinations. */ template std::vector< Match< typename Cat1::Record, typename Cat2::Record> > unpackMatches(BaseCatalog const & matches, Cat1 const & cat1, Cat2 const & cat2); #endif // !SWIG }}} // namespace lsst::afw::table #endif // #ifndef LSST_AFW_TABLE_MATCH_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b7624bb3

    commit b7624bb36ee62931224ca8c29763d5364ae270ce
    Author: Jim Bosch 
    Date:   Tue Feb 21 19:48:03 2012 -0500
    
        reimplemented matching to work on arbitrary records rather than sources; need to modify source matching to delegate to it
    

    3252a40a

    commit 3252a40ad55222b882acf14d2f7cf0f3fe80f585
    Author: Robert Lupton the Good 
    Date:   Tue Jun 10 15:00:58 2014 -0400
    
        Added MatchControl and implemented it for matchXY and MatchRaDec
        
        N.b. added some missing tests on matchXY, although it is unchanged by this
        changeset
    

    4900a14b

    commit 4900a14b62b47e2d9d3c00e8db7e515f76700df5
    Author: Jim Bosch 
    Date:   Wed Feb 22 23:36:01 2012 -0500
    
        refactored SourceMatch to support matching arbitrary Record objects with explicit keys for coordinate and ID fields
    

    Commits in /Users/nate/repos_lsst/afw/

    4c363d4e

    commit 4c363d4e26003e91da9c9731de483546f68950f9
    Author: Jim Bosch 
    Date:   Fri Feb 24 16:50:39 2012 -0500
    
        more refactoring of matching; should finally be usable with meas_astrom (using SimpleRecord/Table for reference catalogs)
    

    Return to list

    ups/afw.cfg

    Diff:

                    # -*- python -*-
                    
                    import lsst.sconsUtils
                    
                    dependencies = {
                        "required": ["utils", "daf_persistence", "daf_base", "pex_exceptions", "pex_logging", "pex_config",
    
    7 722d827e - "pex_policy", "eigen", "fftw", "ndarray", "numpy", "xpa", "minuit2", "gsl", "cfitsio",
    ? -------
    7 f6a3296b + "pex_policy", "eigen", "fftw", "ndarray", "numpy", "minuit2", "gsl", "cfitsio",
    "wcslib", "boost_filesystem", "boost_regex", "boost_serialization"], "buildRequired": ["boost_test", "swig"], "optional": ["cuda_toolkit"], } config = lsst.sconsUtils.Configuration( __file__, headers=["lsst/afw/geom.h"], hasDoxygenInclude=False, hasSwigFiles=True, )

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    722d827e

    commit 722d827e7a69ea0e1bd3f7fe8f84832b52190053
    Author: Russell Owen 
    Date:   Mon Jan 9 16:04:55 2012 -0600
    
        Add pex_config as a dependency
    

    Commits in /Users/nate/repos_lsst/afw/

    f6a3296b

    commit f6a3296b0ba9d6efe64f8d0087a8d4323e2811a8
    Author: Russell Owen 
    Date:   Thu May 14 15:37:48 2015 -0700
    
        Remove vestiges of xpa
        
        Remove another instance of xpa
    

    Return to list

    tests/ticket2019.py

    Diff:

    1 b80fe1d3 + #!/usr/bin/env python2
    2 b80fe1d3 + from __future__ import absolute_import, division
    1 2d72fc25 - import os, sys, unittest
    ? ---------
    3 b80fe1d3 + import unittest
    import lsst.utils.tests as utilsTests import lsst.afw.detection as afwDet import lsst.afw.image as afwImage import lsst.afw.table as afwTable import lsst.afw.geom as afwGeom class SourceHeavyFootprintTestCase(unittest.TestCase): def test1(self): im = afwImage.ImageF(100, 100) im += 42. fp = afwDet.Footprint(afwGeom.Point2I(50,50), 10.) #seed = 42 #rand = afwMath.Random(afwMath.Random.MT19937, seed) #afwMath.randomGaussianImage(im, rand) mi = afwImage.MaskedImageF(im) # set a mask bit before grabbing the heavyfootprint mi.getMask().set(50, 50, 1) heavy = afwDet.makeHeavyFootprint(fp, mi) # reset it mi.getMask().set(50, 50, 0) schema = afwTable.SourceTable.makeMinimalSchema() table = afwTable.SourceTable.make(schema) table.preallocate(10) catalog = afwTable.SourceCatalog(table) catalog.addNew() # This used to segfault catalog[0].setFootprint(heavy) # However, we still have to up-cast fp = catalog[0].getFootprint() hfp = afwDet.cast_HeavyFootprintF(fp) # change one pixel... self.assertEqual(mi.getImage().get(50, 50), 42) self.assertEqual(mi.getMask().get(50, 50), 0) mi.getImage().set(50, 50, 100) mi.getMask().set(50, 50, 2) mi.getMask().set(51, 50, 2) self.assertEqual(mi.getImage().get(50, 50), 100) self.assertEqual(mi.getMask().get(50, 50), 2) self.assertEqual(mi.getMask().get(51, 50), 2) # reinsert the heavy footprint; it should reset the pixel value. # insert(MaskedImage) hfp.insert(mi) self.assertEqual(mi.getImage().get(50, 50), 42) self.assertEqual(mi.getMask().get(50, 50), 1) self.assertEqual(mi.getMask().get(51, 50), 0) # Also test insert(Image) im = mi.getImage() self.assertEqual(im.get(50, 50), 42) im.set(50, 50, 100) self.assertEqual(im.get(50, 50), 100) self.assertEqual(mi.getImage().get(50, 50), 100) # reinsert the heavy footprint; it should reset the pixel value. hfp.insert(im) self.assertEqual(im.get(50, 50), 42) self.assertEqual(mi.getImage().get(50, 50), 42) self.assertEqual(mi.getMask().get(50, 50), 1) self.assertEqual(mi.getMask().get(51, 50), 0) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(SourceHeavyFootprintTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    2d72fc25

    commit 2d72fc256bb198382ba64ed3d0a3c35d7914f412
    Author: Dustin Lang 
    Date:   Mon Apr 9 10:10:36 2012 -0500
    
        add test case that fails in trunk: setting Source.setFootprint(HeavyFootprint)
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    tests/testWcs835.py

    Diff:

    1 063674ab - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import unittest import lsst.utils.tests as tests import lsst.afw.image as afwImage
    28 d8f669a5 - import lsst.afw.coord as afwCoord
    import lsst.daf.base as dafBase import lsst.pex.exceptions as pexExcept class TanSipTestCases(unittest.TestCase): """Tests for the existence of the bug reported in #835 (Wcs class doesn't gracefully handle the case of ctypes having -SIP appended to them). """ def setUp(self): #metadata taken from CFHT data #v695856-e0/v695856-e0-c000-a00.sci_img.fits metadata = dafBase.PropertySet() metadata.set("SIMPLE", "T") metadata.set("BITPIX", -32) metadata.set("NAXIS", 2) metadata.set("NAXIS1", 1024) metadata.set("NAXIS2", 1153) metadata.set("RADECSYS", 'FK5') metadata.set("EQUINOX", 2000.) metadata.setDouble("CRVAL1", 215.604025685476) metadata.setDouble("CRVAL2", 53.1595451514076) metadata.setDouble("CRPIX1", 1109.99981456774) metadata.setDouble("CRPIX2", 560.018167811613) metadata.set("CTYPE1", 'RA---TAN-SIP') metadata.set("CTYPE2", 'DEC--TAN-SIP') metadata.setDouble("CD1_1", 5.10808596133527E-05) metadata.setDouble("CD1_2", 1.85579539217196E-07) metadata.setDouble("CD2_2", -5.10281493481982E-05) metadata.setDouble("CD2_1", -8.27440751733828E-07) self.metadata = metadata def tearDown(self): del self.metadata def testExcept(self):
    74 0460d5f2 - self.assertRaises(pexExcept.LsstCppException, afwImage.makeWcs, self.metadata)
    ? -------
    74 6fc1c3d1 + self.assertRaises(pexExcept.Exception, afwImage.makeWcs, self.metadata)
    ##### def suite(): """Returns a suite containing all the test cases in this module.""" tests.init() suites = [] suites += unittest.makeSuite(TanSipTestCases) suites += unittest.makeSuite(tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0460d5f2

    commit 0460d5f2ade1322cf0a03d31448494b2826393ec
    Author: fergal 
    Date:   Wed Jun 16 16:04:11 2010 +0000
    
        Updated tests for the new behaviour of getPixelOrigin()
    

    063674ab

    commit 063674ab8679afeba56d881e724c871a4daafe4d
    Author: fergal 
    Date:   Wed Jul 15 21:14:18 2009 +0000
    
        Wrote a test for the bug reported in ticket #835
    

    d8f669a5

    commit d8f669a5503270256a607ae1f99be80e89faa898
    Author: fergal 
    Date:   Wed Mar 24 17:44:31 2010 +0000
    
        Updated tests for the new API in Wcs and TanWcs that accepts and returns Coord objects (as appropriate)
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    src/math/binImage.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file
                     *
                     * Bin an Image or MaskedImage by an integral factor (the same in x and y)
                     */
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/offsetImage.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace afwImage = lsst::afw::image;
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    
                    template
                    PTR(ImageT) binImage(ImageT const& in,  ///< The %image to bin
                                         int const binsize, ///< Output pixels are binsize*binsize input pixels
                                         lsst::afw::math::Property const flags ///< how to generate super-pixels
                                        )
                    {
                        return binImage(in, binsize, binsize, flags);
                    }
                    
                    template
                    PTR(ImageT) binImage(ImageT const& in,  ///< The %image to bin
                                         int const binX,    ///< Output pixels are binX*binY input pixels
                                         int const binY,    ///< Output pixels are binX*binY input pixels
                                         lsst::afw::math::Property const flags ///< how to generate super-pixels
                                        )
                    {
                        if (flags != lsst::afw::math::MEAN) {
    
    55 ee59817e - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    55 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ (boost::format("Only afwMath::MEAN is supported, saw 0x%x") % flags).str()); } if (binX <= 0 || binY <= 0) {
    59 ee59817e - throw LSST_EXCEPT(pexExcept::DomainErrorException,
    ? ---------
    59 21597d88 + throw LSST_EXCEPT(pexExcept::DomainError,
    (boost::format("Binning must be >= 0, saw %dx%d") % binX % binY).str()); } int const outWidth = in.getWidth()/binX; int const outHeight = in.getHeight()/binY; typename ImageT::Ptr out = typename ImageT::Ptr( new ImageT(geom::Extent2I(outWidth, outHeight)) ); out->setXY0(in.getXY0()); *out = typename ImageT::SinglePixel(0); for (int oy = 0, iy = 0; oy < out->getHeight(); ++oy) { for (int i = 0; i != binY; ++i, ++iy) { typename ImageT::x_iterator optr = out->row_begin(oy); for (typename ImageT::x_iterator iptr = in.row_begin(iy), iend = iptr + binX*outWidth; iptr < iend; ) { typename ImageT::SinglePixel val = *iptr; ++iptr; for (int j = 1; j != binX; ++j, ++iptr) { val += *iptr; } *optr += val; ++optr; } } for (typename ImageT::x_iterator ptr = out->row_begin(oy), end = out->row_end(oy); ptr != end; ++ptr) { *ptr /= binX*binY; } } return out; } /************************************************************************************************************/ // // Explicit instantiations // /// \cond #define INSTANTIATE(TYPE) \ template afwImage::Image::Ptr \ binImage(afwImage::Image const&, int, lsst::afw::math::Property const); \ template afwImage::Image::Ptr \ binImage(afwImage::Image const&, int, int, lsst::afw::math::Property const); \ template afwImage::MaskedImage::Ptr \ binImage(afwImage::MaskedImage const&, int, lsst::afw::math::Property const); \ template afwImage::MaskedImage::Ptr \ binImage(afwImage::MaskedImage const&, int, int, lsst::afw::math::Property const); \ INSTANTIATE(boost::uint16_t) INSTANTIATE(int) INSTANTIATE(float) INSTANTIATE(double) /// \endcond }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ee59817e

    commit ee59817e6409ae51d3f23e0e9fe536ff361ad8c2
    Author: rhl 
    Date:   Tue May 25 13:12:14 2010 +0000
    
        Added binImage
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/kernelImagesForRegion.py

    Diff:

    1 d5c921da - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import math import unittest import numpy import lsst.utils.tests as utilsTests
    30 d5c921da - import lsst.pex.exceptions as pexExcept
    import lsst.pex.logging as pexLog import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.math.detail as mathDetail import lsst.afw.image.testUtils as imTestUtils VERBOSITY = 0 # increase to see trace pexLog.Debug("lsst.afw", VERBOSITY) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- LocNameDict = { mathDetail.KernelImagesForRegion.BOTTOM_LEFT: "BOTTOM_LEFT", mathDetail.KernelImagesForRegion.BOTTOM_RIGHT: "BOTTOM_RIGHT", mathDetail.KernelImagesForRegion.TOP_LEFT: "TOP_LEFT", mathDetail.KernelImagesForRegion.TOP_RIGHT: "TOP_RIGHT", } NameLocDict = dict((name, loc) for (loc, name) in LocNameDict.iteritems()) class KernelImagesForRegion(unittest.TestCase): def setUp(self): boxCorner = afwGeom.Point2I(11, 50) boxExtent = afwGeom.Extent2I(100, 99) self.bbox = afwGeom.Box2I(boxCorner, boxExtent) self.xy0 = afwGeom.Point2I(100, 251) self.kernel = self.makeKernel() def tearDown(self): self.bbox = None self.kernel = None def assertRegionCorrect(self, region): """Assert that a region has correct corner images This test is only relevant for operations that try to reuse the image array data """ regionCopy = mathDetail.KernelImagesForRegion(region.getKernel(), region.getBBox(), region.getXY0(), region.getDoNormalize()) for location in ( region.BOTTOM_LEFT, region.BOTTOM_RIGHT, region.TOP_LEFT, region.TOP_RIGHT, ): actImage = region.getImage(location) actImArr = actImage.getArray().transpose().copy() desImage = regionCopy.getImage(location) desImArr = desImage.getArray().transpose().copy() actImArr -= desImArr if not numpy.allclose(actImArr, 0): actImage.writeFits("actImage%s.fits" % (location,)) desImage.writeFits("desImage%s.fits" % (location,)) self.fail("failed on location %s" % (location,)) def makeKernel(self): kCols = 7 kRows = 6 # create spatial model sFunc = afwMath.PolynomialFunction2D(1) minSigma = 0.1 maxSigma = 3.0 # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters xSlope = (maxSigma - minSigma) / self.bbox.getWidth() ySlope = (maxSigma - minSigma) / self.bbox.getHeight() xOrigin = minSigma - (self.xy0[0] * xSlope) yOrigin = minSigma - (self.xy0[1] * ySlope) sParams = ( (xOrigin, xSlope, 0.0), (yOrigin, 0.0, ySlope), (0.0, 0.0, 0.0), ) kFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kCols, kRows, kFunc, sFunc) kernel.setSpatialParameters(sParams) return kernel def testDoNormalize(self): """Test getDoNormalize """ kernel = self.makeKernel() for doNormalize in (False, True): region = mathDetail.KernelImagesForRegion(kernel, self.bbox, self.xy0, doNormalize) self.assert_(region.getDoNormalize() == doNormalize) def testGetPixelIndex(self): """Test getPixelIndex method """ region = mathDetail.KernelImagesForRegion(self.kernel, self.bbox, self.xy0, False) leftInd = self.bbox.getMinX() rightInd = self.bbox.getMaxX() + 1 bottomInd = self.bbox.getMinY() topInd = self.bbox.getMaxY() + 1 ctrXInd = int(round((leftInd + rightInd) / 2.0)) ctrYInd = int(round((bottomInd + topInd) / 2.0)) for location, desIndex in ( (region.BOTTOM_LEFT, (leftInd, bottomInd)), (region.BOTTOM_RIGHT, (rightInd, bottomInd)), (region.TOP_LEFT, (leftInd, topInd)), (region.TOP_RIGHT, (rightInd, topInd)), ): desPixIndex = afwGeom.Point2I(desIndex[0], desIndex[1]) self.assert_(region.getPixelIndex(location) == desPixIndex, "getPixelIndex(%s) = %s != %s" % (LocNameDict[location], region.getPixelIndex(location), desPixIndex) ) def testComputeNextRow(self): """Test computeNextRow method and the resulting RowOfKernelImagesForRegion """ nx = 6 ny = 5 regionRow = mathDetail.RowOfKernelImagesForRegion(nx, ny) self.assert_(not regionRow.hasData()) self.assert_(not regionRow.isLastRow()) self.assert_(regionRow.getYInd() == -1) region = mathDetail.KernelImagesForRegion(self.kernel, self.bbox, self.xy0, False) floatWidth = self.bbox.getWidth() / float(nx) validWidths = (int(math.floor(floatWidth)), int(math.ceil(floatWidth))) floatHeight = self.bbox.getHeight() / float(ny) validHeights = (int(math.floor(floatHeight)), int(math.ceil(floatHeight))) totalHeight = 0 for yInd in range(ny): rowWidth = 0 isOK = region.computeNextRow(regionRow) self.assert_(isOK) self.assert_(regionRow.hasData()) self.assert_(regionRow.isLastRow() == (yInd + 1 >= ny)) self.assert_(regionRow.getYInd() == yInd) firstBBox = regionRow.getRegion(0).getBBox() self.assert_(firstBBox.getMinX() == self.bbox.getMinX()) if yInd == 0: self.assert_(firstBBox.getMinY() == self.bbox.getMinY()) firstBBoxHeight = firstBBox.getHeight() self.assert_(firstBBoxHeight in validHeights) totalHeight += firstBBoxHeight if yInd > 0: self.assert_(firstBBox.getMinY() == prevFirstBBox.getMaxY() + 1) if yInd == ny - 1: self.assert_(firstBBox.getMaxY() == self.bbox.getMaxY()) prevFirstBBox = firstBBox for xInd in range(nx): subregion = regionRow.getRegion(xInd) try: self.assertRegionCorrect(subregion) except: print "failed on xInd=%s, yInd=%s" % (xInd, yInd) raise bbox = subregion.getBBox() rowWidth += bbox.getWidth() self.assert_(bbox.getWidth() in validWidths) self.assert_(bbox.getHeight() == firstBBoxHeight) if xInd > 0: self.assert_(bbox.getMinX() == prevBBox.getMaxX() + 1) self.assert_(bbox.getMinY() == prevBBox.getMinY()) self.assert_(bbox.getMaxY() == prevBBox.getMaxY()) if xInd == nx - 1: self.assert_(bbox.getMaxX() == self.bbox.getMaxX()) prevBBox = bbox self.assert_(rowWidth == self.bbox.getWidth()) self.assert_(totalHeight == self.bbox.getHeight()) self.assert_(not region.computeNextRow(regionRow)) def testExactImages(self): """Confirm that kernel image at each location is correct """ desImage = afwImage.ImageD(afwGeom.Extent2I(self.kernel.getWidth(), self.kernel.getHeight())) for doNormalize in (False, True): region = mathDetail.KernelImagesForRegion(self.kernel, self.bbox, self.xy0, doNormalize) for location in ( region.BOTTOM_LEFT, region.BOTTOM_RIGHT, region.TOP_LEFT, region.TOP_RIGHT, ): pixelIndex = region.getPixelIndex(location) xPos = afwImage.indexToPosition(pixelIndex[0] + self.xy0[0]) yPos = afwImage.indexToPosition(pixelIndex[1] + self.xy0[1]) self.kernel.computeImage(desImage, doNormalize, xPos, yPos) desImArr = desImage.getArray().transpose().copy() actImage = region.getImage(location) actImArr = actImage.getArray().transpose().copy() errStr = imTestUtils.imagesDiffer(actImArr, desImArr) if errStr: self.fail("exact image(%s) incorrect:\n%s" % (LocNameDict[location], errStr)) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(KernelImagesForRegion) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(doExit=False): """Run the tests""" utilsTests.run(suite(), doExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d5c921da

    commit d5c921dacdba3ba77095a6b1b65859e3347e05f5
    Author: rowen 
    Date:   Wed May 12 16:54:36 2010 +0000
    
        Added many unit tests. Fixed a few bugs. Added some trace messages.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    tests/polygon.py

    Diff:

    1 3d6fb300 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008-2014 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import numpy import pickle import unittest
    27 c2b0c503 - import os
    import lsst.utils.tests as utilsTests
    30 3d6fb300 - import lsst.pex.exceptions as pexExcept
    import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.coord as afwCoord
    35 c2b0c503 - from lsst.afw.geom.polygon import Polygon, SinglePolygonException
    ? --------
    34 3d6fb300 + from lsst.afw.geom import Polygon, SinglePolygonException
    DEBUG = False def circle(radius, num, x0=0.0, y0=0.0): """Generate points on a circle @param radius: radius of circle @param num: number of points @param x0,y0: Offset in x,y @return x,y coordinates as numpy array """ theta = numpy.linspace(0, 2*numpy.pi, num=num, endpoint=False) x = radius*numpy.cos(theta) + x0 y = radius*numpy.sin(theta) + y0 return numpy.array([x, y]).transpose() class PolygonTest(utilsTests.TestCase): def setUp(self): self.x0 = 0.0 self.y0 = 0.0 def polygon(self, num, radius=1.0, x0=None, y0=None): """Generate a polygon @param num: Number of points @param radius: Radius of polygon @param x0,y0: Offset of center @return polygon """ if x0 is None: x0 = self.x0 if y0 is None: y0 = self.y0 points = circle(radius, num, x0=x0, y0=y0) return Polygon([afwGeom.Point2D(x,y) for x,y in reversed(points)]) def square(self, size=1.0, x0=0, y0=0): """Generate a square @param size: Half-length of the sides @param x0,y0: Offset of center """ return Polygon([afwGeom.Point2D(size*x + x0, size*y + y0) for x, y in ((-1, -1), (-1, 1), (1, 1), (1, -1))]) def testGetters(self): """Test Polygon getters""" for num in range(3, 30): poly = self.polygon(num) self.assertEqual(poly, poly) self.assertNotEqual(poly, self.square(1.0, 2.0, 3.0)) self.assertEqual(poly.getNumEdges(), num) self.assertEqual(len(poly.getVertices()), num + 1) # One extra for the closing point self.assertEqual(len(poly.getEdges()), num) perimeter = 0.0 for p1, p2 in poly.getEdges(): perimeter += numpy.hypot(p1.getX() - p2.getX(), p1.getY() - p2.getY()) self.assertAlmostEqual(poly.calculatePerimeter(), perimeter) self.assertEqual(pickle.loads(pickle.dumps(poly)), poly) size = 3.0 poly = self.square(size=size) self.assertEqual(poly.calculateArea(), (2*size)**2) self.assertEqual(poly.calculatePerimeter(), 2*size*4) edges = poly.getEdges() self.assertEqual(len(edges), 4) perimeter = 0.0 for p1, p2 in edges: self.assertEqual(abs(p1.getX()), size) self.assertEqual(abs(p1.getY()), size) self.assertEqual(abs(p2.getX()), size) self.assertEqual(abs(p2.getY()), size) self.assertNotEqual(p1, p2) def testFromBox(self): size = 1.0 poly1 = self.square(size=size) box = afwGeom.Box2D(afwGeom.Point2D(-1.0, -1.0), afwGeom.Point2D(1.0, 1.0)) poly2 = Polygon(box) self.assertEqual(poly1, poly2) def testBBox(self): """Test Polygon.getBBox""" size = 3.0 poly = self.square(size=size) box = poly.getBBox() self.assertEqual(box.getMinX(), -size) self.assertEqual(box.getMinY(), -size) self.assertEqual(box.getMaxX(), size) self.assertEqual(box.getMaxY(), size) def testCenter(self): """Test Polygon.calculateCenter""" for num in range(3, 30): poly = self.polygon(num) center = poly.calculateCenter() self.assertAlmostEqual(center.getX(), self.x0) self.assertAlmostEqual(center.getY(), self.y0) def testContains(self): """Test Polygon.contains""" radius = 1.0 for num in range(3, 30): poly = self.polygon(num, radius=radius) self.assertTrue(poly.contains(afwGeom.Point2D(self.x0, self.y0))) self.assertFalse(poly.contains(afwGeom.Point2D(self.x0 + radius, self.y0 + radius))) def testOverlaps(self): """Test Polygon.overlaps""" radius = 1.0 for num in range(3, 30): poly1 = self.polygon(num, radius=radius) poly2 = self.polygon(num, radius=radius, x0=radius, y0=radius) poly3 = self.polygon(num, radius=2*radius) poly4 = self.polygon(num, radius=radius, x0=3*radius, y0=3*radius) self.assertTrue(poly1.overlaps(poly2)) self.assertTrue(poly2.overlaps(poly1)) self.assertTrue(poly1.overlaps(poly3)) self.assertTrue(poly3.overlaps(poly1)) self.assertFalse(poly1.overlaps(poly4)) self.assertFalse(poly4.overlaps(poly1)) def testIntersection(self): """Test Polygon.intersection""" poly1 = self.square(2.0, -1.0, -1.0) poly2 = self.square(2.0, +1.0, +1.0) poly3 = self.square(1.0, 0.0, 0.0) poly4 = self.square(1.0, +5.0, +5.0) # intersectionSingle: assumes there's a single intersection (convex polygons) self.assertEqual(poly1.intersectionSingle(poly2), poly3) self.assertEqual(poly2.intersectionSingle(poly1), poly3)
    169 3d6fb300 - self.assertRaisesLsstCpp(SinglePolygonException, poly1.intersectionSingle, poly4)
    ? -------
    168 6fc1c3d1 + self.assertRaises(SinglePolygonException, poly1.intersectionSingle, poly4)
    170 3d6fb300 - self.assertRaisesLsstCpp(SinglePolygonException, poly4.intersectionSingle, poly1)
    ? -------
    169 6fc1c3d1 + self.assertRaises(SinglePolygonException, poly4.intersectionSingle, poly1)
    # intersection: no assumptions polyList1 = poly1.intersection(poly2) polyList2 = poly2.intersection(poly1) self.assertEqual(polyList1, polyList2) self.assertEqual(len(polyList1), 1) self.assertEqual(polyList1[0], poly3) polyList3 = poly1.intersection(poly4) polyList4 = poly4.intersection(poly1) self.assertEqual(polyList3, polyList4) self.assertEqual(len(polyList3), 0) def testUnion(self): """Test Polygon.union""" poly1 = self.square(2.0, -1.0, -1.0) poly2 = self.square(2.0, +1.0, +1.0) poly3 = Polygon([afwGeom.Point2D(x,y) for x,y in ((-3.0, -3.0), (-3.0, +1.0), (-1.0, +1.0), (-1.0, +3.0), (+3.0, +3.0), (+3.0, -1.0), (+1.0, -1.0), (+1.0, -3.0))]) poly4 = self.square(1.0, +5.0, +5.0) # unionSingle: assumes there's a single union (intersecting polygons) self.assertEqual(poly1.unionSingle(poly2), poly3) self.assertEqual(poly2.unionSingle(poly1), poly3)
    195 3d6fb300 - self.assertRaisesLsstCpp(SinglePolygonException, poly1.unionSingle, poly4)
    ? -------
    194 6fc1c3d1 + self.assertRaises(SinglePolygonException, poly1.unionSingle, poly4)
    196 3d6fb300 - self.assertRaisesLsstCpp(SinglePolygonException, poly4.unionSingle, poly1)
    ? -------
    195 6fc1c3d1 + self.assertRaises(SinglePolygonException, poly4.unionSingle, poly1)
    # union: no assumptions polyList1 = poly1.union(poly2) polyList2 = poly2.union(poly1) self.assertEqual(polyList1, polyList2) self.assertEqual(len(polyList1), 1) self.assertEqual(polyList1[0], poly3) polyList3 = poly1.union(poly4) polyList4 = poly4.union(poly1) self.assertEqual(len(polyList3), 2) self.assertEqual(len(polyList3), len(polyList4)) self.assertTrue((polyList3[0] == polyList4[0] and polyList3[1] == polyList4[1]) or (polyList3[0] == polyList4[1] and polyList3[1] == polyList4[0])) self.assertTrue((polyList3[0] == poly1 and polyList3[1] == poly4) or (polyList3[0] == poly4 and polyList3[1] == poly1))
    213 afaf57ce - def testSymDifference(self):
    214 afaf57ce - """Test Polygon.symDifference"""
    215 afaf57ce - poly1 = self.square(2.0, -1.0, -1.0)
    216 afaf57ce - poly2 = self.square(2.0, +1.0, +1.0)
    217 afaf57ce -
    218 afaf57ce - poly3 = Polygon([afwGeom.Point2D(x,y) for x,y in
    219 afaf57ce - ((-3.0, -3.0), (-3.0, +1.0), (-1.0, +1.0), (-1.0, -1.0), (+1.0, -1.0), (1.0, -3.0))])
    220 afaf57ce - poly4 = Polygon([afwGeom.Point2D(x,y) for x,y in
    221 afaf57ce - ((-1.0, +1.0), (-1.0, +3.0), (+3.0, +3.0), (+3.0, -1.0), (+1.0, -1.0), (1.0, +1.0))])
    222 afaf57ce -
    223 afaf57ce - diff1 = poly1.symDifference(poly2)
    224 afaf57ce - diff2 = poly2.symDifference(poly1)
    225 afaf57ce -
    226 afaf57ce - self.assertEqual(len(diff1), 2)
    227 afaf57ce - self.assertEqual(len(diff2), 2)
    228 afaf57ce - self.assertTrue((diff1[0] == diff2[0] and diff1[1] == diff2[1]) or
    229 afaf57ce - (diff1[1] == diff2[0] and diff1[0] == diff2[1]))
    230 afaf57ce - self.assertTrue((diff1[0] == poly3 and diff1[1] == poly4) or
    231 afaf57ce - (diff1[1] == poly3 and diff1[0] == poly4))
    232 afaf57ce -
    def testConvexHull(self): """Test Polygon.convexHull""" poly1 = self.square(2.0, -1.0, -1.0) poly2 = self.square(2.0, +1.0, +1.0) poly = poly1.unionSingle(poly2) expected = Polygon([afwGeom.Point2D(x,y) for x,y in ((-3.0, -3.0), (-3.0, +1.0), (-1.0, +3.0), (+3.0, +3.0), (+3.0, -1.0), (+1.0, -3.0))]) self.assertEqual(poly.convexHull(), expected) def testImage(self): """Test Polygon.createImage""" for i, num in enumerate(range(3, 30)): poly = self.polygon(num, 25, 75, 75) box = afwGeom.Box2I(afwGeom.Point2I(15, 15), afwGeom.Extent2I(115, 115)) image = poly.createImage(box) if DEBUG: import lsst.afw.display.ds9 as ds9 ds9.mtv(image, frame=i+1, title="Polygon nside=%d" % num) for p1, p2 in poly.getEdges(): ds9.line((p1, p2), frame=i+1) self.assertAlmostEqual(image.getArray().sum()/poly.calculateArea(), 1.0, 6) def testTransform(self): """Test constructor for Polygon involving transforms""" box = afwGeom.Box2D(afwGeom.Point2D(0.0, 0.0), afwGeom.Point2D(123.4, 567.8)) poly1 = Polygon(box) scale = (0.2*afwGeom.arcseconds).asDegrees() wcs = afwImage.makeWcs(afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), scale, 0.0, 0.0, scale) transform = afwImage.XYTransformFromWcsPair(wcs, wcs) poly2 = Polygon(box, transform) # We lose some very small precision in the XYTransformFromWcsPair # so we can't compare the polygons directly. self.assertEqual(poly1.getNumEdges(), poly2.getNumEdges()) for p1, p2 in zip(poly1.getVertices(), poly2.getVertices()): self.assertAlmostEqual(p1.getX(), p2.getX()) self.assertAlmostEqual(p1.getY(), p2.getY()) transform = afwGeom.AffineTransform.makeScaling(1.0) poly3 = Polygon(box, transform) self.assertEqual(poly1, poly3) def testIteration(self): """Test iteration over polygon""" for num in range(3, 30): poly = self.polygon(num) self.assertEqual(len(poly), num) points1 = [p for p in poly] points2 = poly.getVertices() self.assertEqual(points2[0], points2[-1]) # Closed representation for p1, p2 in zip(points1, points2): self.assertEqual(p1, p2) for i, p1 in enumerate(points1): self.assertEqual(poly[i], p1) def testSubSample(self): """Test Polygon.subSample""" for num in range(3, 30): poly = self.polygon(num) sub = poly.subSample(2) if DEBUG: import matplotlib.pyplot as plt axes = poly.plot(c='b') sub.plot(axes, c='r') plt.show() self.assertEqual(len(sub), 2*num) self.assertAlmostEqual(sub.calculateArea(), poly.calculateArea()) self.assertAlmostEqual(sub.calculatePerimeter(), poly.calculatePerimeter()) polyCenter = poly.calculateCenter() subCenter = sub.calculateCenter() self.assertAlmostEqual(polyCenter[0], subCenter[0]) self.assertAlmostEqual(polyCenter[1], subCenter[1]) for i in range(num): self.assertEqual(sub[2*i], poly[i]) sub = poly.subSample(0.1) self.assertAlmostEqual(sub.calculateArea(), poly.calculateArea()) self.assertAlmostEqual(sub.calculatePerimeter(), poly.calculatePerimeter()) polyCenter = poly.calculateCenter() subCenter = sub.calculateCenter() self.assertAlmostEqual(polyCenter[0], subCenter[0]) self.assertAlmostEqual(polyCenter[1], subCenter[1])
    321 3d6fb300 - def testTransform(self):
    300 b80fe1d3 + def testTransform2(self):
    ? + scale = 2.0 shift = afwGeom.Extent2D(3.0, 4.0) transform = afwGeom.AffineTransform.makeTranslation(shift)*afwGeom.AffineTransform.makeScaling(scale) for num in range(3, 30): small = self.polygon(num, 1.0, 0.0, 0.0) large = small.transform(transform) expect = self.polygon(num, scale, shift[0], shift[1]) self.assertEqual(large, expect) if DEBUG: import matplotlib.pyplot as plt axes = small.plot(c='k') large.plot(axes, c='b') expected.plot(axes, c='r') plt.show()
    338 c2b0c503 - def testReadWrite(self):
    339 c2b0c503 - """Test that polygons can be read and written to fits files"""
    340 c2b0c503 - for num in range(3, 30):
    341 c2b0c503 - poly = self.polygon(num)
    342 c2b0c503 - filename='polygon.fits'
    343 c2b0c503 - poly.writeFits(filename)
    344 c2b0c503 - poly2=Polygon.readFits(filename)
    345 c2b0c503 - self.assertEqual(poly, poly2)
    346 c2b0c503 - os.remove(filename)
    def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(PolygonTest) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    afaf57ce

    commit afaf57ce5564053054fa700e175e4097a26fec3a
    Author: Paul Price 
    Date:   Sat Mar 1 14:48:26 2014 -0500
    
        Polygon: add symmetric difference
    

    3d6fb300

    commit 3d6fb3001856d9c793c9e6291ea65ccb9e252e7f
    Author: Paul Price 
    Date:   Mon Feb 10 17:50:34 2014 -0500
    
        add CartesianPolygon class (#3139)
    

    c2b0c503

    commit c2b0c503a629b28be7ecee948d082b72516cecb7
    Author: Bob Armstrong 
    Date:   Fri Sep 5 16:33:15 2014 -0400
    
        Polygon: Add table based persistance for Polygon.
        
        This required a split of the Python wrappers for Polygon into a separate module, in its
        own namespace, to resolve a circular dependency.  As part of this, Polygons are now passed around
        by shared_pointer instead of by-value.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    3d6fb300

    commit 3d6fb3001856d9c793c9e6291ea65ccb9e252e7f
    Author: Paul Price 
    Date:   Mon Feb 10 17:50:34 2014 -0500
    
        add CartesianPolygon class (#3139)
    

    Return to list

    tests/exposure.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Test lsst.afw.image.Exposure Author: Nicole M. Silvestri, University of Washington Contact: nms@astro.washington.edu Created on: Mon Sep 10, 2007 """
    33 61855404 - import os
    import os.path import unittest import numpy
    39 61855404 - import eups
    39 7cbb2bb9 + import lsst.utils
    import lsst.daf.base as dafBase
    41 df5b9909 - import lsst.afw.detection as afwDetection
    import lsst.afw.image as afwImage
    43 b5f3475b - import lsst.afw.math as afwMath
    import lsst.afw.geom as afwGeom
    45 d8f669a5 - import lsst.afw.coord as afwCoord
    import lsst.afw.table as afwTable
    47 18d5e213 - import lsst.afw.cameraGeom as cameraGeom
    import lsst.utils.tests as utilsTests import lsst.pex.exceptions as pexExcept import lsst.pex.logging as pexLog import lsst.pex.policy as pexPolicy import lsst.afw.fits
    49 83333880 + from lsst.afw.cameraGeom.testUtils import DetectorWrapper
    from testTableArchivesLib import DummyPsf try: type(VERBOSITY) except: VERBOSITY = 0 # increase to see trace pexLog.Debug("lsst.afw.image", VERBOSITY)
    62 54c68ba0 - try:
    63 54c68ba0 - dataDir = os.path.join(eups.productDir("afwdata"), "data")
    ? ---- ^ ^ ^^^^^ ^
    59 7cbb2bb9 + dataDir = os.path.join(lsst.utils.getPackageDir("afwdata"), "data")
    ? ^^^^^ ^^^ ^^^^^ ^^^^
    64 54c68ba0 - except Exception:
    65 23962509 - raise RuntimeError("Must set up afwdata to run these tests")
    InputMaskedImageName = "871034p_1_MI.fits" InputMaskedImageNameSmall = "small_MI.fits" InputImageNameSmall = "small" OutputMaskedImageName = "871034p_1_MInew.fits" currDir = os.path.abspath(os.path.dirname(__file__)) inFilePath = os.path.join(dataDir, InputMaskedImageName) inFilePathSmall = os.path.join(dataDir, InputMaskedImageNameSmall) inFilePathSmallImage = os.path.join(dataDir, InputImageNameSmall)
    76 98bb0015 - outFile = OutputMaskedImageName
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ExposureTestCase(unittest.TestCase): """ A test case for the Exposure Class """ def setUp(self): maskedImage = afwImage.MaskedImageF(inFilePathSmall) maskedImageMD = afwImage.readMetadata(inFilePathSmall) self.smallExposure = afwImage.ExposureF(inFilePathSmall) self.width = maskedImage.getWidth() self.height = maskedImage.getHeight() self.wcs = afwImage.makeWcs(maskedImageMD) self.psf = DummyPsf(2.0)
    87 83333880 + self.detector = DetectorWrapper().detector
    self.exposureBlank = afwImage.ExposureF() self.exposureMiOnly = afwImage.makeExposure(maskedImage) self.exposureMiWcs = afwImage.makeExposure(maskedImage, self.wcs) self.exposureCrWcs = afwImage.ExposureF(100, 100, self.wcs) # n.b. the (100, 100, ...) form self.exposureCrOnly = afwImage.ExposureF(afwGeom.ExtentI(100, 100)) # test with ExtentI(100, 100) too afwImage.Filter.reset() afwImage.FilterProperty.reset() filterPolicy = pexPolicy.Policy() filterPolicy.add("lambdaEff", 470.0) afwImage.Filter.define(afwImage.FilterProperty("g", filterPolicy)) def tearDown(self): del self.smallExposure del self.wcs del self.psf
    106 83333880 + del self.detector
    del self.exposureBlank del self.exposureMiOnly del self.exposureMiWcs del self.exposureCrWcs del self.exposureCrOnly def testGetMaskedImage(self): """ Test to ensure a MaskedImage can be obtained from each Exposure. An Exposure is required to have a MaskedImage, therefore each of the Exposures should return a MaskedImage. MaskedImage class should throw appropriate lsst::pex::exceptions::NotFound if the MaskedImage can not be obtained. """ maskedImageBlank = self.exposureBlank.getMaskedImage() blankWidth = maskedImageBlank.getWidth() blankHeight = maskedImageBlank.getHeight() if blankWidth != blankHeight != 0: self.fail("%s = %s != 0" % (blankWidth, blankHeight)) maskedImageMiOnly = self.exposureMiOnly.getMaskedImage() miOnlyWidth = maskedImageMiOnly.getWidth() miOnlyHeight = maskedImageMiOnly.getHeight() self.assertAlmostEqual(miOnlyWidth, self.width) self.assertAlmostEqual(miOnlyHeight, self.height) # NOTE: Unittests for Exposures created from a MaskedImage and # a WCS object are incomplete. No way to test the validity of # the WCS being copied/created. maskedImageMiWcs = self.exposureMiWcs.getMaskedImage() miWcsWidth = maskedImageMiWcs.getWidth() miWcsHeight = maskedImageMiWcs.getHeight() self.assertAlmostEqual(miWcsWidth, self.width) self.assertAlmostEqual(miWcsHeight, self.height) maskedImageCrWcs = self.exposureCrWcs.getMaskedImage() crWcsWidth = maskedImageCrWcs.getWidth() crWcsHeight = maskedImageCrWcs.getHeight() if crWcsWidth != crWcsHeight != 0: self.fail("%s != %s != 0" % (crWcsWidth, crWcsHeight)) maskedImageCrOnly = self.exposureCrOnly.getMaskedImage() crOnlyWidth = maskedImageCrOnly.getWidth() crOnlyHeight = maskedImageCrOnly.getHeight() if crOnlyWidth != crOnlyHeight != 0: self.fail("%s != %s != 0" % (crOnlyWidth, crOnlyHeight)) # Check Exposure.getWidth() returns the MaskedImage's width self.assertEqual(crOnlyWidth, self.exposureCrOnly.getWidth()) self.assertEqual(crOnlyHeight, self.exposureCrOnly.getHeight()) def testGetWcs(self): """ Test if a WCS can be obtained from each Exposure created with a WCS. Test that appropriate exceptions are thrown if a WCS is requested from an Exposure that was not created with a WCS. Python turns the pex::exceptions in the Exposure and MaskedImage classes into IndexErrors. The exposureBlank, exposureMiOnly, and exposureCrOnly Exposures should throw a lsst::pex::exceptions::NotFound. """ self.assertTrue(not self.exposureBlank.getWcs()) self.assertTrue(not self.exposureMiOnly.getWcs()) # These two should pass self.exposureMiWcs.getWcs() self.exposureCrWcs.getWcs() self.assertTrue(not self.exposureCrOnly.getWcs()) def testSetMembers(self): """ Test that the MaskedImage and the WCS of an Exposure can be set. """ exposure = afwImage.ExposureF() maskedImage = afwImage.MaskedImageF(inFilePathSmall) exposure.setMaskedImage(maskedImage) exposure.setWcs(self.wcs)
    199 18d5e213 - exposure.setDetector(cameraGeom.Detector(cameraGeom.Id(666)))
    194 83333880 + exposure.setDetector(self.detector)
    exposure.setFilter(afwImage.Filter("g"))
    197 83333880 + self.assertEquals(exposure.getDetector().getName(), self.detector.getName())
    202 18d5e213 - self.assertEquals(exposure.getDetector().getId().getSerial(), 666)
    ? ^^ -----
    198 83333880 + self.assertEquals(exposure.getDetector().getSerial(), self.detector.getSerial())
    ? ^^^^^^ +++++++++++++++ self.assertEquals(exposure.getFilter().getName(), "g") try: exposure.getWcs()
    207 3771b5eb - except pexExcept.LsstCppException, e:
    ? ------- ^
    203 6fc1c3d1 + except pexExcept.Exception as e:
    ? ^^^ print "caught expected exception (getWcs): %s" % e pass # # Test the Calib member. The Calib tests are in color.py, here we just check that it's in Exposure # calib = exposure.getCalib() dt = 10 calib.setExptime(dt) self.assertEqual(exposure.getCalib().getExptime(), dt) # # now check that we can set Calib # calib = afwImage.Calib() dt = 666 calib.setExptime(dt) exposure.setCalib(calib) self.assertEqual(exposure.getCalib().getExptime(), dt) # # Psfs next #
    230 df5b9909 - w, h = 11, 11
    self.assertFalse(exposure.hasPsf()) exposure.setPsf(self.psf) self.assertTrue(exposure.hasPsf()) exposure.setPsf(DummyPsf(1.0)) # we can reset the Psf # Test that we can set the MaskedImage and WCS of an Exposure # that already has both self.exposureMiWcs.setMaskedImage(maskedImage) exposure.setWcs(self.wcs) def testHasWcs(self): """ Test if an Exposure has a WCS or not. """ self.assertFalse(self.exposureBlank.hasWcs()) self.assertFalse(self.exposureMiOnly.hasWcs()) self.assertTrue(self.exposureMiWcs.hasWcs()) self.assertTrue(self.exposureCrWcs.hasWcs()) self.assertFalse(self.exposureCrOnly.hasWcs()) def testGetSubExposure(self): """ Test that a subExposure of the original Exposure can be obtained. The MaskedImage class should throw a lsst::pex::exceptions::InvalidParameter if the requested subRegion is not fully contained within the original MaskedImage. """ # # This subExposure is valid # subBBox = afwGeom.Box2I(afwGeom.Point2I(40, 50), afwGeom.Extent2I(10, 10)) subExposure = self.exposureCrWcs.Factory(self.exposureCrWcs, subBBox, afwImage.LOCAL) self.checkWcs(self.exposureCrWcs, subExposure) # this subRegion is not valid and should trigger an exception # from the MaskedImage class and should trigger an exception # from the WCS class for the MaskedImage 871034p_1_MI. subRegion3 = afwGeom.Box2I(afwGeom.Point2I(100, 100), afwGeom.Extent2I(10, 10)) def getSubRegion(): self.exposureCrWcs.Factory(self.exposureCrWcs, subRegion3, afwImage.LOCAL)
    279 3771b5eb - utilsTests.assertRaisesLsstCpp(self, pexExcept.LengthErrorException, getSubRegion)
    ? ^^^ ^^^^^^ ------- ------ ---------
    274 6fc1c3d1 + self.assertRaises(pexExcept.LengthError, getSubRegion)
    ? ^^ ^ # this subRegion is not valid and should trigger an exception # from the MaskedImage class only for the MaskedImage small_MI. # small_MI (cols, rows) = (256, 256) subRegion4 = afwGeom.Box2I(afwGeom.Point2I(250, 250), afwGeom.Extent2I(10, 10)) def getSubRegion(): self.exposureCrWcs.Factory(self.exposureCrWcs, subRegion4, afwImage.LOCAL)
    289 3771b5eb - utilsTests.assertRaisesLsstCpp(self, pexExcept.LengthErrorException, getSubRegion)
    ? ^^^ ^^^^^^ ------- ------ ---------
    284 6fc1c3d1 + self.assertRaises(pexExcept.LengthError, getSubRegion)
    ? ^^ ^ #check the sub- and parent- exposures are using the same Wcs transformation subBBox = afwGeom.Box2I(afwGeom.Point2I(40, 50), afwGeom.Extent2I(10, 10)) subExposure = self.exposureCrWcs.Factory(self.exposureCrWcs, subBBox, afwImage.LOCAL) parentPos = self.exposureCrWcs.getWcs().pixelToSky(0,0) parentPos = parentPos.getPosition() subExpPos = subExposure.getWcs().pixelToSky(0,0).getPosition() for i in range(2): self.assertAlmostEqual(parentPos[i], subExpPos[i], 9, "Wcs in sub image has changed") def testReadWriteFits(self): """Test readFits and writeFits. """ # This should pass without an exception mainExposure = afwImage.ExposureF(inFilePathSmall)
    308 98bb0015 - mainExposure.setDetector(cameraGeom.Detector(cameraGeom.Id(666)))
    303 83333880 + mainExposure.setDetector(self.detector)
    subBBox = afwGeom.Box2I(afwGeom.Point2I(10, 10), afwGeom.Extent2I(40, 50)) subExposure = mainExposure.Factory(mainExposure, subBBox, afwImage.LOCAL) self.checkWcs(mainExposure, subExposure) det = subExposure.getDetector() self.assertTrue(det)
    316 ded0eb52 - subExposure = afwImage.ExposureF(inFilePathSmall, subBBox)
    311 eea3eb4a + subExposure = afwImage.ExposureF(inFilePathSmall, subBBox, afwImage.LOCAL)
    ? ++++++++++++++++ self.checkWcs(mainExposure, subExposure) # This should throw an exception def getExposure(): afwImage.ExposureF(inFilePathSmallImage)
    324 adb78502 - utilsTests.assertRaisesLsstCpp(self, lsst.afw.fits.FitsError, getExposure)
    ? ^^^ ^^^^^^ ------- ------
    319 6fc1c3d1 + self.assertRaises(lsst.afw.fits.FitsError, getExposure)
    ? ^^ ^ mainExposure.setPsf(self.psf) # Make sure we can write without an exception mainExposure.getCalib().setExptime(10) mainExposure.getCalib().setMidTime(dafBase.DateTime()) midMjd = mainExposure.getCalib().getMidTime().get() fluxMag0, fluxMag0Err = 1e12, 1e10 mainExposure.getCalib().setFluxMag0(fluxMag0, fluxMag0Err)
    330 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    335 98bb0015 - mainExposure.writeFits(outFile)
    ? --
    331 c605dfcd + mainExposure.writeFits(tmpFile)
    ? ++++ ++
    337 f3d3029c - # Check scaling of Calib
    338 f3d3029c - scale = 2.0
    339 f3d3029c - calib = mainExposure.getCalib()
    340 f3d3029c - calib *= scale
    341 f3d3029c - self.assertEqual((fluxMag0*scale, fluxMag0Err*scale), calib.getFluxMag0())
    342 f3d3029c - calib /= scale
    343 f3d3029c - self.assertEqual((fluxMag0, fluxMag0Err), calib.getFluxMag0())
    344 f3d3029c -
    345 a6d8990e - readExposure = type(mainExposure)(outFile)
    ? --
    333 c605dfcd + readExposure = type(mainExposure)(tmpFile)
    ? ++++ ++
    347 98bb0015 - os.remove(outFile)
    348 a6d8990e - #
    335 c605dfcd + #
    ? ++++
    349 a6d8990e - # Check the round-tripping
    336 c605dfcd + # Check the round-tripping
    ? ++++
    350 a6d8990e - #
    337 c605dfcd + #
    ? ++++
    351 a6d8990e - self.assertEqual(mainExposure.getFilter().getName(), readExposure.getFilter().getName())
    338 c605dfcd + self.assertEqual(mainExposure.getFilter().getName(), readExposure.getFilter().getName())
    ? ++++
    353 a6d8990e - self.assertEqual(mainExposure.getCalib().getExptime(), readExposure.getCalib().getExptime())
    340 c605dfcd + self.assertEqual(mainExposure.getCalib().getExptime(), readExposure.getCalib().getExptime())
    ? ++++
    354 a6d8990e - self.assertEqual(midMjd, readExposure.getCalib().getMidTime().get())
    341 c605dfcd + self.assertEqual(midMjd, readExposure.getCalib().getMidTime().get())
    ? ++++
    355 a6d8990e - self.assertEqual((fluxMag0, fluxMag0Err), readExposure.getCalib().getFluxMag0())
    342 c605dfcd + self.assertEqual((fluxMag0, fluxMag0Err), readExposure.getCalib().getFluxMag0())
    ? ++++
    357 4f859dd5 - psf = readExposure.getPsf()
    344 c605dfcd + psf = readExposure.getPsf()
    ? ++++
    358 4f859dd5 - self.assert_(psf is not None)
    345 c605dfcd + self.assert_(psf is not None)
    ? ++++
    359 96b804a8 - dummyPsf = DummyPsf.swigConvert(psf)
    346 c605dfcd + dummyPsf = DummyPsf.swigConvert(psf)
    ? ++++
    360 96b804a8 - self.assert_(dummyPsf is not None)
    347 c605dfcd + self.assert_(dummyPsf is not None)
    ? ++++
    361 96b804a8 - self.assertEqual(dummyPsf.getValue(), self.psf.getValue())
    348 c605dfcd + self.assertEqual(dummyPsf.getValue(), self.psf.getValue())
    ? ++++ def checkWcs(self, parentExposure, subExposure): """Compare WCS at corner points of a sub-exposure and its parent exposure By using the function indexToPosition, we should be able to convert the indices (of the four corners (of the sub-exposure)) to positions and use the wcs to get the same sky coordinates for each. """ subMI = subExposure.getMaskedImage() subDim = subMI.getDimensions()
    371 48b7a605 - subXY0 = subMI.getXY0()
    # Note: pixel positions must be computed relative to XY0 when working with WCS mainWcs = parentExposure.getWcs() subWcs = subExposure.getWcs() for xSubInd in (0, subDim.getX()-1): for ySubInd in (0, subDim.getY()-1): p0 = mainWcs.pixelToSky( afwImage.indexToPosition(xSubInd), afwImage.indexToPosition(ySubInd), ) p1 = subWcs.pixelToSky( afwImage.indexToPosition(xSubInd), afwImage.indexToPosition(ySubInd), ) def cmpExposure(self, e1, e2):
    389 b5f3475b - self.assertEqual(e1.getDetector(), e2.getDetector())
    375 83333880 + self.assertEqual(e1.getDetector().getName(), e2.getDetector().getName())
    ? ++++++++++ ++++++++++
    376 83333880 + self.assertEqual(e1.getDetector().getSerial(), e2.getDetector().getSerial())
    self.assertEqual(e1.getFilter().getName(), e2.getFilter().getName()) xy = afwGeom.Point2D(0, 0) self.assertEqual(e1.getWcs().pixelToSky(xy)[0], e2.getWcs().pixelToSky(xy)[0]) self.assertEqual(e1.getCalib().getExptime(), e2.getCalib().getExptime()) # check PSF identity if not e1.getPsf(): self.assertFalse(e2.getPsf()) else: psf1 = DummyPsf.swigConvert(e1.getPsf()) psf2 = DummyPsf.swigConvert(e2.getPsf()) self.assertEqual(psf1.getValue(), psf2.getValue()) def testCopyExposure(self): """Copy an Exposure (maybe changing type)""" exposureU = afwImage.ExposureU(inFilePathSmall) exposureU.setWcs(self.wcs)
    407 4ab68235 - exposureU.setDetector(cameraGeom.Detector(cameraGeom.Id(666)))
    394 83333880 + exposureU.setDetector(self.detector)
    exposureU.setFilter(afwImage.Filter("g")) exposureU.getCalib().setExptime(666) exposureU.setPsf(DummyPsf(4.0)) exposureF = exposureU.convertF() self.cmpExposure(exposureF, exposureU) nexp = exposureF.Factory(exposureF, False) self.cmpExposure(exposureF, nexp) # Ensure that the copy was deep. # (actually this test is invalid since getDetector() returns a CONST_PTR) # cen0 = exposureU.getDetector().getCenterPixel() # x0,y0 = cen0 # det = exposureF.getDetector() # det.setCenterPixel(afwGeom.Point2D(999.0, 437.8)) # self.assertEqual(exposureU.getDetector().getCenterPixel()[0], x0) # self.assertEqual(exposureU.getDetector().getCenterPixel()[1], y0) def testDeepCopyData(self): """Make sure a deep copy of an Exposure has its own data (ticket #2625) """ exp = afwImage.ExposureF(6, 7) mi = exp.getMaskedImage() mi.getImage().set(100) mi.getMask().set(5) mi.getVariance().set(200)
    435 4cbc7441 - miArrays = mi.getArrays()
    expCopy = exp.clone() miCopy = expCopy.getMaskedImage() miCopy.getImage().set(-50) miCopy.getMask().set(2) miCopy.getVariance().set(175)
    442 4cbc7441 - miCopyArrays = miCopy.getArrays()
    self.assertTrue(numpy.allclose(miCopy.getImage().getArray(), -50)) self.assertTrue(numpy.all(miCopy.getMask().getArray() == 2)) self.assertTrue(numpy.allclose(miCopy.getVariance().getArray(), 175)) self.assertTrue(numpy.allclose(mi.getImage().getArray(), 100)) self.assertTrue(numpy.all(mi.getMask().getArray() == 5)) self.assertTrue(numpy.allclose(mi.getVariance().getArray(), 200)) def testDeepCopySubData(self): """Make sure a deep copy of a subregion of an Exposure has its own data (ticket #2625) """ exp = afwImage.ExposureF(6, 7) mi = exp.getMaskedImage() mi.getImage().set(100) mi.getMask().set(5) mi.getVariance().set(200)
    461 4cbc7441 - miArrays = mi.getArrays()
    bbox = afwGeom.Box2I(afwGeom.Point2I(1,0), afwGeom.Extent2I(5, 4)) expCopy = exp.Factory(exp, bbox, afwImage.PARENT, True) miCopy = expCopy.getMaskedImage() miCopy.getImage().set(-50) miCopy.getMask().set(2) miCopy.getVariance().set(175)
    469 4cbc7441 - miCopyArrays = miCopy.getArrays()
    self.assertTrue(numpy.allclose(miCopy.getImage().getArray(), -50)) self.assertTrue(numpy.all(miCopy.getMask().getArray() == 2)) self.assertTrue(numpy.allclose(miCopy.getVariance().getArray(), 175)) self.assertTrue(numpy.allclose(mi.getImage().getArray(), 100)) self.assertTrue(numpy.all(mi.getMask().getArray() == 5)) self.assertTrue(numpy.allclose(mi.getVariance().getArray(), 200)) def testDeepCopyMetadata(self): """Make sure a deep copy of an Exposure has a deep copy of metadata (ticket #2568) """ exp = afwImage.ExposureF(10, 10) expMeta = exp.getMetadata() expMeta.set("foo", 5) expCopy = exp.clone() expCopyMeta = expCopy.getMetadata() expCopyMeta.set("foo", 6) self.assertEqual(expCopyMeta.get("foo"), 6) self.assertEqual(expMeta.get("foo"), 5) # this will fail if the bug is present def testDeepCopySubMetadata(self): """Make sure a deep copy of a subregion of an Exposure has a deep copy of metadata (ticket #2568) """ exp = afwImage.ExposureF(10, 10) expMeta = exp.getMetadata() expMeta.set("foo", 5) bbox = afwGeom.Box2I(afwGeom.Point2I(1,0), afwGeom.Extent2I(5, 5)) expCopy = exp.Factory(exp, bbox, afwImage.PARENT, True) expCopyMeta = expCopy.getMetadata() expCopyMeta.set("foo", 6) self.assertEqual(expCopyMeta.get("foo"), 6) self.assertEqual(expMeta.get("foo"), 5) # this will fail if the bug is present def testMakeExposureLeaks(self): """Test for memory leaks in makeExposure (the test is in utilsTests.MemoryTestCase)""" m = afwImage.makeMaskedImage(afwImage.ImageU(afwGeom.Extent2I(10, 20))) e = afwImage.makeExposure(afwImage.makeMaskedImage(afwImage.ImageU(afwGeom.Extent2I(10, 20)))) def testImageSlices(self): """Test image slicing, which generate sub-images using Box2I under the covers""" exp = afwImage.ExposureF(10, 20) mi = exp.getMaskedImage() mi[9, 19] = 10 # N.b. Exposures don't support setting/getting the pixels so can't replicate e.g. Image's slice tests sexp = exp[1:4, 6:10] self.assertEqual(sexp.getDimensions(), afwGeom.ExtentI(3, 4)) sexp = exp[..., -3:] self.assertEqual(sexp.getDimensions(), afwGeom.ExtentI(exp.getWidth(), 3)) self.assertEqual(sexp.getMaskedImage().get(sexp.getWidth() - 1, sexp.getHeight() - 1), exp.getMaskedImage().get( exp.getWidth() - 1, exp.getHeight() - 1)) def testConversionToScalar(self): """Test that even 1-pixel Exposures can't be converted to scalars""" im = afwImage.ExposureF(10, 20) self.assertRaises(TypeError, float, im) # only single pixel images may be converted self.assertRaises(TypeError, float, im[0,0]) # actually, can't convert (img, msk, var) to scalar def testReadMetadata(self):
    530 7c299b58 - filename = "testExposureMetadata.fits"
    513 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    531 7c299b58 - self.exposureCrWcs.getMetadata().set("FRAZZLE", True)
    514 c605dfcd + self.exposureCrWcs.getMetadata().set("FRAZZLE", True)
    ? ++++
    532 7c299b58 - # This will write the main metadata (inc. FRAZZLE) to the primary HDU, and the
    515 c605dfcd + # This will write the main metadata (inc. FRAZZLE) to the primary HDU, and the
    ? ++++
    533 7c299b58 - # WCS to subsequent HDUs, along with INHERIT=T.
    516 c605dfcd + # WCS to subsequent HDUs, along with INHERIT=T.
    ? ++++
    534 7c299b58 - self.exposureCrWcs.writeFits(filename)
    ? ^ ----
    517 c605dfcd + self.exposureCrWcs.writeFits(tmpFile)
    ? ++++ ^^^^
    535 7c299b58 - # This should read the first non-empty HDU (i.e. it skips the primary), but
    518 c605dfcd + # This should read the first non-empty HDU (i.e. it skips the primary), but
    ? ++++
    536 7c299b58 - # goes back and reads it if it finds INHERIT=T. That should let us read
    519 c605dfcd + # goes back and reads it if it finds INHERIT=T. That should let us read
    ? ++++
    537 7c299b58 - # frazzle and the Wcs from the PropertySet returned by readMetadata.
    520 c605dfcd + # frazzle and the Wcs from the PropertySet returned by readMetadata.
    ? ++++
    538 7c299b58 - md = afwImage.readMetadata(filename)
    ? ^ ----
    521 c605dfcd + md = afwImage.readMetadata(tmpFile)
    ? ++++ ^^^^
    539 7c299b58 - wcs = afwImage.makeWcs(md, True)
    522 c605dfcd + wcs = afwImage.makeWcs(md, True)
    ? ++++
    540 7c299b58 - self.assertEqual(wcs.getPixelOrigin(), self.wcs.getPixelOrigin())
    523 c605dfcd + self.assertEqual(wcs.getPixelOrigin(), self.wcs.getPixelOrigin())
    ? ++++
    541 7c299b58 - self.assertEqual(wcs.getSkyOrigin(), self.wcs.getSkyOrigin())
    524 c605dfcd + self.assertEqual(wcs.getSkyOrigin(), self.wcs.getSkyOrigin())
    ? ++++
    542 7c299b58 - self.assert_(numpy.all(wcs.getCDMatrix() == self.wcs.getCDMatrix()))
    525 c605dfcd + self.assert_(numpy.all(wcs.getCDMatrix() == self.wcs.getCDMatrix()))
    ? ++++
    543 7c299b58 - frazzle = md.get("FRAZZLE")
    526 c605dfcd + frazzle = md.get("FRAZZLE")
    ? ++++
    544 7c299b58 - self.assert_(frazzle is True)
    527 c605dfcd + self.assert_(frazzle is True)
    ? ++++
    545 7c299b58 - os.remove(filename)
    def testArchiveKeys(self):
    548 b775ea4b - filename = "testArchiveKeys.fits"
    530 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    549 b775ea4b - exposure1 = afwImage.ExposureF(100, 100, self.wcs)
    531 c605dfcd + exposure1 = afwImage.ExposureF(100, 100, self.wcs)
    ? ++++
    550 b775ea4b - exposure1.setPsf(self.psf)
    532 c605dfcd + exposure1.setPsf(self.psf)
    ? ++++
    551 b775ea4b - exposure1.writeFits(filename)
    ? ^ ----
    533 c605dfcd + exposure1.writeFits(tmpFile)
    ? ++++ ^^^^
    552 b775ea4b - exposure2 = afwImage.ExposureF(filename)
    ? ^ ----
    534 c605dfcd + exposure2 = afwImage.ExposureF(tmpFile)
    ? ++++ ^^^^
    553 b775ea4b - self.assertFalse(exposure2.getMetadata().exists("AR_ID"))
    535 c605dfcd + self.assertFalse(exposure2.getMetadata().exists("AR_ID"))
    ? ++++
    554 b775ea4b - self.assertFalse(exposure2.getMetadata().exists("PSF_ID"))
    536 c605dfcd + self.assertFalse(exposure2.getMetadata().exists("PSF_ID"))
    ? ++++
    555 b775ea4b - self.assertFalse(exposure2.getMetadata().exists("WCS_ID"))
    537 c605dfcd + self.assertFalse(exposure2.getMetadata().exists("WCS_ID"))
    ? ++++
    556 b775ea4b - os.remove(filename)
    def testTicket2861(self):
    559 f7227ff2 - filename = "testTicket2861.fits"
    540 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    560 f7227ff2 - exposure1 = afwImage.ExposureF(100, 100, self.wcs)
    541 c605dfcd + exposure1 = afwImage.ExposureF(100, 100, self.wcs)
    ? ++++
    561 f7227ff2 - exposure1.setPsf(self.psf)
    542 c605dfcd + exposure1.setPsf(self.psf)
    ? ++++
    562 f7227ff2 - schema = afwTable.ExposureTable.makeMinimalSchema()
    543 c605dfcd + schema = afwTable.ExposureTable.makeMinimalSchema()
    ? ++++
    563 f7227ff2 - coaddInputs = afwImage.CoaddInputs(schema, schema)
    544 c605dfcd + coaddInputs = afwImage.CoaddInputs(schema, schema)
    ? ++++
    564 f7227ff2 - exposure1.getInfo().setCoaddInputs(coaddInputs)
    545 c605dfcd + exposure1.getInfo().setCoaddInputs(coaddInputs)
    ? ++++
    565 f7227ff2 - exposure2 = afwImage.ExposureF(exposure1, True)
    546 c605dfcd + exposure2 = afwImage.ExposureF(exposure1, True)
    ? ++++
    566 f7227ff2 - self.assertIsNotNone(exposure2.getInfo().getCoaddInputs())
    547 c605dfcd + self.assertIsNotNone(exposure2.getInfo().getCoaddInputs())
    ? ++++
    567 f7227ff2 - exposure2.writeFits(filename)
    ? ^ ----
    548 c605dfcd + exposure2.writeFits(tmpFile)
    ? ++++ ^^^^
    568 f7227ff2 - exposure3 = afwImage.ExposureF(filename)
    ? ^ ----
    549 c605dfcd + exposure3 = afwImage.ExposureF(tmpFile)
    ? ++++ ^^^^
    569 f7227ff2 - self.assertIsNotNone(exposure3.getInfo().getCoaddInputs())
    550 c605dfcd + self.assertIsNotNone(exposure3.getInfo().getCoaddInputs())
    ? ++++
    570 f7227ff2 - os.remove(filename)
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """ Returns a suite containing all the test cases in this module. """ utilsTests.init() suites = [] suites += unittest.makeSuite(ExposureTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    96b804a8

    commit 96b804a8d909e5398156b9cb9876aee57f3bd662
    Author: Jim Bosch 
    Date:   Tue Mar 19 13:50:56 2013 -0400
    
        Move KernelPsf, DoubleGaussianPsf, WarpedPsf, and associated tests to meas_algorithms.
        
        We now use DummyPsf from testTableArchivesLib instead for Exposure and
        ExposureTable tests (which works better anyway), and this will let us use
        shape and aperture algorithms in meas_algorithms in the implementation.
    

    18d5e213

    commit 18d5e213c7bc81d057e35f0ba9ceba05917e8ee9
    Author: rhl 
    Date:   Wed Apr 7 00:46:43 2010 +0000
    
        Add Detector to Exposure
    

    a6d8990e

    commit a6d8990e1384850d9c47ca82d9adaec4878e4c05
    Author: rhl 
    Date:   Thu May 20 14:53:13 2010 +0000
    
        Added a Calib object, used in an Exposure
    

    7c299b58

    commit 7c299b582d0255aa84b4e8f11a9417ce168eac6f
    Author: Jim Bosch 
    Date:   Mon Mar 4 16:28:02 2013 -0500
    
        Unit test for INHERIT-awareness in readMetadata.
    

    98bb0015

    commit 98bb001577cfc1ad914f502ed4f72b30ce77e4b3
    Author: rhl 
    Date:   Fri Apr 9 14:57:34 2010 +0000
    
        Check that Detectors are properly copied, and that we can write their Ids ti FITS
    

    4ab68235

    commit 4ab682357b7f138c0d309a4fb59e99c6efb01457
    Author: rhl 
    Date:   Fri Apr 9 18:26:10 2010 +0000
    
        Added a generalised copy constructor to Exposure
    

    b5f3475b

    commit b5f3475ba49a88c2d499d4b138d4bc8232134ed3
    Author: rhl 
    Date:   Fri Apr 29 13:52:15 2011 +0000
    
        Reinstated the (width, height) form of Image etc. constructors (#1652).  Added Exposure(Exposure, deep).  Adjusted copying/creating of Exposure._psf
    

    4f859dd5

    commit 4f859dd5ad7dd3301410833d48076da3d552a387
    Author: Jim Bosch 
    Date:   Mon Dec 17 17:13:45 2012 -0500
    
        ExposureInfo now saves Psf and Wcs.
    

    d8f669a5

    commit d8f669a5503270256a607ae1f99be80e89faa898
    Author: fergal 
    Date:   Wed Mar 24 17:44:31 2010 +0000
    
        Updated tests for the new API in Wcs and TanWcs that accepts and returns Coord objects (as appropriate)
    

    ded0eb52

    commit ded0eb52af9b4e28790afe94d115c1d8699fa271
    Author: Jim Bosch 
    Date:   Tue Nov 20 00:46:52 2012 -0500
    
        Overhaul FITS persistence for MaskedImage and Exposure: no more appending or passing HDU to read, no more multi-file support, but we put metadata in primary HDU and use INHERIT keyword (as per discussion on lsst-data list).
    

    4cbc7441

    commit 4cbc74414035a0143bfe0d59334ea3bf54efd131
    Author: Russell Owen 
    Date:   Sat Feb 2 16:24:58 2013 -0600
    
        Add a unit test that shows the problem (I also switched from Factory to clone for another test).
    

    adb78502

    commit adb7850213df954a184cdcf53ee2b778e5d8699c
    Author: Jim Bosch 
    Date:   Mon Nov 19 13:43:47 2012 -0500
    
        Make afw::fits exceptions visible in Python.
    

    b775ea4b

    commit b775ea4b20e08b8b53226d53218c32e207238cb9
    Author: Jim Bosch 
    Date:   Fri May 3 21:09:05 2013 -0500
    
        Strip archive keywords when reading exposures from FITS
    

    23962509

    commit 23962509bbef6c17daff384b46b511d3f50e8bb8
    Author: Russell Owen 
    Date:   Mon Jan 21 08:41:30 2013 -0800
    
        Remove trailing whitespace from exposure unit test
    

    48b7a605

    commit 48b7a60513243b5a9f2d182d960d9ef5ae93bb9a
    Author: rowen 
    Date:   Fri Mar 20 04:43:23 2009 +0000
    
        Fixed tests/Exposure_1.py
    

    54c68ba0

    commit 54c68ba064418bfa7f404c80c2fc5eff738c9f65
    Author: Russell Owen 
    Date:   Tue Jan 22 15:57:24 2013 -0800
    
        Add unit test for exposuredeep copy of with bbox for metadata
    

    f7227ff2

    commit f7227ff2c564e69cc64edb92c8d71c9f1d76e7fa
    Author: Jim Bosch 
    Date:   Fri May 3 22:04:12 2013 -0500
    
        Add test to ensure #2861 is fixed
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    f3d3029c

    commit f3d3029c561b957069cbf280b62ea8e37447c068
    Author: Paul Price 
    Date:   Mon Apr 27 18:09:36 2015 -0400
    
        Calib: add operator*= for scaling zeropoint
    

    df5b9909

    commit df5b9909720b5d4fd1a8b527b188f704594a4170
    Author: rhl 
    Date:   Mon Jul 12 19:19:22 2010 +0000
    
        Add a Psf to an Exposure (#645)
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    61855404

    commit 618554041c03d30fe370e2c3e69c0fb394c93ccb
    Author: nms 
    Date:   Tue Oct 9 00:00:09 2007 +0000
    
        Merged Exposure class code (.cc/.h and exposure.i) to trunk (from Ticket 167).
        Merged modifications made in Ticket 167 to MaskedImage, Kernel, and WCS class code.
        Added and merged final modifications to Exposure, WCS and Kernel class test code
          (associated examples/*.cc & tests/*.py files)
        Deleted all test images from tests/data.
        Added small_MI_corrupt_img.fits to tests/data for temporary storage of a test file used
        in both the WCS and Exposure test suites.
    

    Commits in /Users/nate/repos_lsst/afw/

    eea3eb4a

    commit eea3eb4aaa72e0956cce3c5a4bb2c78863540dd3
    Author: Russell Owen 
    Date:   Thu Sep 18 17:23:09 2014 -0700
    
        Respond to review by restoring LOCAL where appropriate.
        Also enhanced documentation in detection.py
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    83333880

    commit 83333880b73a52772e68efbcbf5ff3ac871820a0
    Author: Russell Owen 
    Date:   Fri Feb 14 13:22:57 2014 -0800
    
        Fixed exposure and color unit tests. That just leaves two failing tests
        which will be replaced or rewritten once the functionality is available.
    

    Return to list

    src/detection/PsfFormatter.cc

    Diff:

                    // -*- LSST-C++ -*-
                    /** \file
                     * \brief Implementation of PsfFormatter class
                     *
                     * \version $Revision: 2151 $
                     * \date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * \ingroup afw
                     */
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/serialization/nvp.hpp"
                    
                    #include "lsst/afw/detection/PsfFormatter.h"
                    #include "lsst/afw/detection/Psf.h"
                    #include "lsst/daf/persistence/FormatterImpl.h"
                    #include "lsst/daf/persistence/LogicalLocation.h"
                    #include "lsst/daf/persistence/BoostStorage.h"
                    #include "lsst/daf/persistence/XmlStorage.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/pex/policy/Policy.h"
                    
                    BOOST_CLASS_EXPORT(lsst::afw::detection::Psf)
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.detection.PsfFormatter", level, s);
                    }
                    
                    namespace afwDetect = lsst::afw::detection;
                    namespace afwMath = lsst::afw::math;
                    namespace dafBase = lsst::daf::base;
                    namespace dafPersist = lsst::daf::persistence;
                    namespace pexPolicy = lsst::pex::policy;
                    
                    using boost::serialization::make_nvp;
                    
                    /** Register this Formatter subclass through a static instance of
                     * FormatterRegistration.
                     */
                    dafPersist::FormatterRegistration
                    afwDetect::PsfFormatter::registration("Psf", typeid(afwDetect::Psf), createInstance);
                    
                    /** Constructor.
                     * \param[in] policy Policy for configuring this Formatter
                     */
                    afwDetect::PsfFormatter::PsfFormatter(
                        pexPolicy::Policy::Ptr policy) :
                        dafPersist::Formatter(typeid(this)), _policy(policy) {}
                    
                    /** Minimal destructor.
                     */
                    afwDetect::PsfFormatter::~PsfFormatter(void) {}
                    
                    void afwDetect::PsfFormatter::write(
                        dafBase::Persistable const* persistable,
                        dafPersist::Storage::Ptr storage,
                        dafBase::PropertySet::Ptr) {
                        execTrace("PsfFormatter write start");
                        afwDetect::Psf const* ps = dynamic_cast(persistable);
                        if (ps == 0) {
    
    67 721f604a - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Persisting non-Psf");
    ? ---------
    67 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Persisting non-Psf");
    } if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { execTrace("PsfFormatter write BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & ps; execTrace("PsfFormatter write end"); return; } else if (typeid(*storage) == typeid(dafPersist::XmlStorage)) { execTrace("PsfFormatter write XmlStorage"); dafPersist::XmlStorage* xml = dynamic_cast(storage.get()); xml->getOArchive() & make_nvp("psf", ps); execTrace("PsfFormatter write end"); return; }
    85 721f604a - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Psf");
    ? ---------
    85 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Psf");
    } dafBase::Persistable* afwDetect::PsfFormatter::read( dafPersist::Storage::Ptr storage, dafBase::PropertySet::Ptr) { execTrace("PsfFormatter read start"); afwDetect::Psf* ps; if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { execTrace("PsfFormatter read BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getIArchive() & ps; execTrace("PsfFormatter read end"); return ps; } else if (typeid(*storage) == typeid(dafPersist::XmlStorage)) { execTrace("PsfFormatter read XmlStorage"); dafPersist::XmlStorage* xml = dynamic_cast(storage.get()); xml->getIArchive() & make_nvp("psf", ps); execTrace("PsfFormatter read end"); return ps; }
    108 721f604a - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Psf");
    ? ---------
    108 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Psf");
    } void afwDetect::PsfFormatter::update(dafBase::Persistable* , dafPersist::Storage::Ptr, dafBase::PropertySet::Ptr) {
    114 721f604a - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unexpected call to update for Psf");
    ? ---------
    114 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unexpected call to update for Psf");
    } /** Serialize a Psf to a Boost archive. Handles text or XML * archives, input or output. */ template void afwDetect::PsfFormatter::delegateSerialize( Archive& ar, ///< Boost archive unsigned int const, ///< Version of the Psf class dafBase::Persistable* persistable ///< persistable Pointer to the Psf as a Persistable ) { execTrace("PsfFormatter delegateSerialize start"); afwDetect::Psf* ps = dynamic_cast(persistable); if (ps == 0) {
    129 721f604a - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Serializing non-Psf");
    ? ---------
    129 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Serializing non-Psf");
    } #if 0 // not present in baseclass ar & make_nvp("width", ps->_width) & make_nvp("height", ps->_height); ar & make_nvp("k", ps->_kernel); #endif execTrace("PsfFormatter delegateSerialize end"); } /** Factory method for PsfFormatter. * \param[in] policy Policy for configuring the PsfFormatter * \return Shared pointer to a new instance */ dafPersist::Formatter::Ptr afwDetect::PsfFormatter::createInstance( pexPolicy::Policy::Ptr policy) { return dafPersist::Formatter::Ptr(new afwDetect::PsfFormatter(policy)); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    721f604a

    commit 721f604a42baeb6fe8b4699d483ac54eeea41683
    Author: rhl 
    Date:   Fri Mar 26 17:34:30 2010 +0000
    
        Home for non-public details
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/display/displayLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define displayLib_DOCSTRING
                    "
                    Basic routines to talk to ds9
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.display", docstring=displayLib_DOCSTRING) displayLib
                    
                    %{
                    #   include "lsst/daf/base.h"
                    #   include "lsst/daf/persistence.h"
                    #   include "lsst/pex/policy.h"
                    #   include "lsst/pex/logging.h"
                    #   include "lsst/afw/geom.h"
                    #   include "lsst/afw/cameraGeom.h"
                    #   include "lsst/afw/image.h"
                    
                    #   include "simpleFits.h"
                    #   include "Rgb.h"
                    %}
                    
                    %include "lsst/p_lsstSwig.i"
                    
                    %import "lsst/afw/image/imageLib.i"
                    
                    %lsst_exceptions();
                    
                    %include "simpleFits.h"
                    
                    %template(writeFitsImage) lsst::afw::display::writeBasicFits >;
    
    56 b5bc9db1 + %template(writeFitsImage) lsst::afw::display::writeBasicFits >;
    %template(writeFitsImage) lsst::afw::display::writeBasicFits >; %template(writeFitsImage) lsst::afw::display::writeBasicFits >; %template(writeFitsImage) lsst::afw::display::writeBasicFits >; %template(writeFitsImage) lsst::afw::display::writeBasicFits >; %include "Rgb.h" %template(replaceSaturatedPixels) lsst::afw::display::replaceSaturatedPixels >;
    65 f49676d7 -
    66 f49676d7 - %template(getZScale) lsst::afw::display::getZScale;
    67 f49676d7 - %template(getZScale) lsst::afw::display::getZScale;

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f49676d7

    commit f49676d7f1348f9de8ca21ee633e0c25473251ae
    Author: Robert Lupton the Good 
    Date:   Sun Apr 19 10:50:17 2015 -0300
    
        Implemented Linear and ZScale transformations, HSC-1206
        
        Linear was already available with Q=0, but this way is clearer; the default is to use min/max limits.
        
        I also added AsinhZScaleMapping which uses the zscale code to set the stretch.
        
        I did not port the log mappings, as the C++ is not really something I'd like to see in the long-term stack (e.g. reinterpret_casts between ints and doubles).
        It would be easy to add a LogMapper in pure python, and if this is needed please open a new issue.
        
        The ZScale code comes from Mineo-san's fitsthumb, but doesn't give quite the same upper limit as ds9.  I'm not sure where the discrepancy is, but I don't think it matters.
    

    Commits in /Users/nate/repos_lsst/afw/

    b5bc9db1

    commit b5bc9db1610c30b8c0d675545af40c3991525aed
    Author: John Swinbank 
    Date:   Tue Nov 18 09:50:36 2014 -0600
    
        Enable writeFitsImage for uint64_t
    

    Return to list

    tests/angle.py

    Diff:

    1 35153a16 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Angle Run with: angle.py or python >>> import angle; angle.run() """ import math, os, sys import unittest import numpy import lsst.utils.tests as tests import lsst.afw.geom as afwGeom #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class AngleTestCase(unittest.TestCase): """A test case for Angle""" def setUp(self): self.pi = afwGeom.Angle(math.pi, afwGeom.radians) self.d = 180*afwGeom.degrees def tearDown(self): pass def testCtor(self): self.assertEqual(self.pi, math.pi) self.assertEqual(self.pi, afwGeom.Angle(math.pi)) self.assertEqual(self.pi, self.d) dd = afwGeom.Angle(180, afwGeom.degrees) self.assertEqual(self.d, dd) dd = afwGeom.Angle(60*180, afwGeom.arcminutes) self.assertEqual(self.d, dd) dd = afwGeom.Angle(60*60*180, afwGeom.arcseconds) self.assertEqual(self.d, dd) def testArithmetic(self): self.assertTrue(afwGeom.isAngle(self.pi)) self.assertFalse(afwGeom.isAngle(self.pi.asRadians())) self.assertFalse(afwGeom.isAngle(math.pi)) def tst(): self.pi - math.pi # subtracting a float from an Angle self.assertRaises(TypeError, tst) self.assertEqual(self.pi - math.pi*afwGeom.radians, 0) # OK with units specified self.assertEqual(self.pi - self.d, 0) # can subtract Angles def tst(): self.pi + math.pi # adding a float to an Angle self.assertRaises(TypeError, tst) def tst(): self.pi*afwGeom.degrees # self.pi is already an Angle self.assertRaises(NotImplementedError, tst) self.assertEqual((self.pi + self.d).asAngularUnits(afwGeom.degrees), 360) self.assertEqual((self.pi).asRadians(), math.pi) self.assertEqual((self.pi/2).asDegrees(), 90) self.assertEqual((self.pi*2).asArcminutes(), 360*60) self.assertEqual((self.pi*2).asArcseconds(), 360*60*60) self.assertEqual(math.sin(self.pi/2), 1.0) # automatic conversion to double def testAbs(self): self.assertEqual(abs(0.0*afwGeom.degrees - self.pi), self.pi) def testPi(self): self.assertEqual(afwGeom.PI, math.pi) def testComparison(self): a2 = 2.0 * afwGeom.arcseconds a1 = 0.5 * afwGeom.arcseconds a3 = 0.5 * afwGeom.arcseconds print 'a1', a1 print 'a2', a2 print 'a3', a3 self.assertEqual(a1 == a3, True) self.assertEqual(a1 != a2, True) self.assertEqual(a1 <= a2, True) self.assertEqual(a1 < a2, True) self.assertEqual(a2 > a1, True) self.assertEqual(a2 >= a1, True) self.assertEqual(a1 != a3, False) self.assertEqual(a1 == a2, False) self.assertEqual(a1 >= a2, False) self.assertEqual(a1 > a2, False) self.assertEqual(a2 < a1, False) self.assertEqual(a2 <= a1, False) self.assertEqual(a1 == None, False) self.assertEqual(None == a1, False) self.assertEqual(a1 != None, True) self.assertEqual(None != a1, True) self.assertEqual(a1 == float(a1), True) self.assertEqual(float(a1) == a1, True) def testTrig(self): self.assertEqual(math.cos(self.d), -1.0) self.assertAlmostEqual(math.sin(self.d), 0.0, places=15) thirty = 30.*afwGeom.degrees self.assertAlmostEqual(math.sin(thirty), 0.5, places=15) def testWrap(self): eps = numpy.finfo(float).eps oneEightyWithSlop = 180 * (1 + eps) self.assertNotEqual(1 + eps, eps) for wrap in (-1000, -10, -1, 0, 1, 10, 1000): for offset in (-2*math.pi, -math.pi, -math.pi*0.5, 0.0, math.pi*0.5, math.pi*0.75, math.pi, math.pi*2.0): for epsMult in (-3, -2, -1, 0, 1, 2, 3): angRad = (offset + (wrap * math.pi)) * (1 + (eps * epsMult)) ang = angRad * afwGeom.radians angDeg = ang.asDegrees() sinAng = math.sin(angRad) cosAng = math.cos(angRad) posAng = angRad * afwGeom.radians posAng.wrap() posAngRad = posAng.asRadians() posAngDeg = posAng.asDegrees() posAngArcmin = posAng.asArcminutes() posAngArcsec = posAng.asArcseconds() # the code promises 0 <= posAng for all units self.assertGreaterEqual(posAngRad, 0) self.assertGreaterEqual(posAngDeg, 0) self.assertGreaterEqual(posAngArcmin, 0) self.assertGreaterEqual(posAngArcsec, 0) # wrap promises posAng < 2*pi only for radians, but it seems to work for all units self.assertLess(posAngRad, 2*math.pi) self.assertLess(posAngDeg, 360) self.assertLess(posAngArcmin, 360 * 60) self.assertLess(posAngArcsec, 360 * 3600) # prove that posAngDeg and angDeg are the same angle posErrAng = (posAngDeg - angDeg) * afwGeom.degrees posErrAng.wrapCtr() self.assertAlmostEqual(posErrAng.asDegrees(), 0) # a sanity check in case wrapCtr gives the wrong answer self.assertAlmostEqual(math.sin(posAngRad), sinAng) self.assertAlmostEqual(math.cos(posAngRad), cosAng) ctrAng = angRad * afwGeom.radians ctrAng.wrapCtr() ctrAngRad = ctrAng.asRadians() ctrAngDeg = ctrAng.asDegrees() ctrAngArcmin = ctrAng.asArcminutes() ctrAngArcsec = ctrAng.asArcseconds() # wrapCtr promises -pi <= ctrAngRad < pi only for radians, # but it seems to work for all units self.assertGreaterEqual(ctrAngRad, -math.pi) self.assertGreaterEqual(ctrAngDeg, -180) self.assertGreaterEqual(ctrAngArcmin, -180 * 60) self.assertGreaterEqual(ctrAngArcsec, -180 * 3600) self.assertLess(ctrAngRad, math.pi) self.assertLess(ctrAngDeg, 180) self.assertLess(ctrAngArcmin, 180 * 60) self.assertLess(ctrAngArcsec, 180 * 3600) # prove that ctrAngDeg and ang are the same angle ctrErrAng = (ctrAngDeg - angDeg) * afwGeom.degrees ctrErrAng.wrapCtr() self.assertAlmostEqual(ctrErrAng.asDegrees(), 0) self.assertAlmostEqual(math.sin(ctrAngRad), sinAng) self.assertAlmostEqual(math.cos(ctrAngRad), cosAng) for refAngBase in (-math.pi, 0.0, math.pi, math.pi*2.0): for refEpsMult in (-3, -2, -1, 0, 1, 2, 3): refAngRad = refAngBase * (1 + (eps * refEpsMult)) refAng = refAngRad * afwGeom.radians refAngDeg = refAng.asDegrees() refAngArcmin = refAng.asArcminutes() refAngArcsec = refAng.asArcseconds() nearAng = angRad * afwGeom.radians nearAng.wrapNear(refAng) nearAngRad = nearAng.asRadians() nearAngDeg = nearAng.asDegrees() nearAngArcmin = nearAng.asArcminutes() nearAngArcsec = nearAng.asArcseconds() # wrapNear promises nearAngRad - refAngRad >= -pi for radians # but has known failures due to roundoff error for other units self.assertGreaterEqual(nearAngRad - refAngRad, -math.pi) self.assertGreaterEqual(nearAngDeg - refAngDeg, -oneEightyWithSlop) self.assertGreaterEqual(nearAngArcmin - refAngArcmin, - oneEightyWithSlop * 60) self.assertGreaterEqual(nearAngArcsec - refAngArcsec, -oneEightyWithSlop * 3600) # wrapNear promises nearAngRad - refAngRad < pi for radians # but has known failures due to roundoff error for other units self.assertLess(nearAngRad - refAngRad, math.pi) self.assertLess(nearAngDeg - refAngDeg, oneEightyWithSlop) self.assertLess(nearAngArcmin - refAngArcmin, oneEightyWithSlop * 60) self.assertLess(nearAngArcsec - refAngArcsec, oneEightyWithSlop * 3600) # prove that nearAng and ang are the same angle nearErrAng = (nearAngRad - angRad) * afwGeom.radians nearErrAng.wrapCtr() self.assertAlmostEqual(nearErrAng.asRadians(), 0) self.assertAlmostEqual(math.sin(nearAngRad), sinAng) self.assertAlmostEqual(math.cos(nearAngRad), cosAng) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" tests.init() suites = [] suites += unittest.makeSuite(AngleTestCase) suites += unittest.makeSuite(tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    35153a16

    commit 35153a16adf59642b70caa1eba565dca9eb9e4a6
    Author: rhl 
    Date:   Tue May 3 16:43:30 2011 +0000
    
        Added Angle class from hg; #1663
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    include/lsst/afw/table/detail/Access.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_DETAIL_Access_h_INCLUDED
                    #define AFW_TABLE_DETAIL_Access_h_INCLUDED
                    
                    #include 
                    
                    #include "ndarray/Manager.h"
                    #include "lsst/afw/table/FieldBase.h"
                    #include "lsst/afw/table/Schema.h"
                    #include "lsst/afw/table/detail/SchemaImpl.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    class BaseRecord;
                    class BaseTable;
                    
                    namespace detail {
                    
                    /**
                     *  @internal
                     *
                     *  @brief Friendship-aggregation class for afw/table.
                     *
                     *  Access is a collection of static member functions that provide access to internals of other
                     *  classes.  It allows many classes to just declare Access as a friend rather than a long list of
                     *  related classes.  This is less secure, but it's obviously not part of the public interface,
                     *  and that's good enough.
                     */
                    class Access {
                    public:
                    
                        /// @internal @brief Return a sub-field key corresponding to the nth element.
                        template 
                        static Key::Element> extractElement(KeyBase const & kb, int n) {
                            if (!static_cast const &>(kb).isValid()) {
                                throw LSST_EXCEPT(
    
    37 d01f3a63 - pex::exceptions::LogicErrorException,
    ? ---------
    37 21597d88 + pex::exceptions::LogicError,
    (boost::format("Cannot extract subfield key from invalid key of type '%s' " "(most often this is caused by failing to setup centroid or shape slots)") % Key::getTypeString()).str() ); } return Key::Element>( static_cast const &>(kb).getOffset() + n * sizeof(typename Key::Element) ); } /// @internal @brief Return a sub-field key corresponding to a range template static Key< Array > extractRange(KeyBase< Array > const & kb, int begin, int end) { if (!static_cast > const &>(kb).isValid()) { throw LSST_EXCEPT(
    53 7ebf031f - pex::exceptions::LogicErrorException,
    ? ---------
    53 21597d88 + pex::exceptions::LogicError,
    (boost::format("Cannot extract subfield key from invalid key of type '%s' ") % Key::getTypeString()).str() ); } return Key< Array >( static_cast > const &>(kb).getOffset() + begin * sizeof(typename Key::Element), end - begin );
    62 7ebf031f + }
    63 7ebf031f +
    64 9a205e3c + /// @internal @brief Access to the private Key constructor.
    65 5dee136a + template
    66 f9fa5877 + static Key makeKey(int offset) {
    67 f9fa5877 + return Key(offset);
    } /// @internal @brief Access to the private Key constructor. template static Key makeKey(Field const & field, int offset) { return Key(offset, field); } /// @internal @brief Access to the private Key constructor. static Key makeKey(int offset, int bit) { return Key(offset, bit); } /// @internal @brief Add some padding to a schema without adding a field. static void padSchema(Schema & schema, int bytes) { schema._edit(); schema._impl->_recordSize += bytes; } }; }}}} // namespace lsst::afw::table::detail #endif // !AFW_TABLE_DETAIL_Access_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d01f3a63

    commit d01f3a63feaa9523c38ace7eefa66026e7b08d6b
    Author: Jim Bosch 
    Date:   Wed Jun 13 17:13:25 2012 -0400
    
        Throw exceptions instead of asserting in Python-accessible code.
    

    7ebf031f

    commit 7ebf031f548246fc086a89cc8038a8350d5f85d8
    Author: Jim Bosch 
    Date:   Mon Jan 13 12:40:09 2014 -0500
    
        Add support for slicing table Array Keys (#3103)
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    9a205e3c

    commit 9a205e3c73d9b0a8471ec0cd71f8e9656bd5f39d
    Author: Jim Bosch 
    Date:   Fri Feb 3 22:53:58 2012 -0500
    
        working on internals documentation
    

    5dee136a

    commit 5dee136a9f602af873bc62bd6c6efb36e7aeb0d6
    Author: Jim Bosch 
    Date:   Sun Nov 20 01:21:52 2011 -0500
    
        removed per-field null bits
    

    f9fa5877

    commit f9fa5877d27976c5bbec22173b33e1337aa420fa
    Author: Jim Bosch 
    Date:   Thu Sep 18 17:21:34 2014 -0400
    
        Add FunctorKey for arrays
    

    7ebf031f

    commit 7ebf031f548246fc086a89cc8038a8350d5f85d8
    Author: Jim Bosch 
    Date:   Mon Jan 13 12:40:09 2014 -0500
    
        Add support for slicing table Array Keys (#3103)
    

    Return to list

    src/image/MaskedImage.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * \file
                     * \brief Implementation for MaskedImage
                     */
                    #include 
                    #include 
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/lambda/lambda.hpp"
                    #pragma clang diagnostic pop
                    #include "boost/regex.hpp"
                    #include "boost/filesystem/path.hpp"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/pex/exceptions.h"
                    #include "boost/algorithm/string/trim.hpp"
                    
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/image/fits/fits_io.h"
                    #include "lsst/afw/fits.h"
                    
                    namespace bl = boost::lambda;
                    namespace image = lsst::afw::image;
                    
                    /** Constructors
                     *
                     * \brief Construct from a supplied dimensions. The Image, Mask, and Variance will be set to zero
                     */
                    template
                    image::MaskedImage::MaskedImage(
                        unsigned int width, ///< number of columns
                        unsigned int height, ///< number of rows
                        MaskPlaneDict const& planeDict  //!< Make Mask conform to this mask layout (ignore if empty)
                    ) :
                        lsst::daf::base::Citizen(typeid(this)),
                        _image(new Image(width, height)),
                        _mask(new Mask(width, height, planeDict)),
                        _variance(new Variance(width, height)) {
                        *_image = 0;
                        *_mask = 0x0;
                        *_variance = 0;
                    }
                    
                    /** Constructors
                     *
                     * \brief Construct from a supplied dimensions. The Image, Mask, and Variance will be set to zero
                     */
                    template
                    image::MaskedImage::MaskedImage(
                        geom::Extent2I const & dimensions, //!< Number of columns, rows in image
                        MaskPlaneDict const& planeDict  //!< Make Mask conform to this mask layout (ignore if empty)
                    ) :
                        lsst::daf::base::Citizen(typeid(this)),
                        _image(new Image(dimensions)),
                        _mask(new Mask(dimensions, planeDict)),
                        _variance(new Variance(dimensions)) {
                        *_image = 0;
                        *_mask = 0x0;
                        *_variance = 0;
                    }
                    
                    /**
                     * Create an MaskedImage of the specified size
                     *
                     * The Image, Mask, and Variance will be set to zero
                     *
                     * \note Many lsst::afw::image and lsst::afw::math objects define a \c dimensions member
                     * which may be conveniently used to make objects of an appropriate size
                     */
                    template
                    image::MaskedImage::MaskedImage(
                        geom::Box2I const & bbox, //!< dimensions of image: width x height
                        MaskPlaneDict const& planeDict  //!< Make Mask conform to this mask layout (ignore if empty)
                    ) :
                        lsst::daf::base::Citizen(typeid(this)),
                        _image(new Image(bbox)),
                        _mask(new Mask(bbox, planeDict)),
                        _variance(new Variance(bbox)) {
                        *_image = 0;
                        *_mask = 0x0;
                        *_variance = 0;
                    }
                    
                    template
                    image::MaskedImage::MaskedImage(
                        std::string const & fileName, PTR(daf::base::PropertySet) metadata,
                        geom::Box2I const & bbox, ImageOrigin origin, bool conformMasks, bool needAllHdus,
                        PTR(daf::base::PropertySet) imageMetadata,
                        PTR(daf::base::PropertySet) maskMetadata,
                        PTR(daf::base::PropertySet) varianceMetadata
                    ) : lsst::daf::base::Citizen(typeid(this)),
                        _image(), _mask(), _variance() 
                    {
                        fits::Fits fitsfile(fileName, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
                        *this = MaskedImage(fitsfile, metadata, bbox, origin, conformMasks, needAllHdus,
                                            imageMetadata, maskMetadata, varianceMetadata);
                     }
                    
                    template
                    image::MaskedImage::MaskedImage(
                        fits::MemFileManager & manager, PTR(daf::base::PropertySet) metadata,
                        geom::Box2I const & bbox, ImageOrigin origin, bool conformMasks, bool needAllHdus,
                        PTR(daf::base::PropertySet) imageMetadata,
                        PTR(daf::base::PropertySet) maskMetadata,
                        PTR(daf::base::PropertySet) varianceMetadata
                    ) : lsst::daf::base::Citizen(typeid(this)),
                        _image(), _mask(), _variance() 
                    {
                        fits::Fits fitsfile(manager, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK);
                        *this = MaskedImage(fitsfile, metadata, bbox, origin, conformMasks, needAllHdus,
                                            imageMetadata, maskMetadata, varianceMetadata);
                    }
                    
                    namespace {
                    
                    // Helper functions for MaskedImage FITS ctor.
                    
                    void checkExtType(
                        lsst::afw::fits::Fits & fitsfile,
                        PTR(lsst::daf::base::PropertySet) metadata,
                        std::string const & expected
                    ) {
                        try {
                            std::string exttype = boost::algorithm::trim_right_copy(metadata->getAsString("EXTTYPE"));
                            if (exttype != "" && exttype != expected) {
    
    149 ded0eb52 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    149 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Reading %s (hdu %d) Expected EXTTYPE==\"%s\", saw \"%s\"") % expected % fitsfile.getFileName() % fitsfile.getHdu() % exttype).str()); } metadata->remove("EXTTYPE");
    154 504cf02b - } catch (lsst::pex::exceptions::NotFoundException) {}
    ? - ^^^^^^ ^
    154 21597d88 + } catch(lsst::pex::exceptions::NotFoundError) {}
    ? ^^ ^
    155 504cf02b - try {
    156 504cf02b - metadata->remove("EXTNAME");
    157 504cf02b - } catch (lsst::pex::exceptions::NotFoundException) {}
    } void ensureMetadata(PTR(lsst::daf::base::PropertySet) & metadata) { if (!metadata) { metadata.reset(new lsst::daf::base::PropertyList()); } } } // anonymous template image::MaskedImage::MaskedImage( fits::Fits & fitsfile, PTR(daf::base::PropertySet) metadata, geom::Box2I const & bbox, ImageOrigin origin, bool conformMasks, bool needAllHdus, PTR(daf::base::PropertySet) imageMetadata, PTR(daf::base::PropertySet) maskMetadata, PTR(daf::base::PropertySet) varianceMetadata ) : lsst::daf::base::Citizen(typeid(this)), _image(), _mask(), _variance() { if (metadata) { // Read primary metadata - only if user asks for it. // If the primary HDU is not empty, this may be the same as imageMetadata. fitsfile.setHdu(1); fitsfile.readMetadata(*metadata); } fitsfile.setHdu(0); // this moves to the first non-empty HDU, which should always be the Image HDU. int hdu = fitsfile.getHdu(); ensureMetadata(imageMetadata); _image.reset(new Image(fitsfile, imageMetadata, bbox, origin)); checkExtType(fitsfile, imageMetadata, "IMAGE"); try { fitsfile.setHdu(++hdu); ensureMetadata(maskMetadata); _mask.reset(new Mask(fitsfile, maskMetadata, bbox, origin, conformMasks)); checkExtType(fitsfile, maskMetadata, "MASK"); } catch(fits::FitsError &e) { if (needAllHdus) { LSST_EXCEPT_ADD(e, "Reading Mask"); throw e; }
    203 42dadff6 - _mask.reset(new Mask(_image->getBBox(PARENT)));
    ? ------
    200 93994d54 + _mask.reset(new Mask(_image->getBBox()));
    } try { fitsfile.setHdu(++hdu); ensureMetadata(varianceMetadata); _variance.reset(new Variance(fitsfile, varianceMetadata, bbox, origin)); checkExtType(fitsfile, varianceMetadata, "VARIANCE"); } catch(fits::FitsError &e) { if (needAllHdus) { LSST_EXCEPT_ADD(e, "Reading Variance"); throw e; }
    216 42dadff6 - _variance.reset(new Variance(_image->getBBox(PARENT)));
    ? ------
    213 93994d54 + _variance.reset(new Variance(_image->getBBox()));
    } } /** * \brief Construct from a supplied Image and optional Mask and Variance. * The Mask and Variance will be set to zero if omitted */ template image::MaskedImage::MaskedImage( ImagePtr image, ///< %Image MaskPtr mask, ///< %Mask VariancePtr variance ///< Variance %Mask ) : lsst::daf::base::Citizen(typeid(this)), _image(image), _mask(mask), _variance(variance) { conformSizes(); } /** * \brief Copy constructor; shallow, unless deep is true. */ template image::MaskedImage::MaskedImage( MaskedImage const& rhs, ///< %Image to copy bool deep ///< Make deep copy? ) : lsst::daf::base::Citizen(typeid(this)), _image(rhs._image), _mask(rhs._mask), _variance(rhs._variance) { if (deep) { _image = typename Image::Ptr(new Image(*rhs.getImage(), deep)); _mask = typename Mask::Ptr(new Mask(*rhs.getMask(), deep)); _variance = typename Variance::Ptr(new Variance(*rhs.getVariance(), deep)); } conformSizes(); } /** * \brief Copy constructor of the pixels specified by bbox; shallow, unless deep is true. */ template image::MaskedImage::MaskedImage( MaskedImage const& rhs, ///< MaskedImage to copy const geom::Box2I& bbox, ///< Specify desired region ImageOrigin const origin, ///< Specify the coordinate system of the bbox bool deep ///< If false, new ImageBase shares storage with rhs; ///< if true make a new, standalone, MaskedImage ) : lsst::daf::base::Citizen(typeid(this)), _image(new Image(*rhs.getImage(), bbox, origin, deep)), _mask(rhs._mask ? new Mask(*rhs.getMask(), bbox, origin, deep) : static_cast(NULL)), _variance(rhs._variance ? new Variance(*rhs.getVariance(), bbox, origin, deep) : static_cast(NULL)) { conformSizes(); } #if defined(DOXYGEN) /** * \brief Make the lhs use the rhs's pixels * * If you are copying a scalar value, a simple lhs = scalar; is OK, but * this is probably not the function that you want to use with an %image. To copy pixel values * from the rhs use operator<<=() */ template image::MaskedImage& image::MaskedImage::operator=(image::MaskedImage const& rhs ///< Right hand side ) {} #endif template void image::MaskedImage::swap(MaskedImage &rhs) { using std::swap; // See Meyers, Effective C++, Item 25 _image.swap(rhs._image); _mask.swap(rhs._mask); _variance.swap(rhs._variance); } // Use compiler generated version of: // MaskedImage &operator=(const MaskedImage& rhs); /************************************************************************************************************/ // Operators /** * Set the pixels in the MaskedImage to the rhs */ template image::MaskedImage& image::MaskedImage::operator=(MaskedImage::Pixel const& rhs) { *_image = rhs.image(); *_mask = rhs.mask(); *_variance = rhs.variance(); return *this; } /** * Set the pixels in the MaskedImage to the rhs */ template image::MaskedImage& image::MaskedImage::operator=(MaskedImage::SinglePixel const& rhs) { *_image = rhs.image(); *_mask = rhs.mask(); *_variance = rhs.variance(); return *this; } /** * Copy the pixels from the rhs to the lhs * * \note operator=() is not equivalent to this command */ template void image::MaskedImage::operator<<=(MaskedImage const& rhs) { *_image <<= *rhs.getImage(); *_mask <<= *rhs.getMask(); *_variance <<= *rhs.getVariance(); } /// Add a MaskedImage rhs to a MaskedImage /// /// The %image and variances are added; the masks are ORd together /// /// \note The pixels in the two images are taken to be independent. There is /// a Pixel operation (plus) which models the covariance, but this is not (yet?) /// available as full-MaskedImage operators template void image::MaskedImage::operator+=(MaskedImage const& rhs) { *_image += *rhs.getImage(); *_mask |= *rhs.getMask(); *_variance += *rhs.getVariance(); } /// Add a scaled MaskedImage c*rhs to a MaskedImage /// /// The %image and variances are added; the masks are ORd together /// /// \note The pixels in the two images are taken to be independent. There is /// a Pixel operation (plus) which models the covariance, but this is not (yet?) /// available as full-MaskedImage operators template void image::MaskedImage::scaledPlus(double const c, MaskedImage const& rhs) { (*_image).scaledPlus(c, *rhs.getImage()); *_mask |= *rhs.getMask(); (*_variance).scaledPlus(c*c, *rhs.getVariance()); } /// Add a scalar rhs to a MaskedImage template void image::MaskedImage::operator+=(ImagePixelT const rhs) { *_image += rhs; } /// Subtract a MaskedImage rhs from a MaskedImage /// /// The %images are subtracted; the masks are ORd together; and the variances are added /// /// \note the pixels in the two images are taken to be independent template void image::MaskedImage::operator-=(MaskedImage const& rhs) { *_image -= *rhs.getImage(); *_mask |= *rhs.getMask(); *_variance += *rhs.getVariance(); } /// Subtract a scaled MaskedImage c*rhs from a MaskedImage /// /// The %images are subtracted; the masks are ORd together; and the variances are added /// /// \note the pixels in the two images are taken to be independent template void image::MaskedImage::scaledMinus(double const c, MaskedImage const& rhs) { (*_image).scaledMinus(c, *rhs.getImage()); *_mask |= *rhs.getMask(); (*_variance).scaledPlus(c*c, *rhs.getVariance()); } /// Subtract a scalar rhs from a MaskedImage template void image::MaskedImage::operator-=(ImagePixelT const rhs) { *_image -= rhs; } namespace { /// Functor to calculate the variance of the product of two independent variables template struct productVariance { double operator()(ImagePixelT lhs, ImagePixelT rhs, VariancePixelT varLhs, VariancePixelT varRhs) { return lhs*lhs*varRhs + rhs*rhs*varLhs; } }; /// Functor to calculate variance of the product of two independent variables, with the rhs scaled by c template struct scaledProductVariance { double _c; scaledProductVariance(double const c) : _c(c) {} double operator()(ImagePixelT lhs, ImagePixelT rhs, VariancePixelT varLhs, VariancePixelT varRhs) { return _c*_c*(lhs*lhs*varRhs + rhs*rhs*varLhs); } }; } template void image::MaskedImage::operator*=(MaskedImage const& rhs) { // Must do variance before we modify the image values transform_pixels(_image->_getRawView(), // lhs rhs._image->_getRawView(), // rhs, _variance->_getRawView(), // Var(lhs), rhs._variance->_getRawView(), // Var(rhs) _variance->_getRawView(), // result productVariance()); *_image *= *rhs.getImage(); *_mask |= *rhs.getMask(); } template void image::MaskedImage::scaledMultiplies(double const c, MaskedImage const& rhs) { // Must do variance before we modify the image values transform_pixels(_image->_getRawView(), // lhs rhs._image->_getRawView(), // rhs, _variance->_getRawView(), // Var(lhs), rhs._variance->_getRawView(), // Var(rhs) _variance->_getRawView(), // result scaledProductVariance(c)); (*_image).scaledMultiplies(c, *rhs.getImage()); *_mask |= *rhs.getMask(); } template void image::MaskedImage::operator*=(ImagePixelT const rhs) { *_image *= rhs; *_variance *= rhs*rhs; } namespace { /// Functor to calculate the variance of the ratio of two independent variables template struct quotientVariance { double operator()(ImagePixelT lhs, ImagePixelT rhs, VariancePixelT varLhs, VariancePixelT varRhs) { ImagePixelT const rhs2 = rhs*rhs; return (lhs*lhs*varRhs + rhs2*varLhs)/(rhs2*rhs2); } }; /// Functor to calculate the variance of the ratio of two independent variables, the second scaled by c template struct scaledQuotientVariance { double _c; scaledQuotientVariance(double c) : _c(c) {} double operator()(ImagePixelT lhs, ImagePixelT rhs, VariancePixelT varLhs, VariancePixelT varRhs) { ImagePixelT const rhs2 = rhs*rhs; return (lhs*lhs*varRhs + rhs2*varLhs)/(_c*_c*rhs2*rhs2); } }; } template void image::MaskedImage::operator/=(MaskedImage const& rhs) { // Must do variance before we modify the image values transform_pixels(_image->_getRawView(), // lhs rhs._image->_getRawView(), // rhs, _variance->_getRawView(), // Var(lhs), rhs._variance->_getRawView(), // Var(rhs) _variance->_getRawView(), // result quotientVariance()); *_image /= *rhs.getImage(); *_mask |= *rhs.getMask(); } template void image::MaskedImage::scaledDivides(double const c, MaskedImage const& rhs) { // Must do variance before we modify the image values transform_pixels(_image->_getRawView(), // lhs rhs._image->_getRawView(), // rhs, _variance->_getRawView(), // Var(lhs), rhs._variance->_getRawView(), // Var(rhs) _variance->_getRawView(), // result scaledQuotientVariance(c)); (*_image).scaledDivides(c, *rhs.getImage()); *_mask |= *rhs._mask; } template void image::MaskedImage::operator/=(ImagePixelT const rhs) { *_image /= rhs; *_variance /= rhs*rhs; } template void image::MaskedImage::writeFits( std::string const& fileName, CONST_PTR(daf::base::PropertySet) metadata, CONST_PTR(daf::base::PropertySet) imageMetadata, CONST_PTR(daf::base::PropertySet) maskMetadata, CONST_PTR(daf::base::PropertySet) varianceMetadata ) const { fits::Fits fitsfile(fileName, "w", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); writeFits(fitsfile, metadata, imageMetadata, maskMetadata, varianceMetadata); } template void image::MaskedImage::writeFits( fits::MemFileManager & manager, CONST_PTR(daf::base::PropertySet) metadata, CONST_PTR(daf::base::PropertySet) imageMetadata, CONST_PTR(daf::base::PropertySet) maskMetadata, CONST_PTR(daf::base::PropertySet) varianceMetadata ) const { fits::Fits fitsfile(manager, "w", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); writeFits(fitsfile, metadata, imageMetadata, maskMetadata, varianceMetadata); } namespace { void processPlaneMetadata( CONST_PTR(lsst::daf::base::PropertySet) metadata, PTR(lsst::daf::base::PropertySet) & hdr, char const * exttype ) { if (metadata) { hdr = metadata->deepCopy(); } else { hdr.reset(new lsst::daf::base::PropertyList()); } hdr->set("INHERIT", true); hdr->set("EXTTYPE", exttype);
    553 504cf02b - hdr->set("EXTNAME", exttype);
    } } // anonymous template void image::MaskedImage::writeFits( fits::Fits & fitsfile, CONST_PTR(daf::base::PropertySet) metadata, CONST_PTR(daf::base::PropertySet) imageMetadata, CONST_PTR(daf::base::PropertySet) maskMetadata, CONST_PTR(daf::base::PropertySet) varianceMetadata ) const { PTR(daf::base::PropertySet) hdr; if (metadata) { hdr = metadata->deepCopy(); } else { hdr.reset(new daf::base::PropertyList()); } if (fitsfile.countHdus() != 0) { throw LSST_EXCEPT(
    576 ded0eb52 - pex::exceptions::LogicErrorException,
    ? ---------
    572 21597d88 + pex::exceptions::LogicError,
    "MaskedImage::writeFits can only write to an empty file" ); } if (fitsfile.getHdu() <= 1) { // Don't ever write images to primary; instead we make an empty primary. fitsfile.createEmpty(); } else { fitsfile.setHdu(1); } fitsfile.writeMetadata(*hdr); processPlaneMetadata(imageMetadata, hdr, "IMAGE"); _image->writeFits(fitsfile, hdr); processPlaneMetadata(maskMetadata, hdr, "MASK"); _mask->writeFits(fitsfile, hdr); processPlaneMetadata(varianceMetadata, hdr, "VARIANCE"); _variance->writeFits(fitsfile, hdr); } /************************************************************************************************************/ // private function conformSizes() ensures that the Mask and Variance have the same dimensions // as Image. If Mask and/or Variance have non-zero dimensions that conflict with the size of Image, // a lsst::pex::exceptions::LengthError is thrown. template void image::MaskedImage::conformSizes() { if (!_mask || _mask->getWidth() == 0 || _mask->getHeight() == 0) {
    607 3263f939 - _mask = MaskPtr(new Mask(_image->getBBox(PARENT)));
    ? ------
    603 93994d54 + _mask = MaskPtr(new Mask(_image->getBBox()));
    *_mask = 0; } else { if (_mask->getDimensions() != _image->getDimensions()) { throw LSST_EXCEPT(
    612 3263f939 - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    608 21597d88 + lsst::pex::exceptions::LengthError,
    (boost::format("Dimension mismatch: Image %dx%d v. Mask %dx%d") % _image->getWidth() % _image->getHeight() % _mask->getWidth() % _mask->getHeight() ).str() ); } } if (!_variance || _variance->getWidth() == 0 || _variance->getHeight() == 0) {
    622 7e954fae - _variance = VariancePtr(new Variance(_image->getBBox(PARENT)));
    ? ------
    618 93994d54 + _variance = VariancePtr(new Variance(_image->getBBox()));
    *_variance = 0; } else { if (_variance->getDimensions() != _image->getDimensions()) { throw LSST_EXCEPT(
    627 3263f939 - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    623 21597d88 + lsst::pex::exceptions::LengthError,
    (boost::format("Dimension mismatch: Image %dx%d v. Variance %dx%d") % _image->getWidth() % _image->getHeight() % _variance->getWidth() % _variance->getHeight() ).str() ); } } } /************************************************************************************************************/ // // Iterators and locators // /// Return an \c iterator to the start of the %image template typename image::MaskedImage::iterator image::MaskedImage::begin() const { #if 0 // this doesn't compile; why? return iterator(_image->begin(), _mask->begin(), _variance->begin()); #else typename Image::iterator imageBegin = _image->begin(); typename Mask::iterator maskBegin = _mask->begin(); typename Variance::iterator varianceBegin = _variance->begin(); return iterator(imageBegin, maskBegin, varianceBegin); #endif } /// Return an \c iterator to the end of the %image template typename image::MaskedImage::iterator image::MaskedImage::end() const { typename Image::iterator imageEnd = getImage()->end(); typename Mask::iterator maskEnd = getMask()->end(); typename Variance::iterator varianceEnd = getVariance()->end(); return iterator(imageEnd, maskEnd, varianceEnd); } /// Return an \c iterator at the point (x, y) template typename image::MaskedImage::iterator image::MaskedImage::at(int const x, int const y) const { typename Image::iterator imageEnd = getImage()->at(x, y); typename Mask::iterator maskEnd = getMask()->at(x, y); typename Variance::iterator varianceEnd = getVariance()->at(x, y); return iterator(imageEnd, maskEnd, varianceEnd); } /// Return a \c reverse_iterator to the start of the %image template typename image::MaskedImage::reverse_iterator image::MaskedImage::rbegin() const { typename Image::reverse_iterator imageBegin = _image->rbegin(); typename Mask::reverse_iterator maskBegin = _mask->rbegin(); typename Variance::reverse_iterator varianceBegin = _variance->rbegin(); return reverse_iterator(imageBegin, maskBegin, varianceBegin); } /// Return a \c reverse_iterator to the end of the %image template typename image::MaskedImage::reverse_iterator image::MaskedImage::rend() const { typename Image::reverse_iterator imageEnd = getImage()->rend(); typename Mask::reverse_iterator maskEnd = getMask()->rend(); typename Variance::reverse_iterator varianceEnd = getVariance()->rend(); return reverse_iterator(imageEnd, maskEnd, varianceEnd); } /// Return an \c x_iterator to the start of the %image template typename image::MaskedImage::x_iterator image::MaskedImage::row_begin(int y) const { typename Image::x_iterator imageBegin = _image->row_begin(y); typename Mask::x_iterator maskBegin = _mask->row_begin(y); typename Variance::x_iterator varianceBegin = _variance->row_begin(y); return x_iterator(imageBegin, maskBegin, varianceBegin); } /// Return an \c x_iterator to the end of the %image template typename image::MaskedImage::x_iterator image::MaskedImage::row_end(int y) const { typename Image::x_iterator imageEnd = getImage()->row_end(y); typename Mask::x_iterator maskEnd = getMask()->row_end(y); typename Variance::x_iterator varianceEnd = getVariance()->row_end(y); return x_iterator(imageEnd, maskEnd, varianceEnd); } /************************************************************************************************************/ /// Return an \c y_iterator to the start of the %image template typename image::MaskedImage::y_iterator image::MaskedImage::col_begin(int x) const { typename Image::y_iterator imageBegin = _image->col_begin(x); typename Mask::y_iterator maskBegin = _mask->col_begin(x); typename Variance::y_iterator varianceBegin = _variance->col_begin(x); return y_iterator(imageBegin, maskBegin, varianceBegin); } /// Return an \c y_iterator to the end of the %image template typename image::MaskedImage::y_iterator image::MaskedImage::col_end(int x) const { typename Image::y_iterator imageEnd = getImage()->col_end(x); typename Mask::y_iterator maskEnd = getMask()->col_end(x); typename Variance::y_iterator varianceEnd = getVariance()->col_end(x); return y_iterator(imageEnd, maskEnd, varianceEnd); } /************************************************************************************************************/ /// Fast iterators to contiguous images /// /// Return a fast \c iterator to the start of the %image, which must be contiguous /// Note that the order in which pixels are visited is undefined. /// /// \exception lsst::pex::exceptions::Runtime /// Argument \a contiguous is false, or the pixels are not in fact contiguous template typename image::MaskedImage::fast_iterator image::MaskedImage::begin( bool contiguous ///< Pixels are contiguous (must be true) ) const { typename Image::fast_iterator imageBegin = _image->begin(contiguous); typename Mask::fast_iterator maskBegin = _mask->begin(contiguous); typename Variance::fast_iterator varianceBegin = _variance->begin(contiguous); return fast_iterator(imageBegin, maskBegin, varianceBegin); } /// Return a fast \c iterator to the end of the %image, which must be contiguous /// Note that the order in which pixels are visited is undefined. /// /// \exception lsst::pex::exceptions::Runtime /// Argument \a contiguous is false, or the pixels are not in fact contiguous template typename image::MaskedImage::fast_iterator image::MaskedImage::end( bool contiguous ///< Pixels are contiguous (must be true) ) const { typename Image::fast_iterator imageEnd = getImage()->end(contiguous); typename Mask::fast_iterator maskEnd = getMask()->end(contiguous); typename Variance::fast_iterator varianceEnd = getVariance()->end(contiguous); return fast_iterator(imageEnd, maskEnd, varianceEnd); } /************************************************************************************************************/ // // Explicit instantiations // template class image::MaskedImage; template class image::MaskedImage; template class image::MaskedImage; template class image::MaskedImage; template class image::MaskedImage;

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ded0eb52

    commit ded0eb52af9b4e28790afe94d115c1d8699fa271
    Author: Jim Bosch 
    Date:   Tue Nov 20 00:46:52 2012 -0500
    
        Overhaul FITS persistence for MaskedImage and Exposure: no more appending or passing HDU to read, no more multi-file support, but we put metadata in primary HDU and use INHERIT keyword (as per discussion on lsst-data list).
    

    7e954fae

    commit 7e954fae9aeba9a89862062f52a76c063757f0d8
    Author: Robert Lupton the Good 
    Date:   Mon Jan 21 14:41:42 2013 -0500
    
        Set variance's BBox correctly; #2577
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    504cf02b

    commit 504cf02b6a6c50b1614a9b6285e4155c8e30d2d2
    Author: Jim Bosch 
    Date:   Fri Mar 1 12:08:40 2013 +0900
    
        Set EXTNAME as well as EXTTYPE to descriptive names for HDUs; it seems to be more commonly interpreted by various FITS readers.
    

    42dadff6

    commit 42dadff68d69c7a54f53cc9d55fe0153e7a5b350
    Author: Jim Bosch 
    Date:   Sun Nov 18 18:50:24 2012 -0500
    
        Reimplement FITS image reading to use afw::fits
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    include/lsst/afw/geom.h

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief An include file to include the header files for lsst::afw::geom
                     *
                     * Does not include lsst/afw/geom/ellipses.h.
                     */
                    #ifndef LSST_GEOM_H
                    #define LSST_GEOM_H
                    
                    #include "lsst/afw/geom/CoordinateBase.h"
                    #include "lsst/afw/geom/CoordinateExpr.h"
                    #include "lsst/afw/geom/Angle.h"
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/geom/Extent.h"
                    #include "lsst/afw/geom/AffineTransform.h"
                    #include "lsst/afw/geom/LinearTransform.h"
                    #include "lsst/afw/geom/Box.h"
                    #include "lsst/afw/geom/Span.h"
                    #include "lsst/afw/geom/XYTransform.h"
    
    42 a06cb6fe + #include "lsst/afw/geom/Functor.h"
    43 a06cb6fe + #include "lsst/afw/geom/SeparableXYTransform.h"
    44 3d6fb300 + #include "lsst/afw/geom/Polygon.h"
    45 6f5ea58d + #include "lsst/afw/geom/TransformMap.h"
    #endif // LSST_GEOM_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    6f5ea58d

    commit 6f5ea58df69e1713505a44d25dbbd0e121bd6aff
    Author: Russell Owen 
    Date:   Tue Feb 18 11:25:54 2014 -0800
    
        Rename TransformRegistry to TransformMap and TransformMap to TransformMap::Transforms
    

    a06cb6fe

    commit a06cb6fe9ad8724f3f9b48c2a7ccf1013b742312
    Author: Jim Chiang 
    Date:   Tue Feb 17 08:07:00 2015 -0800
    
        Add Functor and SeparableXYTransform classes to support modeling of
        sensor effects.
        
        Functor is an abstract class that SeparableXYTransform takes as
        arguments in its constructor.  Distinct Functor subclass objects are
        used to model the transformations in the x- and y-directions,
        respectively.  Functor provides an inverse(...) member function that
        calls the subclass' concrete implementation of the Functor::derivative(...)
        pure virtual function to compute the inverse of the 1D function using
        Newton-Raphson.  LinearFunctor is provided as an example subclass.
    

    3d6fb300

    commit 3d6fb3001856d9c793c9e6291ea65ccb9e252e7f
    Author: Paul Price 
    Date:   Mon Feb 10 17:50:34 2014 -0500
    
        add CartesianPolygon class (#3139)
    

    Return to list

    include/lsst/afw/geom/Point.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * @brief A coordinate class intended to represent absolute positions.
                     */
                    #ifndef LSST_AFW_GEOM_POINT_H
                    #define LSST_AFW_GEOM_POINT_H
                    
                    #include "lsst/afw/geom/CoordinateBase.h"
                    #include "lsst/afw/geom/CoordinateExpr.h"
                    #include "lsst/afw/geom/Extent.h"
                    
                    namespace lsst { namespace afw { namespace geom {
                    
                    template 
                    class PointBase : public CoordinateBase,T,N> {
                        typedef CoordinateBase,T,N> Super;
                    public:
                    
                        /**
                         *  @brief Standard equality comparison.
                         *
                         *  Returns true iff all(this->eq(other));
                         */
                        bool operator==(Point const & other) const { return all(this->eq(other)); }
                    
                        /**
                         *  @brief Standard inequality comparison.
                         *
                         *  Returns true iff any(this->ne(other));
                         */
                        bool operator!=(Point const & other) const { return any(this->ne(other)); }
                    
                        /**
                         *  @name Named vectorized comparison functions
                         *
                         *  Note that these return CoordinateExpr, not bool.
                         *
                         *  Unlike most arithmetic and assignment operators, scalar interoperability is provided
                         *  for comparisons; expressions like 
                         *  \code
                         *    if (all(point.gt(0))) ...
                         *  \endcode
                         *  are both ubiquitous and easy to interpret.
                         */
                        //@{
                        CoordinateExpr eq(Point const & other) const;
                        CoordinateExpr ne(Point const & other) const;
                        CoordinateExpr lt(Point const & other) const;
                        CoordinateExpr le(Point const & other) const;
                        CoordinateExpr gt(Point const & other) const;
                        CoordinateExpr ge(Point const & other) const;
                        CoordinateExpr eq(T scalar) const { return this->eq(Point(scalar)); }
                        CoordinateExpr ne(T scalar) const { return this->ne(Point(scalar)); }
                        CoordinateExpr lt(T scalar) const { return this->lt(Point(scalar)); }
                        CoordinateExpr le(T scalar) const { return this->le(Point(scalar)); }
                        CoordinateExpr gt(T scalar) const { return this->gt(Point(scalar)); }
                        CoordinateExpr ge(T scalar) const { return this->ge(Point(scalar)); }
                        //@}
                    
                        /**
                         *  @name Arithmetic operators
                         *
                         *  No scalar interoperability is provided for Point arithmetic operations.
                         */
                        //@{
                        Extent operator-(Point const & other) const {
                            return Extent(this->_vector - other._vector);
                        }
                        Point operator+(Extent const & other) const {
                            return Point(this->_vector + other.asEigen());
                        }
                        Point operator-(Extent const & other) const {
                            return Point(this->_vector - other.asEigen());
                        }
                        Point & operator+=(Extent const & other) {
                            this->_vector += other.asEigen();
                            return static_cast &>(*this); 
                        }
                        Point & operator-=(Extent const & other) {
                            this->_vector -= other.asEigen();
                            return static_cast &>(*this); 
                        }
                        //@}
                    
    
    109 b449d4b3 + /// Cast this object to an Extent of the same numeric type and dimensionality.
    110 b449d4b3 + Extent asExtent() const { return Extent(static_cast const &>(*this)); }
    111 b449d4b3 +
    /// @brief Shift the point by the given offset. void shift(Extent const & offset) { this->_vector += offset.asEigen(); } void scale(double factor) { this->_vector *= factor; } double distanceSquared(PointBase const & other) const { // the cast to double is lame but Eigen seems to require they be the same type return (this->asEigen() - other.asEigen()).squaredNorm(); } std::string toString() const { std::stringstream out; out << "Point("; for (size_t i = 0; i < N; ++i) { if (i != 0) { out << ","; } out << (*this)[i]; } out << ")"; return out.str(); } protected: explicit PointBase(T val = static_cast(0)) : Super(val) {} template explicit PointBase(Eigen::MatrixBase const & vector) : Super(vector) {} }; /** * @brief A coordinate class intended to represent absolute positions.
    146 8196a1ba + *
    147 8196a1ba + * See @ref afwGeomOps for mathematical operators on Point.
    */ template class Point : public PointBase { typedef PointBase Super; public: typedef typename Super::EigenVector EigenVector; /// @brief Construct a Point with all elements set to the same scalar value. explicit Point(T val=static_cast(0)) : Super(val) {} /** * @brief Explicit converting constructor. * * Converting from floating point to integer rounds to the nearest integer instead of truncating. * This ensures that a floating-point pixel coordinate converts to the coordinate of the pixel * it lies on (assuming the floating point origin is the center of the first pixel). */ template explicit Point(Point const & other); /// @brief Construct a Point from an Eigen vector. explicit Point(EigenVector const & vector) : Super(vector) {} /// @brief Explicit constructor from Extent. explicit Point(Extent const & other) : Super(other.asEigen()) {} void swap(Point & other) { this->_swap(other); } }; /** * @brief A coordinate class intended to represent absolute positions (2-d specialization).
    179 8196a1ba + *
    180 8196a1ba + * See @ref afwGeomOps for mathematical operators on Point.
    */ template class Point : public PointBase { typedef PointBase Super; public: typedef typename Super::EigenVector EigenVector; /// @brief Construct a Point with all elements set to the same scalar value. explicit Point(T val=static_cast(0)) : Super(val) {} /** * @brief Explicit converting constructor. * * Converting from floating point to integer rounds to the nearest integer instead of truncating. * This ensures that a floating-point pixel coordinate converts to the coordinate of the pixel * it lies on (assuming the floating point origin is the center of the first pixel). */ template explicit Point(Point const & other); /// @brief Construct a Point from an Eigen vector. explicit Point(EigenVector const & vector) : Super(vector) {} /// @brief Explicit constructor from Extent. explicit Point(Extent const & other) : Super(other.asEigen()) {} /// @brief Explicit constructor from a pair of doubles. explicit Point(T x, T y) : Super(EigenVector(x,y)) {} /// @brief Construct from a two-element array. explicit Point(T const xy[2]) : Super(EigenVector(xy[0], xy[1])) {} /// @brief Construct from a std::pair. explicit Point(std::pair const & xy) : Super(EigenVector(xy.first, xy.second)) {} /// @brief Construct from boost::tuple. explicit Point(boost::tuple const & xy) : Super(EigenVector(xy.template get<0>(), xy.template get<1>())) {} #ifdef SWIG T getX() const; T getY() const; void setX(T x); void setY(T y); #endif void swap(Point & other) { this->_swap(other); } }; /** * @brief A coordinate class intended to represent absolute positions (3-d specialization).
    232 8196a1ba + *
    233 8196a1ba + * See @ref afwGeomOps for mathematical operators on Point.
    */ template class Point : public PointBase { typedef PointBase Super; public: typedef typename Super::EigenVector EigenVector; /// @brief Construct a Point with all elements set to the same scalar value. explicit Point(T val=static_cast(0)) : Super(val) {} /** * @brief Explicit converting constructor. * * Converting from floating point to integer rounds to the nearest integer instead of truncating. * This ensures that a floating-point pixel coordinate converts to the coordinate of the pixel * it lies on (assuming the floating point origin is the center of the first pixel). */ template explicit Point(Point const & other); /// @brief Construct a Point from an Eigen vector. explicit Point(EigenVector const & vector) : Super(vector) {} /// @brief Explicit constructor from Extent. explicit Point(Extent const & other) : Super(other.asEigen()) {} /// @brief Explicit constructor from a sequence of doubles. explicit Point(T x, T y, T z) : Super(EigenVector(x,y,z)) {} /// @brief Construct from a two-element array. explicit Point(T const xyz[3]) : Super(EigenVector(xyz[0], xyz[1], xyz[2])) {} /// @brief Construct from boost::tuple. explicit Point(boost::tuple const & xyz) : Super(EigenVector(xyz.template get<0>(), xyz.template get<1>(), xyz.template get<2>())) {} #ifdef SWIG T getX() const; T getY() const; T getZ() const; void setX(T x); void setY(T y); void setZ(T z); #endif void swap(Point & other) { this->_swap(other); } }; typedef Point PointI; typedef Point Point2I; typedef Point Point3I; typedef Point PointD; typedef Point Point2D; typedef Point Point3D;
    289 4567a4cd + template
    290 4567a4cd + Point operator+(Point const & lhs, Extent const & rhs) {
    291 4567a4cd + return lhs + Extent(rhs);
    292 4567a4cd + }
    293 4567a4cd +
    294 4567a4cd + template
    295 4567a4cd + Point operator+(Extent const & rhs, Point const & lhs) {
    296 4567a4cd + return Point(lhs) + rhs;
    297 4567a4cd + }
    298 4567a4cd +
    299 4567a4cd + template
    300 4567a4cd + Point & operator+=(Point & lhs, Extent const & rhs) {
    301 4567a4cd + return lhs += Extent(rhs);
    302 4567a4cd + }
    303 4567a4cd +
    304 4567a4cd + template
    305 4567a4cd + Point operator+(Point const & lhs, Extent const & rhs) {
    306 4567a4cd + return Point(lhs) + rhs;
    307 4567a4cd + }
    308 4567a4cd +
    309 4567a4cd + template
    310 4567a4cd + Point operator-(Point const & lhs, Extent const & rhs) {
    311 4567a4cd + return lhs - Extent(rhs);
    312 4567a4cd + }
    313 4567a4cd +
    314 4567a4cd + template
    315 4567a4cd + Point & operator-=(Point & lhs, Extent const & rhs) {
    316 4567a4cd + return lhs -= Extent(rhs);
    317 4567a4cd + }
    318 4567a4cd +
    319 4567a4cd + template
    320 4567a4cd + Point operator-(Point const & lhs, Extent const & rhs) {
    321 4567a4cd + return Point(lhs) - rhs;
    322 4567a4cd + }
    323 4567a4cd +
    324 4567a4cd + template
    325 4567a4cd + Extent operator-(Point const & lhs, Point const & rhs) {
    326 4567a4cd + return lhs - Point(rhs);
    327 4567a4cd + }
    328 4567a4cd +
    329 4567a4cd + template
    330 4567a4cd + Extent operator-(Point const & lhs, Point const & rhs) {
    331 4567a4cd + return Point(lhs) - rhs;
    332 4567a4cd + }
    333 4567a4cd +
    }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    8196a1ba

    commit 8196a1baa9b18a3cf752b2784d0c895d54a3ab36
    Author: Jim Bosch 
    Date:   Tue Apr 14 15:25:10 2015 -0400
    
        Add table of Point/Extent operations to Doxygen.
    

    b449d4b3

    commit b449d4b3dd5e2b050d522b7c3990f50277096ef0
    Author: Jim Bosch 
    Date:   Fri Apr 3 18:17:10 2015 -0400
    
        Add conversion between Point and Extent as methods.
        
        Methods are much less verbose than the existing conversion constructors
        in Python.
    

    Return to list

    tests/ticket2707.py

    Diff:

    1 1f8403de - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . #
    25 1f8403de - import os, os.path
    import unittest import lsst.afw.geom as afwGeom import lsst.afw.table as afwTable import lsst.utils.tests as utilsTests #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class MatchXyTest(unittest.TestCase): """Test that matching sources by centroid works as expected, even when some of the centroids contain NaN. """ def setUp(self): nan = float('nan') self.schema = afwTable.SourceTable.makeMinimalSchema() centroidKey = self.schema.addField("cen", type="PointD") self.table = afwTable.SourceTable.make(self.schema)
    43 1f8403de - self.table.defineCentroid(centroidKey)
    ? ^^^^^^^^
    43 2f75198f + self.table.defineCentroid("cen")
    ? + ^ idKey = self.table.getIdKey() self.cat1 = afwTable.SourceCatalog(self.table) self.cat2 = afwTable.SourceCatalog(self.table)
    47 3252a40a - self.nobj = 10
    48 3252a40a - self.nUniqueMatch = 0
    49 3252a40a - for i in range(self.nobj):
    ? ^^^^^^^^^
    47 1f8403de + for i in xrange(10):
    ? + ^^
    50 3252a40a - j = self.nobj - i - 1
    ? ^^^^^^^^^ ----
    48 1f8403de + j = 9 - i
    ? ^ r1, r2 = self.cat1.addNew(), self.cat2.addNew() r1.set(idKey, i)
    53 3252a40a - r2.set(idKey, self.nobj + j)
    ? ^^^^^^^^^
    51 1f8403de + r2.set(idKey, 10 + j)
    ? ^^ if i % 3 != 0: r1.set(centroidKey, afwGeom.Point2D(i,i)) r2.set(centroidKey, afwGeom.Point2D(j,j))
    57 3252a40a - self.nUniqueMatch += 1
    58 3252a40a - elif i == 3:
    59 3252a40a - r1.set(centroidKey, afwGeom.Point2D(i,i))
    60 3252a40a - r2.set(centroidKey, afwGeom.Point2D(j + 2,j + 2))
    else: r1.set(centroidKey, afwGeom.Point2D(nan,nan)) r2.set(centroidKey, afwGeom.Point2D(nan,nan)) def tearDown(self): del self.cat2 del self.cat1 del self.table del self.schema def testMatchXy(self): matches = afwTable.matchXy(self.cat1, self.cat2, 0.01)
    73 3252a40a - self.assertEquals(len(matches), self.nUniqueMatch)
    ? ^^^^^^^^^^^^^^^^^
    67 1f8403de + self.assertEquals(len(matches), 6)
    ? ^
    74 3252a40a -
    for m in matches:
    76 3252a40a - self.assertEquals(m.first.getId() + self.nobj, m.second.getId())
    ? ^^^^^^^^^
    69 1f8403de + self.assertEquals(m.first.getId() + 10, m.second.getId())
    ? ^^ self.assertEquals(m.distance, 0.0)
    79 3252a40a - def testMatchXyMatchControl(self):
    80 3252a40a - """Test using MatchControl to return all matches, and add a test for closest==False at the same time"""
    81 3252a40a - for closest in (True, False):
    82 81c6063a - for includeMismatches in (True, False):
    83 81c6063a - mc = afwTable.MatchControl()
    84 81c6063a - mc.findOnlyClosest = closest
    85 81c6063a - mc.includeMismatches = includeMismatches
    86 81c6063a - matches = afwTable.matchXy(self.cat1, self.cat2, 0.01, mc)
    87 81c6063a -
    88 81c6063a - if False:
    89 81c6063a - for m in matches:
    90 81c6063a - print closest, m.first.getId(), m.second.getId(), m.distance
    91 81c6063a -
    92 81c6063a - if includeMismatches:
    93 81c6063a - catMatches = afwTable.SourceCatalog(self.table)
    94 81c6063a - catMismatches = afwTable.SourceCatalog(self.table)
    95 81c6063a - for m in matches:
    96 81c6063a - if m[1] != None:
    97 81c6063a - if not any(x == m[0] for x in catMatches):
    98 81c6063a - catMatches.append(m[0])
    99 81c6063a - else:
    100 81c6063a - catMismatches.append(m[0])
    101 81c6063a - matches = afwTable.matchXy(catMatches, self.cat2, 0.01, mc)
    102 81c6063a - mc.includeMismatches = False
    103 81c6063a - noMatches = afwTable.matchXy(catMismatches, self.cat2, 0.01, mc)
    104 81c6063a - self.assertEquals(len(noMatches), 0)
    105 81c6063a -
    106 81c6063a - self.assertEquals(len(matches), self.nUniqueMatch if closest else self.nUniqueMatch + 1)
    107 3252a40a - for m in matches:
    108 81c6063a - if closest:
    109 81c6063a - self.assertEquals(m.first.getId() + self.nobj, m.second.getId())
    110 81c6063a - self.assertEquals(m.distance, 0.0)
    111 3252a40a -
    112 3252a40a - def testSelfMatchXy(self):
    113 3252a40a - """Test doing a self-matches"""
    114 3252a40a - for symmetric in (True, False):
    115 3252a40a - mc = afwTable.MatchControl()
    116 3252a40a - mc.symmetricMatch = symmetric
    117 3252a40a - matches = afwTable.matchXy(self.cat2, 0.01, mc)
    118 3252a40a -
    119 3252a40a - if False:
    120 3252a40a - for m in matches:
    121 3252a40a - print m.first.getId(), m.second.getId(), m.distance
    122 3252a40a -
    123 3252a40a - self.assertEquals(len(matches), 2 if symmetric else 1)
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(MatchXyTest) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    81c6063a

    commit 81c6063a32883b748f3770b7124d74ced7b480f5
    Author: Jose Garmilla 
    Date:   Thu Jun 12 16:14:39 2014 -0400
    
        Implement and test includeMismatches option in MatchControl object
    

    1f8403de

    commit 1f8403de8f7cdce36604cc3044593a518f4024d6
    Author: Serge Monkewitz 
    Date:   Wed Feb 27 22:02:19 2013 -0600
    
        Fix #2707 by making matchXy() ignore sources with NaNs in their centroids.
    

    3252a40a

    commit 3252a40ad55222b882acf14d2f7cf0f3fe80f585
    Author: Robert Lupton the Good 
    Date:   Tue Jun 10 15:00:58 2014 -0400
    
        Added MatchControl and implemented it for matchXY and MatchRaDec
        
        N.b. added some missing tests on matchXY, although it is unchanged by this
        changeset
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    1f8403de

    commit 1f8403de8f7cdce36604cc3044593a518f4024d6
    Author: Serge Monkewitz 
    Date:   Wed Feb 27 22:02:19 2013 -0600
    
        Fix #2707 by making matchXy() ignore sources with NaNs in their centroids.
    

    2f75198f

    commit 2f75198fac120aa8d7d376014b1dba1a37922464
    Author: Perry Gee 
    Date:   Tue Jul 22 14:19:12 2014 -0500
    
        Fix quick tests for DM-936 where definition of slots is done with keys.  That is no longer supported.
    

    Return to list

    python/lsst/afw/table/io/ioLib.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define ioLib_DOCSTRING
                    "
                    Python interface to lsst::afw::table::io classes
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.table.io", docstring=ioLib_DOCSTRING) ioLib
                    
                    #pragma SWIG nowarn=362                 // operator=  ignored
                    #pragma SWIG nowarn=389                 // operator[]  ignored
                    #pragma SWIG nowarn=503                 // comparison operators ignored
                    #pragma SWIG nowarn=520                 // base class not similarly marked as smart pointer
                    #pragma SWIG nowarn=401                 // nothing known about base class
                    #pragma SWIG nowarn=302                 // redefine identifier (SourceSet<> -> SourceSet)
                    
                    %{
                    #include "lsst/afw/table/io/Persistable.h"
    
    41 6fc1c3d1 + #include "lsst/pex/exceptions.h"
    %} %include "boost_shared_ptr.i" %include "lsst/p_lsstSwig.i" %import "lsst/pex/exceptions/exceptionsLib.i" %lsst_exceptions(); // =============== Persistable ============================================================================== %shared_ptr(lsst::afw::table::io::Persistable); %define %declareTablePersistable(NAME, T...) %shared_ptr(lsst::afw::table::io::Persistable); %shared_ptr(lsst::afw::table::io::PersistableFacade< T >); %shared_ptr(T); %template(NAME ## PersistableFacade) lsst::afw::table::io::PersistableFacade< T >; %enddef %include "lsst/afw/table/io/Persistable.h" // =============== Utility code =============================================================================
    65 6fc1c3d1 + %declareException(PersistenceError, lsst.pex.exceptions.IoError, lsst::afw::table::io::PersistenceError)
    66 6fc1c3d1 + %declareException(MalformedArchiveError, PersistenceError, lsst::afw::table::io::MalformedArchiveError)
    67 6fc1c3d1 +
    %inline %{ // It's useful in test code to be able to compare Persistables for pointer equality, // but I don't think this is possible without actually wrapping a shared_ptr equality // comparison - the Swig 'this' objects only expose the address *of* the shared_ptr, // not the address *in* the shared_ptr. bool comparePersistablePtrs( PTR(lsst::afw::table::io::Persistable) a, PTR(lsst::afw::table::io::Persistable) b ) { return a == b; } %}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    tests/rowColumnStats.py

    Diff:

    1 3ad6e04d - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? + # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # # -*- python -*- """ Tests for statisticsStack row/column statistics Run with: ./rowColumnStats.py or python >>> import rowColumnStats; rowColumnStats.run() """ ########################## # rowColumnStats.py # Steve Bickerton # An python test to check the row/column statistics from statisticsStack import unittest import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom import lsst.utils.tests as utilsTests class RowColumnStatisticsTestCase(unittest.TestCase): def setUp(self): # fill an image with a gradient self.n = 8 self.img = afwImage.ImageF(afwGeom.Extent2I(self.n, self.n), 0) # these are the known answers for comparison def nVector(n, v): return [v for i in range(n)] self.column = nVector(self.n, 0.0) self.row = nVector(self.n, 0.0) self.colPlus = nVector(self.n, 0.0) self.colMinus = nVector(self.n, 0.0) self.colMult = nVector(self.n, 0.0) self.colDiv = nVector(self.n, 0.0) self.rowPlus = nVector(self.n, 0.0) self.rowMinus = nVector(self.n, 0.0) self.rowMult = nVector(self.n, 0.0) self.rowDiv = nVector(self.n, 0.0) # set the values in the image, and keep track of the stats to verify things for y in range(self.n): for x in range(self.n): val = 1.0*x + 2.0*y self.img.set(x, y, val) self.column[y] += val self.row[x] += val for i in range(self.n): self.row[i] /= self.n self.column[i] /= self.n self.colPlus[i] = self.img.get(0, i) + self.column[i] # get stats on the columns and rows self.imgProjectCol = afwMath.statisticsStack(self.img, afwMath.MEAN, 'x') self.imgProjectRow = afwMath.statisticsStack(self.img, afwMath.MEAN, 'y') def tearDown(self): del self.img del self.imgProjectCol del self.imgProjectRow def testColumnStats(self): """Test the column statistics """ for i in range(self.n): self.assertEqual(self.imgProjectCol.get(0, i)[0], self.column[i]) def testRowStats(self): """Test the row statistics """ for i in range(self.n): self.assertEqual(self.imgProjectRow.get(i, 0)[0], self.row[i]) def testColumnOperators(self): """ Test operator overloading on columns """ columnSlice = afwImage.ImageSliceF(self.imgProjectCol.getImage()) imgAdd = self.img + columnSlice imgAdd2 = columnSlice + self.img imgSub = self.img - columnSlice imgMul = self.img * columnSlice imgMul2 = columnSlice * self.img imgDiv = self.img / columnSlice for i in range(self.n): self.assertAlmostEqual(imgAdd.get(0, i), self.img.get(0, i) + columnSlice.get(0, i)) self.assertAlmostEqual(imgAdd2.get(0, i), imgAdd.get(0, i)) self.assertAlmostEqual(imgSub.get(0, i), self.img.get(0, i) - columnSlice.get(0, i)) self.assertAlmostEqual(imgMul.get(0, i), self.img.get(0, i) * columnSlice.get(0, i)) self.assertAlmostEqual(imgMul2.get(0, i), imgMul.get(0, i)) self.assertAlmostEqual(imgDiv.get(0, i), self.img.get(0, i) / columnSlice.get(0, i)) ################################################################# # Test suite boiler plate ################################################################# def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(RowColumnStatisticsTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3ad6e04d

    commit 3ad6e04dc0fdfc8d57739e5957ad2a6b80246f92
    Author: bick 
    Date:   Wed Jan 20 09:03:34 2010 +0000
    
        #1135 row column stats and +-*/ row/column operations function.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    src/table/Source.cc

    Diff:

                    // -*- lsst-c++ -*-
                    #include 
                    
                    #include "boost/iterator/transform_iterator.hpp"
                    
                    #include "lsst/afw/table/io/FitsWriter.h"
                    #include "lsst/afw/table/Source.h"
                    #include "lsst/afw/table/detail/Access.h"
                    #include "lsst/afw/image/Wcs.h"
                    #include "lsst/afw/detection/FootprintCtrl.h"
                    #include "lsst/afw/detection/HeavyFootprint.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/table/io/InputArchive.h"
                    
    
    15 d6480e01 - // Some boilerplate macros for saving/loading Source slot aliases to/from FITS headers.
    16 d6480e01 - // Didn't seem to be quite enough to give the file the full M4 treatment.
    17 d6480e01 -
    18 6581586d - #define SAVE_MEAS_SLOT(NAME, Name, TYPE, Type) \
    19 6581586d - if (table->get ## Name ## Type ## Key().isValid()) { \
    20 5f0980b1 - std::string s = table->getSchema().find(table->get ## Name ## Type ## Key()).field.getName(); \
    21 5f0980b1 - std::replace(s.begin(), s.end(), '.', '_'); \
    22 813b4228 - _fits->writeKey(#NAME #TYPE "_SLOT", s.c_str(), "Defines the " #Name #Type " slot"); \
    23 5f0980b1 - } \
    24 6581586d - if (table->get ## Name ## Type ## ErrKey().isValid()) { \
    25 6581586d - std::string s = table->getSchema().find(table->get ## Name ## Type ## ErrKey()).field.getName(); \
    26 5f0980b1 - std::replace(s.begin(), s.end(), '.', '_'); \
    27 813b4228 - _fits->writeKey(#NAME #TYPE "_ERR_SLOT", s.c_str(), \
    28 6581586d - "Defines the " #Name #Type "Err slot"); \
    29 6581586d - } \
    30 6581586d - if (table->get ## Name ## Type ## Flag ## Key().isValid()) { \
    31 6581586d - std::string s = table->getSchema().find(table->get ## Name ## Type ## FlagKey()).field.getName(); \
    32 6581586d - std::replace(s.begin(), s.end(), '.', '_'); \
    33 813b4228 - _fits->writeKey(#NAME #TYPE "_FLAG_SLOT", s.c_str(), \
    34 6581586d - "Defines the " #Name #Type "Flag slot"); \
    35 5f0980b1 - }
    36 5f0980b1 -
    37 813b4228 - #define SAVE_FLUX_SLOT(NAME, Name) SAVE_MEAS_SLOT(NAME ## _, Name, FLUX, Flux)
    38 6581586d - #define SAVE_CENTROID_SLOT() SAVE_MEAS_SLOT(, , CENTROID, Centroid)
    39 6581586d - #define SAVE_SHAPE_SLOT() SAVE_MEAS_SLOT(, , SHAPE, Shape)
    40 5f0980b1 -
    41 6581586d - #define LOAD_MEAS_SLOT(NAME, Name, TYPE, Type) \
    42 5f0980b1 - { \
    43 1f3aeb26 - _fits->behavior &= ~fits::Fits::AUTO_CHECK; \
    44 6581586d - std::string s, sErr, sFlag; \
    45 813b4228 - _fits->readKey(#NAME #TYPE "_SLOT", s); \
    46 813b4228 - _fits->readKey(#NAME #TYPE "_ERR_SLOT", sErr); \
    47 813b4228 - _fits->readKey(#NAME #TYPE "_FLAG_SLOT", sFlag); \
    48 5f0980b1 - if (_fits->status == 0) { \
    49 813b4228 - metadata->remove(#NAME #TYPE "_SLOT"); \
    50 813b4228 - metadata->remove(#NAME #TYPE "_ERR_SLOT"); \
    51 813b4228 - metadata->remove(#NAME #TYPE "_FLAG_SLOT"); \
    52 5f0980b1 - std::replace(s.begin(), s.end(), '_', '.'); \
    53 5f0980b1 - std::replace(sErr.begin(), sErr.end(), '_', '.'); \
    54 813b4228 - std::replace(sFlag.begin(), sFlag.end(), '_', '.'); \
    55 6581586d - table->define ## Name ## Type(schema[s], schema[sErr], schema[sFlag]); \
    56 5f0980b1 - } else { \
    57 5f0980b1 - _fits->status = 0; \
    58 5f0980b1 - } \
    59 1f3aeb26 - _fits->behavior |= fits::Fits::AUTO_CHECK; \
    60 5f0980b1 - }
    61 5f0980b1 -
    62 5f0980b1 -
    63 813b4228 - #define LOAD_FLUX_SLOT(NAME, Name) LOAD_MEAS_SLOT(NAME ## _, Name, FLUX, Flux)
    64 6581586d - #define LOAD_CENTROID_SLOT() LOAD_MEAS_SLOT(, , CENTROID, Centroid)
    65 6581586d - #define LOAD_SHAPE_SLOT() LOAD_MEAS_SLOT(, , SHAPE, Shape)
    66 5f0980b1 -
    namespace lsst { namespace afw { namespace table { //----------------------------------------------------------------------------------------------------------- //----- Private SourceTable/Record classes ------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------- // These private derived classes are what you actually get when you do SourceTable::make; like the // private classes in BaseTable.cc, it's more convenient to have an extra set of trivial derived // classes than to do a lot of friending. namespace { class SourceTableImpl; class SourceRecordImpl : public SourceRecord { public: explicit SourceRecordImpl(PTR(SourceTable) const & table) : SourceRecord(table) {} }; class SourceTableImpl : public SourceTable { public: explicit SourceTableImpl(Schema const & schema, PTR(IdFactory) const & idFactory) : SourceTable(schema, idFactory) {} SourceTableImpl(SourceTableImpl const & other) : SourceTable(other) {} private: virtual PTR(BaseTable) _clone() const { return boost::make_shared(*this); } virtual PTR(BaseRecord) _makeRecord() { PTR(SourceRecord) record = boost::make_shared(getSelf()); if (getIdFactory()) record->setId((*getIdFactory())()); return record; }
    56 03ea6486 + };
    57 03ea6486 +
    58 d6480e01 + } // anonymous
    59 03ea6486 +
    60 d6480e01 + //-----------------------------------------------------------------------------------------------------------
    61 192c1d9f + //----- PersistenceHelpers ----------------------------------------------------------------------------------
    62 192c1d9f + //-----------------------------------------------------------------------------------------------------------
    63 192c1d9f +
    64 192c1d9f +
    65 192c1d9f + namespace {
    66 192c1d9f +
    67 192c1d9f + struct PersistenceHelper {
    68 192c1d9f + SchemaMapper mapper;
    69 192c1d9f + afw::table::Key footprintKey;
    }; } // anonymous //----------------------------------------------------------------------------------------------------------- //----- SourceFitsWriter ------------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------- // A custom FitsWriter for Sources. It also sets the AFW_TYPE key to SOURCE, which should // ensure we use SourceFitsReader to read it. // Because it also holds Footprints, a SourceCatalog isn't persisted with the same Schema // it has in-memory; instead, it's saved in a Schema that has an additional int field // appended to the end, which contains the afw::table::io "archive ID" that's used to // extract the Footprint from additional FITS HDUs. (If we disable saving Footprints via // SourceFitsFlags, we do save using the original Schema). // The only public access point to this class is SourceTable::makeFitsWriter. If we // subclass SourceTable someday, it may be necessary to put SourceFitsWriter in a header // file so we can subclass it too. namespace { class SourceFitsWriter : public io::FitsWriter { public: explicit SourceFitsWriter(Fits * fits, int flags) : io::FitsWriter(fits, flags) {} protected:
    139 d6480e01 -
    101 0c8edce7 +
    virtual void _writeTable(CONST_PTR(BaseTable) const & table, std::size_t nRows); virtual void _writeRecord(BaseRecord const & record); virtual void _finish() { if (!(_flags & SOURCE_IO_NO_FOOTPRINTS)) { _archive.writeFits(*_fits); } } private: SchemaMapper _mapper; PTR(BaseRecord) _outRecord; PTR(BaseTable) _outTable; Key _footprintKey; io::OutputArchive _archive; }; void SourceFitsWriter::_writeTable(CONST_PTR(BaseTable) const & t, std::size_t nRows) { CONST_PTR(SourceTable) table = boost::dynamic_pointer_cast(t); if (!table) { throw LSST_EXCEPT(
    162 03ea6486 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    124 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot use a SourceFitsWriter on a non-Source table." ); } if (!(_flags & SOURCE_IO_NO_FOOTPRINTS)) {
    167 ad8a441b - _mapper = SchemaMapper(t->getSchema()) ;
    129 f1760fcb + _mapper = SchemaMapper(t->getSchema(), true) ;
    ? ++++++ _mapper.addMinimalSchema(t->getSchema(), true); _footprintKey = _mapper.editOutputSchema().addField("footprint", "archive ID for Footprint"); _outTable = BaseTable::make(_mapper.getOutputSchema()); PTR(daf::base::PropertyList) metadata = table->getMetadata(); if (metadata) { metadata = boost::static_pointer_cast(metadata->deepCopy()); } else { metadata.reset(new daf::base::PropertyList()); } // HDU 1 is empty (primary HDU can't be a table) // HDU 2 is the SourceCatalog's records // HDU 3 is the index for the afw::table::io archive that holds more complex objects metadata->set( "AR_HDU", 3, "HDU containing the archive index for non-record data (e.g. Footprints)" ); _outTable->setMetadata(metadata); _outRecord = _outTable->makeRecord(); // make temporary record to use as a workspace io::FitsWriter::_writeTable(_outTable, nRows); } else { io::FitsWriter::_writeTable(table, nRows); } _fits->writeKey("AFW_TYPE", "SOURCE", "Tells lsst::afw to load this as a Source table.");
    190 5f0980b1 - SAVE_FLUX_SLOT(PSF, Psf);
    191 5f0980b1 - SAVE_FLUX_SLOT(MODEL, Model);
    192 5f0980b1 - SAVE_FLUX_SLOT(AP, Ap);
    193 5f0980b1 - SAVE_FLUX_SLOT(INST, Inst);
    194 62ae3464 - SAVE_FLUX_SLOT(INST, Calib);
    195 5f0980b1 - SAVE_CENTROID_SLOT();
    196 5f0980b1 - SAVE_SHAPE_SLOT();
    } void SourceFitsWriter::_writeRecord(BaseRecord const & r) { SourceRecord const & record = static_cast(r); if (!(_flags & SOURCE_IO_NO_FOOTPRINTS)) { _outRecord->assign(record, _mapper); PTR(afw::detection::Footprint) footprint = record.getFootprint(); if (footprint) { if ((_flags & SOURCE_IO_NO_HEAVY_FOOTPRINTS) && footprint->isHeavy()) { footprint.reset(new afw::detection::Footprint(*footprint)); } int footprintArchiveId = _archive.put(footprint); _outRecord->set(_footprintKey, footprintArchiveId); } io::FitsWriter::_writeRecord(*_outRecord); } else { io::FitsWriter::_writeRecord(record); } } } // anonymous //----------------------------------------------------------------------------------------------------------- //----- SourceFitsReader ------------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------- // A custom FitsReader for Sources - this reads footprints as variable-length arrays, and adds header // keys that define the slots. It gets registered with name SOURCE, so it should get used whenever // we read a table with AFW_TYPE set to that value. // As noted in the comments for SourceFitsWriter, we have to modify the Schema by adding a column for the // Footprint archive ID when we save a SourceCatalog. // Things are a bit more complicated than that when reading, because we also need to be able to read files // saved with an older version of the pipeline, in which there were 2-5 additional columns, all variable- // length arrays, holding the Spans, Peaks, and HeavyFootprint arrays. Those are handled by explicit // calls to the FITS I/O routines here. // The only public access point to this class is through the registry. If we subclass SourceTable // someday, it may be necessary to put SourceFitsReader in a header file so we can subclass it too. namespace { class SourceFitsReader : public io::FitsReader { public: // The archive argument here was added to all the derived-class FitsReader classes, just to support // one use case with ExposureCatalog (which is unusual in that it's used to implement afw::table::io // persistence for other objects e.g. CoaddPsf, but also uses afw::table::io persistence to save // itself). SourceCatalog now does the latter, but not the former, so we'll continue ignoring this // archive argument and creating our own. And hope someday we have time to clean up this hack. explicit SourceFitsReader(Fits * fits, PTR(io::InputArchive) archive, int flags) : io::FitsReader(fits, archive, flags), _spanCol(-1), _peakCol(-1), _heavyPixCol(-1), _heavyMaskCol(-1), _heavyVarCol(-1) { if (archive) { throw LSST_EXCEPT(
    253 ad8a441b - pex::exceptions::LogicErrorException,
    ? ---------
    208 44b7b576 + pex::exceptions::LogicError,
    "SourceCatalog does not support reading from an external archive" ); } } protected: virtual PTR(BaseTable) _readTable(); virtual PTR(BaseRecord) _readRecord(PTR(BaseTable) const & table); private: PTR(BaseTable) _inTable; PTR(io::InputArchive) _archive; SchemaMapper _mapper; Key _footprintKey; int _spanCol; // all *Col data members are for backwards-compatibility reading of old int _peakCol; // Footprint persistence int _heavyPixCol; int _heavyMaskCol; int _heavyVarCol; }; namespace { // Predicate for SchemaMapper::addMappingsWhere to map all fields in a schema except the one holding // the Footprint's archive ID. struct FieldIsNotFootprint { template bool operator()(SchemaItem const & item) const { return true; } bool operator()(SchemaItem const & item) const { return item.field.getName() != "footprint"; } }; } // anonymous PTR(BaseTable) SourceFitsReader::_readTable() { PTR(daf::base::PropertyList) metadata = boost::make_shared(); _fits->readMetadata(*metadata, true);
    297 813b4228 - if (metadata->exists("AFW_TYPE")) metadata->remove("AFW_TYPE");
    // if there's an archive attached, it's the new way of persisting Footprints int archiveHdu = metadata->get("AR_HDU", -1); if (archiveHdu > 0) { // If we have an AR_HDU key, we have new-style persistence of Footprints, // using afw::table::io archives. We strip the key from the metadata, but we // don't read the archive if the flags tell us not to. metadata->remove("AR_HDU"); if (!(_flags & SOURCE_IO_NO_FOOTPRINTS)) { int oldHdu = _fits->getHdu(); _fits->setHdu(archiveHdu); _archive.reset(new io::InputArchive(io::InputArchive::readFits(*_fits))); _fits->setHdu(oldHdu); } } else { // Old-style persistence of Footprints, for backwards compatibility, OR we didn't persist the // Footprints at all. If it's old-style persistence, we remove the appropriate Keys from the // metadata before we construct a Schema, to keep those fields from getting added to the Schema. // If we just didn't persist any Footprints, then none of these keys should be present, and // we don't have to do anything to get the Schema we want. _spanCol = metadata->get("SPANCOL", 0); if (_spanCol > 0) { metadata->remove("SPANCOL"); metadata->remove((boost::format("TTYPE%d") % _spanCol).str()); metadata->remove((boost::format("TFORM%d") % _spanCol).str()); } _peakCol = metadata->get("PEAKCOL", 0); if (_peakCol > 0) { metadata->remove("PEAKCOL"); metadata->remove((boost::format("TTYPE%d") % _peakCol).str()); metadata->remove((boost::format("TFORM%d") % _peakCol).str()); } _heavyPixCol = metadata->get("HVYPIXCO", 0); if (_heavyPixCol > 0) { metadata->remove("HVYPIXCO"); metadata->remove((boost::format("TTYPE%d") % _heavyPixCol).str()); metadata->remove((boost::format("TFORM%d") % _heavyPixCol).str()); } _heavyMaskCol = metadata->get("HVYMSKCO", 0); if (_heavyMaskCol > 0) { metadata->remove("HVYMSKCO"); metadata->remove((boost::format("TTYPE%d") % _heavyMaskCol).str()); metadata->remove((boost::format("TFORM%d") % _heavyMaskCol).str()); metadata->remove((boost::format("TZERO%d") % _heavyMaskCol).str()); metadata->remove((boost::format("TSCAL%d") % _heavyMaskCol).str()); } _heavyVarCol = metadata->get("HVYVARCO", 0); if (_heavyVarCol > 0) { metadata->remove("HVYVARCO"); metadata->remove((boost::format("TTYPE%d") % _heavyVarCol).str()); metadata->remove((boost::format("TFORM%d") % _heavyVarCol).str()); } --_spanCol; // switch to 0-indexed rather than 1-indexed convention. --_peakCol; --_heavyPixCol; --_heavyMaskCol; --_heavyVarCol; } Schema schema(*metadata, true); if (archiveHdu > 0) { // If an archive was present, regardless of whether or not we actually read it, the Schema we just // constructed has an extra int field holding the Footprint archive IDs. // We need to create a SchemaMapper to go from that Schema to one without those ints (even if we // aren't reading the Footprints), and an intermediate BaseTable with that Schema. // This table being non-null is what we'll use later to indicate whether we need to use the // SchemaMapper.
    363 ad8a441b - _mapper = SchemaMapper(schema);
    317 f1760fcb + _mapper = SchemaMapper(schema, true);
    ? ++++++ _mapper.addMappingsWhere(FieldIsNotFootprint()); _inTable = BaseTable::make(schema); _footprintKey = schema["footprint"]; schema = _mapper.getOutputSchema(); } PTR(SourceTable) table = SourceTable::make(schema, PTR(IdFactory)());
    324 bc5cccae + table->setMetadata(metadata);
    370 5f0980b1 - LOAD_FLUX_SLOT(PSF, Psf);
    371 5f0980b1 - LOAD_FLUX_SLOT(MODEL, Model);
    372 5f0980b1 - LOAD_FLUX_SLOT(AP, Ap);
    373 5f0980b1 - LOAD_FLUX_SLOT(INST, Inst);
    374 62ae3464 - LOAD_FLUX_SLOT(INST, Calib);
    375 5f0980b1 - LOAD_CENTROID_SLOT();
    376 5f0980b1 - LOAD_SHAPE_SLOT();
    _startRecords(*table);
    378 813b4228 - table->setMetadata(metadata);
    return table; } PTR(BaseRecord) SourceFitsReader::_readRecord(PTR(BaseTable) const & table) { PTR(SourceRecord) record; if (_inTable) { // New-style persisted Footprints PTR(BaseRecord) inRecord = io::FitsReader::_readRecord(_inTable); if (inRecord) { record = boost::static_pointer_cast(table->makeRecord()); record->assign(*inRecord, _mapper); if (_archive) { // archive is only initialized if we should read Footprints PTR(afw::detection::Footprint) footprint = _archive->get(inRecord->get(_footprintKey)); if (footprint && footprint->isHeavy() && (_flags & SOURCE_IO_NO_HEAVY_FOOTPRINTS)) { // It sort of defeats the purpose of the flag if we have to do the I/O to read // a HeavyFootprint before we can downgrade it to a regular Footprint, but that's // what we're going to do - at least this will save on on some memory usage, which // might still be useful. That's far from ideal, but it'd be really hard to fix // (because we have no way to pass something like the flags to the InputArchive). // The good news is that if someone's concerned about performance of reading // SourceCatalogs, they'll almost certainly use SOURCE_IO_NO_FOOTPRINTS, which // will do what we want. SOURCE_IO_NO_HEAVY_FOOTPRINTS is more useful for writing // sources, and that works just fine. footprint.reset(new afw::detection::Footprint(*footprint)); } record->setFootprint(footprint); } return record; } else { return record; } } // Old-style persisted Footprints, or no persisted Footprints. record = boost::static_pointer_cast(io::FitsReader::_readRecord(table)); if (_flags & SOURCE_IO_NO_FOOTPRINTS || !record) return record; int spanElementCount = (_spanCol >= 0) ? _fits->getTableArraySize(_row, _spanCol) : 0; int peakElementCount = (_peakCol >= 0) ? _fits->getTableArraySize(_row, _peakCol) : 0; int heavyPixElementCount = (_heavyPixCol >= 0) ? _fits->getTableArraySize(_row, _heavyPixCol) : 0; int heavyMaskElementCount = (_heavyMaskCol >= 0) ? _fits->getTableArraySize(_row, _heavyMaskCol) : 0; int heavyVarElementCount = (_heavyVarCol >= 0) ? _fits->getTableArraySize(_row, _heavyVarCol) : 0; if (spanElementCount || peakElementCount) { PTR(Footprint) fp = boost::make_shared(); if (spanElementCount) { if (spanElementCount % 3) { throw LSST_EXCEPT( afw::fits::FitsError, afw::fits::makeErrorMessage( _fits->fptr, _fits->status, boost::format("Number of span elements (%d) must divisible by 3 (row %d)") % spanElementCount % _row ) ); } std::vector spanElements(spanElementCount); _fits->readTableArray(_row, _spanCol, spanElementCount, &spanElements.front()); std::vector::iterator j = spanElements.begin(); while (j != spanElements.end()) { int y = *j++; int x0 = *j++; int x1 = *j++; fp->addSpan(y, x0, x1); } } if (peakElementCount) { if (peakElementCount % 3) { throw LSST_EXCEPT( afw::fits::FitsError, afw::fits::makeErrorMessage( _fits->fptr, _fits->status, boost::format("Number of peak elements (%d) must divisible by 3 (row %d)") % peakElementCount % _row ) ); } std::vector peakElements(peakElementCount); _fits->readTableArray(_row, _peakCol, peakElementCount, &peakElements.front()); std::vector::iterator j = peakElements.begin(); while (j != peakElements.end()) { float x = *j++; float y = *j++; float value = *j++; fp->addPeak(x, y, value); } } record->setFootprint(fp); if ( !(_flags & SOURCE_IO_NO_HEAVY_FOOTPRINTS) && heavyPixElementCount && heavyMaskElementCount && heavyVarElementCount ) { int N = fp->getArea(); if ((heavyPixElementCount != N) || (heavyMaskElementCount != N) || (heavyVarElementCount != N)) { throw LSST_EXCEPT( afw::fits::FitsError, afw::fits::makeErrorMessage( _fits->fptr, _fits->status, boost::format("Number of HeavyFootprint elements (pix %d, mask %d, var %d) must all be equal to footprint area (%d)") % heavyPixElementCount % heavyMaskElementCount % heavyVarElementCount % N )); } // float HeavyFootprints were the only kind we ever saved using the old format typedef detection::HeavyFootprint HeavyFootprint; PTR(HeavyFootprint) heavy = boost::make_shared(*fp); _fits->readTableArray(_row, _heavyPixCol, N, heavy->getImageArray().getData()); _fits->readTableArray(_row, _heavyMaskCol, N, heavy->getMaskArray().getData()); _fits->readTableArray(_row, _heavyVarCol, N, heavy->getVarianceArray().getData()); record->setFootprint(heavy); } } return record; } // registers the reader so FitsReader::make can use it. static io::FitsReader::FactoryT sourceFitsReaderFactory("SOURCE"); } // anonymous //----------------------------------------------------------------------------------------------------------- //----- SourceTable/Record member function implementations -------------------------------------------------- //----------------------------------------------------------------------------------------------------------- SourceRecord::SourceRecord(PTR(SourceTable) const & table) : SimpleRecord(table) {} void SourceRecord::updateCoord(image::Wcs const & wcs) { set(SourceTable::getCoordKey(), *wcs.pixelToSky(getCentroid())); } void SourceRecord::updateCoord(image::Wcs const & wcs, Key< Point > const & key) { set(SourceTable::getCoordKey(), *wcs.pixelToSky(get(key))); } void SourceRecord::_assign(BaseRecord const & other) { try { SourceRecord const & s = dynamic_cast(other); _footprint = s._footprint; } catch (std::bad_cast&) {} } PTR(SourceTable) SourceTable::make(Schema const & schema, PTR(IdFactory) const & idFactory) { if (!checkSchema(schema)) { throw LSST_EXCEPT(
    522 03ea6486 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    469 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Schema for Source must contain at least the keys defined by getMinimalSchema()." ); } return boost::make_shared(schema, idFactory); } SourceTable::SourceTable( Schema const & schema, PTR(IdFactory) const & idFactory
    532 fbdf0845 - ) : SimpleTable(schema, idFactory) {}
    479 0c8edce7 + ) : SimpleTable(schema, idFactory), _slots(schema) {}
    ? ++++++++++++++++ SourceTable::SourceTable(SourceTable const & other) :
    482 0c8edce7 + SimpleTable(other), _slots(other._slots)
    535 6ac30ab0 - SimpleTable(other),
    536 fbdf0845 - _slotFlux(other._slotFlux), _slotCentroid(other._slotCentroid), _slotShape(other._slotShape)
    {}
    484 03ea6486 +
    485 e1fc4de2 + void SourceTable::handleAliasChange(std::string const & alias) {
    486 0c8edce7 + if (alias.compare(0, 4, "slot") != 0) {
    487 e1fc4de2 + return;
    488 e1fc4de2 + }
    489 0c8edce7 + _slots.handleAliasChange(alias, getSchema());
    490 e1fc4de2 + }
    SourceTable::MinimalSchema::MinimalSchema() { schema = SimpleTable::makeMinimalSchema(); parent = schema.addField("parent", "unique ID of parent source"); schema.getCitizen().markPersistent(); } SourceTable::MinimalSchema & SourceTable::getMinimalSchema() { static MinimalSchema it; return it; } PTR(io::FitsWriter) SourceTable::makeFitsWriter(fits::Fits * fitsfile, int flags) const { return boost::make_shared(fitsfile, flags); }
    554 d6480e01 - //-----------------------------------------------------------------------------------------------------------
    555 d6480e01 - //----- Convenience functions for adding common measurements to Schemas -------------------------------------
    556 d6480e01 - //-----------------------------------------------------------------------------------------------------------
    557 d6480e01 -
    558 6581586d - KeyTuple addCentroidFields(
    559 6581586d - Schema & schema,
    560 6581586d - std::string const & name,
    561 6581586d - std::string const & doc
    562 6581586d - ) {
    563 6581586d - KeyTuple keys;
    564 6581586d - keys.meas = schema.addField(name, doc, "pixels");
    565 6581586d - keys.err = schema.addField(
    566 0d36a22f - name + ".err", "covariance matrix for " + name, "pixels^2"
    567 6581586d - );
    568 b3c7db23 - keys.flag = schema.addField(
    569 b3c7db23 - name + ".flags", "set if the " + name + " measurement did not fully succeed"
    570 b3c7db23 - );
    571 6581586d - return keys;
    572 6581586d - }
    573 6581586d -
    574 6581586d - KeyTuple addShapeFields(
    575 6581586d - Schema & schema,
    576 6581586d - std::string const & name,
    577 6581586d - std::string const & doc
    578 6581586d - ) {
    579 6581586d - KeyTuple keys;
    580 6581586d - keys.meas = schema.addField(
    581 6581586d - name, doc, "pixels^2"
    582 6581586d - );
    583 6581586d - keys.err = schema.addField(
    584 0d36a22f - name + ".err", "covariance matrix for " + name, "pixels^4"
    585 6581586d - );
    586 b3c7db23 - keys.flag = schema.addField(
    587 b3c7db23 - name + ".flags", "set if the " + name + " measurement failed"
    588 b3c7db23 - );
    589 6581586d - return keys;
    590 6581586d - }
    591 6581586d -
    592 6581586d - KeyTuple addFluxFields(
    593 6581586d - Schema & schema,
    594 6581586d - std::string const & name,
    595 6581586d - std::string const & doc
    596 6581586d - ) {
    597 6581586d - KeyTuple keys;
    598 6581586d - keys.meas = schema.addField(
    599 6581586d - name, doc, "dn"
    600 6581586d - );
    601 6581586d - keys.err = schema.addField(
    602 6581586d - name + ".err", "uncertainty for " + name, "dn"
    603 6581586d - );
    604 b3c7db23 - keys.flag = schema.addField(
    605 b3c7db23 - name + ".flags", "set if the " + name + " measurement failed"
    606 b3c7db23 - );
    607 6581586d - return keys;
    608 6581586d - }
    template class CatalogT; template class CatalogT; template class SortedCatalogT; template class SortedCatalogT; }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0d36a22f

    commit 0d36a22f588e024cc16a862666503d20ebd1a00b
    Author: Jim Bosch 
    Date:   Thu Feb 2 15:39:14 2012 -0500
    
        more flag->flags renames, fixed swig dangling references in SchemaItem, added name-based accessors to BaseRecord
    

    d6480e01

    commit d6480e01cf98ec6e6ebea9b7f58d2d9dcef6beef
    Author: Jim Bosch 
    Date:   Sun Feb 5 23:11:25 2012 -0500
    
        lots of documentation, and a little refactoring to improve readability
    

    ad8a441b

    commit ad8a441b6f9f2e08b4381ac3b2f1e5ca8e256a96
    Author: Jim Bosch 
    Date:   Fri Dec 12 14:53:49 2014 -0500
    
        Change Source to use afw::table::io persistence for Footprints
    

    b3c7db23

    commit b3c7db23c4a64a24d495e8e34371cfbe02690a8b
    Author: Jim Bosch 
    Date:   Thu Feb 2 11:09:41 2012 -0500
    
        changed name of standard flag fields to '.flags'; works better when it's a base for multiple flags
    

    fbdf0845

    commit fbdf08458f287be72ad231a0e50fa3c519941fb6
    Author: Jim Bosch 
    Date:   Tue Jun 18 18:56:39 2013 -0600
    
        Use Catalog I/O flags to control writing of Source footprints
        
        This replaces the previous mechanism for controlling whether
        to write heavy footprints, which involved a SourceTable data
        member.
    

    1f3aeb26

    commit 1f3aeb26976b3b4d70f83ea828e8d1c62ca43fc5
    Author: Jim Bosch 
    Date:   Sat Feb 25 16:11:45 2012 -0500
    
        cherry-pick (not quite automatic) of 057928; first of several to improve table FITS support without merging all the image FITS changes
    

    6ac30ab0

    commit 6ac30ab06cdd0a18a6a8874f49e5e7e28ddf788d
    Author: Jim Bosch 
    Date:   Fri Feb 24 00:47:17 2012 -0500
    
        made SimpleTable/Record the base class for SourceTable/Record, removed SourceCatalogT (SimpleCatalogT is sufficient)
    

    5f0980b1

    commit 5f0980b13f25349d67fd8c160519ed0fe11450e7
    Author: Jim Bosch 
    Date:   Sun Jan 29 00:12:48 2012 -0500
    
        fixed period-handling bug in table FITS reading, added slot reading/writing in FITS
    

    03ea6486

    commit 03ea6486684bf284f7428c2f7cec0fc15b7c6172
    Author: Jim Bosch 
    Date:   Thu Jan 26 18:11:15 2012 -0500
    
        afw now building successfully, but with limited SWIG for table and corresponding unit test failures
    

    813b4228

    commit 813b4228386f4cd6e022b175cf9b3466d58b28a1
    Author: Jim Bosch 
    Date:   Wed Feb 8 22:41:54 2012 -0500
    
        added flexible metadata to BaseTable (read-only persistence so far)
    

    62ae3464

    commit 62ae3464e75d4dbd7f7ee3e3ddcc9b3a941f880c
    Author: Jim Bosch 
    Date:   Mon Dec 8 21:19:28 2014 -0500
    
        Add Source slot for calibration fluxes: CalibFlux
    

    6581586d

    commit 6581586d25bea008aadd57a10968ca6c9fb72677
    Author: Jim Bosch 
    Date:   Mon Jan 30 01:09:10 2012 -0500
    
        fixed bug in schema key-based lookups, added flag fields to standard measurements
    

    Commits in /Users/nate/repos_lsst/afw/

    0c8edce7

    commit 0c8edce7dfb2db4539497ac18187e75d2494f4e4
    Author: Jim Bosch 
    Date:   Mon Aug 25 01:48:39 2014 -0400
    
        Switch to new slot definition classes, using aliases for version>0
    

    d6480e01

    commit d6480e01cf98ec6e6ebea9b7f58d2d9dcef6beef
    Author: Jim Bosch 
    Date:   Sun Feb 5 23:11:25 2012 -0500
    
        lots of documentation, and a little refactoring to improve readability
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    44b7b576

    commit 44b7b576400aaf0a24c413114e047ccf3f34a29b
    Author: Lauren MacArthur 
    Date:   Thu Apr 2 17:39:06 2015 -0400
    
        Remove trailing Exception in exception names
    

    f1760fcb

    commit f1760fcb7952e5dbf1baf526b40e502027f30491
    Author: Jim Bosch 
    Date:   Tue Apr 14 19:09:13 2015 -0400
    
        Make transfer of aliases in SchemaMapper optional.
        
        The previous change to always transfer aliases in SchemaMapper
        broke existing code; this change reverts to the original behavior,
        with an easy option for to transfer aliases if desired (which is now
        used by SourceTable and ExposureTable).
    

    192c1d9f

    commit 192c1d9fe14f2daedc6cc6fc908cfc8a391de110
    Author: Jim Bosch 
    Date:   Wed Nov 26 11:35:51 2014 -0500
    
        Change Source to use afw::table::io persistence for Footprints
        
        Conflicts:
            src/table/Source.cc
            tests/testSourceTable.py
    

    03ea6486

    commit 03ea6486684bf284f7428c2f7cec0fc15b7c6172
    Author: Jim Bosch 
    Date:   Thu Jan 26 18:11:15 2012 -0500
    
        afw now building successfully, but with limited SWIG for table and corresponding unit test failures
    

    bc5cccae

    commit bc5cccaefd7b295975759bfd5213afb4e79a8f9e
    Author: Perry Gee 
    Date:   Mon Apr 14 12:45:10 2014 -0500
    
        Change to the _readTable routines in these 4 types plus BaseTable so that the
        AFW_TABLE_VERSION entry in the header is used to version each type of table.
        The getVersion() routine from BaseTable is used to get the version number during
        save, and it is written to the metadata of the table before the metadata is persisted.
        
        On read, the metadata is searched at the beginning of FitsReader::_startRecords,
        and the version number is set on the table then.  The table-getMetadata() is cleansed.
        I also moved the removal code for AFW_TYPE to here.
        
        Jim, please check the code to be sure that there are not unintended consquences from
        moving the table->setMetadata to the middle of the _readTable routines
    

    e1fc4de2

    commit e1fc4de2138439c6b6e81ef34b15b92da48d3566
    Author: Jim Bosch 
    Date:   Mon Aug 18 16:58:07 2014 -0400
    
        Remove old slot definers from SourceTable
    

    Return to list

    include/lsst/afw/cameraGeom/Orientation.h

    Diff:

                    /* 
                     * LSST Data Management System
    
    3 a6d55f08 - * Copyright 2008, 2009, 2010 LSST Corporation.
    3 a5c76748 + * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014 LSST Corporation.
    ? ++++++++++++++++++++++++ * * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the LSST License Statement and * the GNU General Public License along with this program. If not, * see . */ #if !defined(LSST_AFW_CAMERAGEOM_ORIENTATION_H) #define LSST_AFW_CAMERAGEOM_ORIENTATION_H #include #include
    28 47d30d84 + #include "Eigen/Dense"
    28 df438a72 - #include "lsst/afw/geom/Angle.h"
    ? ------
    29 47d30d84 + #include "lsst/afw/geom.h"
    #include "lsst/afw/image/Utils.h" /** * @file * * Describe a Detector's orientation */ namespace lsst { namespace afw { namespace cameraGeom {
    40 56044208 +
    39 df438a72 - #if defined(SWIG)
    40 0efdb5e2 - // swig generates incorrect python bindings, putting e.g. "pitch = 0*lsst::afw::geom::radians" into
    41 0efdb5e2 - // the .py file. The other part of the workaround is to make the symbol "radian" available to python
    42 0efdb5e2 - // in cameraGeomLib.i
    43 df438a72 - #define AFW_GEOM_RADIANS radians
    44 df438a72 - #else
    45 df438a72 - #define AFW_GEOM_RADIANS lsst::afw::geom::radians
    46 df438a72 - #endif
    /**
    48 4b6acf34 - * Describe a detector's orientation with respect to the nominal position
    ? - ^^^^^^^^^^^^^ ^ ^^^ ^^^^^^
    42 04332f69 + * Describe a detector's orientation in the focal plane
    ? ^ ^ ^ ^^ + *
    50 9e5b4bd9 - * Only the yaw angle is used when computing the mapping between detector and focal plane coordinates.
    51 9e5b4bd9 - * All rotations are about the origin of the trimmed detector coordinate system, NOT the center.
    44 04332f69 + * All rotations are about the reference point on the detector.
    45 04332f69 + * Rotations are intrinsic, meaning each rotation is applied in the coordinates system
    46 04332f69 + * produced by the previous rotation.
    47 4d5e59aa + * Rotations are applied in this order: yaw (Z), pitch (Y'), and roll (X'').
    48 04332f69 + *
    49 04332f69 + * @warning: default refPoint is -0.5, -0.5 (the lower left corner of a detector).
    50 04332f69 + * This means that the default-constructed Orientation is not a unity transform,
    51 04332f69 + * but instead includes a 1/2 pixel shift.
    */ class Orientation { public:
    55 04332f69 + explicit Orientation(
    56 04332f69 + geom::Point2D const fpPosition=geom::Point2D(0, 0),
    57 04332f69 + ///< Focal plane position of detector reference point (mm)
    58 04332f69 + geom::Point2D const refPoint=geom::Point2D(-0.5, -0.5),
    59 04332f69 + ///< Reference point on detector (pixels).
    60 04332f69 + ///< Offset is measured to this point and all all rotations are about this point.
    61 04332f69 + ///< The default value (-0.5, -0.5) is the lower left corner of the detector.
    62 04332f69 + geom::Angle const yaw=geom::Angle(0), ///< yaw: rotation about Z (X to Y), 1st rotation
    63 4d5e59aa + geom::Angle const pitch=geom::Angle(0), ///< pitch: rotation about Y' (Z'=Z to X'), 2nd rotation
    64 4d5e59aa + geom::Angle const roll=geom::Angle(0) ///< roll: rotation about X'' (Y''=Y' to Z''), 3rd rotation
    65 47d30d84 + );
    55 4b6acf34 - explicit Orientation(int nQuarter = 0, ///< Nominal rotation of device in units of pi/2
    56 df438a72 - lsst::afw::geom::Angle pitch=0*AFW_GEOM_RADIANS, ///< pitch (rotation in YZ)
    57 df438a72 - lsst::afw::geom::Angle roll=0*AFW_GEOM_RADIANS, ///< roll (rotation in XZ)
    58 df438a72 - lsst::afw::geom::Angle yaw=0*AFW_GEOM_RADIANS ///< yaw (rotation in XY)
    59 53f42b75 - )
    60 d37efcde - #undef AFW_GEOM_RADIANS
    61 53f42b75 - :
    62 4b6acf34 - _nQuarter(nQuarter % 4),
    63 ffc2778f - _pitch(pitch), _cosPitch(std::cos(pitch)), _sinPitch(std::sin(pitch)),
    64 ffc2778f - _roll(roll), _cosRoll(std::cos(roll)), _sinRoll(std::sin(roll)),
    65 ffc2778f - _yaw(yaw), _cosYaw(std::cos(yaw)), _sinYaw(std::sin(yaw))
    66 ffc2778f - {}
    68 4b6acf34 - /// Return the number of quarter-turns applied to this detector
    69 4b6acf34 - int getNQuarter() const { return _nQuarter; }
    67 04332f69 + /// Return focal plane position of detector reference point (mm)
    68 04332f69 + geom::Point2D getFpPosition() const { return _fpPosition; }
    69 04332f69 +
    70 04332f69 + /// Return detector reference point (pixels)
    71 04332f69 + geom::Point2D getReferencePoint() const { return _refPoint; }
    72 4b6acf34 +
    73 a5c76748 + /// Return the yaw angle
    74 a5c76748 + geom::Angle getYaw() const { return _yaw; }
    /// Return the pitch angle lsst::afw::geom::Angle getPitch() const { return _pitch; }
    73 ffc2778f - /// Return cos(pitch)
    74 ffc2778f - double getCosPitch() const { return _cosPitch; }
    75 ffc2778f - /// Return sin(pitch)
    76 ffc2778f - double getSinPitch() const { return _sinPitch; }
    /// Return the roll angle
    79 df438a72 - lsst::afw::geom::Angle getRoll() const { return _roll; }
    ? -----------
    80 780e3962 + geom::Angle getRoll() const { return _roll; }
    80 ffc2778f - /// Return cos(roll)
    81 ffc2778f - double getCosRoll() const { return _cosRoll; }
    82 ffc2778f - /// Return sin(roll)
    83 ffc2778f - double getSinRoll() const { return _sinRoll; }
    85 78652121 - /// Return the yaw angle
    86 df438a72 - lsst::afw::geom::Angle getYaw() const { return _yaw; }
    87 ffc2778f - /// Return cos(yaw)
    88 ffc2778f - double getCosYaw() const { return _cosYaw; }
    89 ffc2778f - /// Return sin(yaw)
    90 ffc2778f - double getSinYaw() const { return _sinYaw; }
    82 c856a32c + /// Return the number of quarter turns (rounded to the closest quarter)
    83 47d30d84 + int getNQuarter() const;
    84 c856a32c +
    85 780e3962 + /**
    86 04332f69 + * @brief Generate an XYTransform from pixel to focal plane coordinates
    87 780e3962 + *
    88 04332f69 + * @return lsst::afw::geom::AffineXYTransform from pixel to focal plane coordinates
    89 780e3962 + */
    90 780e3962 + geom::AffineXYTransform makePixelFpTransform(
    91 780e3962 + geom::Extent2D const pixelSizeMm ///< Size of the pixel in mm in X and Y
    92 47d30d84 + ) const;
    93 780e3962 +
    94 780e3962 + /**
    95 04332f69 + * @brief Generate an XYTransform from focal plane to pixel coordinates
    96 780e3962 + *
    97 04332f69 + * @return lsst::afw::geom::AffineXYTransform from focal plane to pixel coordinates
    98 780e3962 + */
    99 7c7144b0 + geom::AffineXYTransform makeFpPixelTransform(
    100 780e3962 + geom::Extent2D const pixelSizeMm ///< Size of the pixel in mm in X and Y
    101 47d30d84 + ) const;
    102 47d30d84 +
    private:
    92 4b6acf34 - int _nQuarter; // number of quarter-turns in +ve direction
    104 04332f69 + geom::Point2D _fpPosition; ///< focal plane position of reference point on detector
    105 04332f69 + geom::Point2D _refPoint; ///< reference point on detector
    107 04332f69 + lsst::afw::geom::Angle _yaw; ///< yaw
    94 df438a72 - lsst::afw::geom::Angle _pitch; // pitch
    108 04332f69 + lsst::afw::geom::Angle _pitch; ///< pitch
    ? ++
    109 4d5e59aa + lsst::afw::geom::Angle _roll; ///< roll
    95 ffc2778f - double _cosPitch; // cos(pitch)
    96 ffc2778f - double _sinPitch; // sin(pitch)
    111 04332f69 + // Elements of the Jacobian for three space rotation projected into XY plane.
    112 606443c9 + // Turn off alignment since this is dynamically allocated (via Detector)
    113 606443c9 + Eigen::Matrix _rotMat;
    98 df438a72 - lsst::afw::geom::Angle _roll; // roll
    99 ffc2778f - double _cosRoll; // cos(roll)
    100 ffc2778f - double _sinRoll; // sin(roll)
    101 ffc2778f -
    102 df438a72 - lsst::afw::geom::Angle _yaw; // yaw
    103 ffc2778f - double _cosYaw; // cos(yaw)
    104 ffc2778f - double _sinYaw; // sin(yaw)
    }; }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4b6acf34

    commit 4b6acf347c723a61081eb7211584ce7712372ddb
    Author: rhl 
    Date:   Wed Jan 13 06:32:59 2010 +0000
    
        Got rotation of detectors by 90n degrees (and non-square dataSecs) working
    

    78652121

    commit 78652121c24a3aeaddbbbeecdbced15c38140e08
    Author: rhl 
    Date:   Fri Jan 8 19:08:35 2010 +0000
    
        Get detector centres right
    

    53f42b75

    commit 53f42b7570a1dc0914481f5557b0715606290286
    Author: rhl 
    Date:   Sun Jan 17 14:40:22 2010 +0000
    
        Make icc less unhappy; mostly unused variable and LsstImpl::toString not being virtual
    

    d37efcde

    commit d37efcdee98540d91f89a6183697cc67d8fc0923
    Author: Robert Lupton the Good 
    Date:   Mon Jun 4 20:40:23 2012 -0400
    
        Oops, let's unset the proper variable (thanks, KT)
    

    df438a72

    commit df438a724651ee2a107de2df8b27094d34d050b8
    Author: Robert Lupton the Good 
    Date:   Wed Feb 1 12:29:57 2012 -0500
    
        Use Angle for cameraGeom::Orientation; #1879
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    ffc2778f

    commit ffc2778fcf414a7bf95fdcb429cc5d14c8a079e6
    Author: rhl 
    Date:   Sat Jan 9 14:45:15 2010 +0000
    
        Got pixel -> position working.  Position -> pixel is still broken
    

    9e5b4bd9

    commit 9e5b4bd92062b8fd788ab4753ffb5ed0153f3861
    Author: Jim Bosch 
    Date:   Thu Feb 28 21:27:14 2013 +0900
    
        Improve cameraGeom::Orientation docs.
    

    0efdb5e2

    commit 0efdb5e243515f4627c69f2a7f0a9234112d3b7c
    Author: Robert Lupton the Good 
    Date:   Tue Jun 5 10:50:51 2012 -0400
    
        Clarified the necessity for the AFW_GEOM_RADIANS define
    

    Commits in /Users/nate/repos_lsst/afw/

    c856a32c

    commit c856a32c3ccde92fb10084e436529ecb2401192c
    Author: Simon Krughoff 
    Date:   Wed Mar 5 19:04:01 2014 -0600
    
        Cleaned up cameraGeom.utils and added getNQuarters to Orientation
    

    4b6acf34

    commit 4b6acf347c723a61081eb7211584ce7712372ddb
    Author: rhl 
    Date:   Wed Jan 13 06:32:59 2010 +0000
    
        Got rotation of detectors by 90n degrees (and non-square dataSecs) working
    

    04332f69

    commit 04332f6929dd397384a3b73e9d4e1bc166a7df80
    Author: Russell Owen 
    Date:   Fri Feb 14 16:48:04 2014 -0800
    
        Improved Orientation documentation.
        Reordered Orientation angle arguments in the order they are applied.
        Renamed a few Orientation arguments and getters.
        Started a unit test for orientation.
    

    780e3962

    commit 780e3962f7e3e311cbe9e1d49daf0c9db0478668
    Author: Simon Krughoff 
    Date:   Tue Feb 11 20:06:24 2014 -0600
    
        Added getters to AffineXYTransform to get the AffineTransform.  Fixed tests/testDetector.py.
    

    56044208

    commit 560442087fe3ec1f3c44e5b30ba3efff7bf782a2
    Author: Russell Owen 
    Date:   Tue Jan 28 10:06:40 2014 -0800
    
        Modified Detector to be built with a list of transforms instead of a registry
        (because a list is easier to build in python).
        Added TransformRegistry.getTransformList and the typedef TransformRegistry::TransformList.
        Removed some ugly SWIG hackery from the old Orientation class.
    

    7c7144b0

    commit 7c7144b09d8838393f1f1cc2f7fabd0d034df19c
    Author: Russell Owen 
    Date:   Tue Feb 25 10:56:44 2014 -0800
    
        Reversed the direction of transforms in TransformMap: forward is now native -> other.
        This seems to match our use cases for CameraGeom better.
        Orientation.makeFpPixelTransform now returns an AffineXYTransform.
    

    606443c9

    commit 606443c9d1cd72ed449246ea6a19568377e115a3
    Author: Kian-Tat Lim 
    Date:   Mon Mar 24 20:19:55 2014 -0700
    
        Turn off alignment of matrix in Orientation since Detector containing it is dynamically allocated.
    

    4d5e59aa

    commit 4d5e59aa91a6f812a2e2e91c2184ab639da1e8f0
    Author: Simon Krughoff 
    Date:   Fri Feb 21 14:55:00 2014 -0600
    
        Fixed documents in Orientation.h and updated testOrientation.py.  Added a PupilXYTransform which applies a plate scale and pincushion/barrel distortion to the mapping of pupil coordinates to focalplane coordinates
    

    47d30d84

    commit 47d30d844a0771f579a125f7d2af3497c76f9420
    Author: Russell Owen 
    Date:   Fri Mar 7 16:18:26 2014 -0800
    
        I implemented most of Jim's C++ suggestions from his second C++ review.
        I also broke out most of the Orientation implementation into a separate .cc file.
    

    a5c76748

    commit a5c76748dacb55b8da343ddcc9ee9df276b9a25f
    Author: Russell Owen 
    Date:   Thu Feb 27 17:05:05 2014 -0800
    
        Remove unneeded destructors from non-polymorphic classes.
    

    Return to list

    tests/imagePickle.py

    Diff:

    1 6751654c - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008-2013 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . #
    25 6751654c - import os
    import unittest import pickle import numpy import lsst.utils.tests as utilsTests import lsst.afw.coord as afwCoord import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage class ImagePickleTestCase(unittest.TestCase): """A test case for Image pickling""" def setUp(self): self.xSize = 4 self.ySize = 7 self.x0 = 567 self.y0 = 98765 def createImage(self, factory=afwImage.ImageF): image = factory(self.xSize, self.ySize) image.setXY0(afwGeom.Point2I(self.x0, self.y0)) image.getArray()[:] = self.createPattern() return image def createMaskedImage(self, factory=afwImage.MaskedImageF): image = factory(self.xSize, self.ySize) image.setXY0(afwGeom.Point2I(self.x0, self.y0)) image.getImage().getArray()[:] = self.createPattern() image.getMask().getArray()[:] = self.createPattern() image.getVariance().getArray()[:] = self.createPattern() return image def createPattern(self): yy, xx = numpy.ogrid[0:self.ySize, 0:self.xSize] # NB: numpy operates 'backwards' return self.xSize*yy + xx def assertImagesEqual(self, image, original): self.assertEqual(image.__class__.__name__, original.__class__.__name__) self.assertEqual(image.getHeight(), original.getHeight()) self.assertEqual(image.getWidth(), original.getWidth()) self.assertEqual(image.getY0(), original.getY0()) self.assertEqual(image.getX0(), original.getX0()) for x in xrange(0, original.getWidth()): for y in xrange(0, image.getHeight()): self.assertEqual(image.get(x, y), original.get(x, y)) def checkImages(self, original): image = pickle.loads(pickle.dumps(original)) self.assertImagesEqual(image, original) def checkExposures(self, original): image = pickle.loads(pickle.dumps(original)) self.assertImagesEqual(image.getMaskedImage(), original.getMaskedImage()) self.assertEqual(image.getWcs(), original.getWcs()) def testImage(self): for Image in (afwImage.ImageU, afwImage.ImageI, afwImage.ImageF, afwImage.ImageD, afwImage.MaskU, ): image = self.createImage(Image) self.checkImages(image) def testMaskedImage(self): scale = (1.0*afwGeom.arcseconds).asDegrees() wcs = afwImage.makeWcs(afwCoord.Coord(0.0*afwGeom.degrees, 0.0*afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), scale, 0.0, 0.0, scale) for MaskedImage in (afwImage.MaskedImageF, afwImage.MaskedImageD, ): image = self.createMaskedImage(MaskedImage) self.checkImages(image) exposure = afwImage.makeExposure(image, wcs) self.checkExposures(exposure) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ImagePickleTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6751654c

    commit 6751654c14e9ca1a453c1f4f9643335e9bda26a2
    Author: Paul Price 
    Date:   Fri Nov 1 22:16:50 2013 -0400
    
        image,fits: consolidate FITS pickling code, and use for image classes (#3035)
        
        Image pickling code didn't work on MaskedImage or Mask.  Stripped
        out use of boost_picklable for image classes in favour of FITS-based
        pickling (like Table; see #2344).  To do so, made the FITS-based
        pickling code generally accessible; now anything can use it so long as
        it can "writeFits" and "readFits".
        
        Picklable image classes are: Image, Mask, MaskedImage, Exposure.
        
        This adds new static "readFits" methods to the image classes that simply
        forward to the proper Constructor methods.  While this increases the number
        of interfaces, this parallels the operations in the Catalog classes (which
        don't have proper Constructors that can read a FITS file).
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    python/lsst/afw/image/maskedImage.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %{
                    #   include "lsst/afw/image/MaskedImage.h"
                    %}
                    
                    /************************************************************************************************************/
                    //
                    // Must go Before the %include
                    //
                    %define %maskedImagePtr(NAME, TYPE, PIXEL_TYPES...)
                        %shared_ptr(lsst::afw::image::MaskedImage);
                        %template(vector##NAME##TYPE) std::vector > >;
                    %enddef
                    
                    //
                    // Must go After the %include
                    //
                    %define %maskedImage(NAME, TYPE, PIXEL_TYPES...)
                    %template(NAME##TYPE) lsst::afw::image::MaskedImage;
                    %template(makeMaskedImage) lsst::afw::image::makeMaskedImage;
                    %newobject makeMaskedImage;
                    %lsst_persistable(lsst::afw::image::MaskedImage);
                    %fits_reduce(lsst::afw::image::MaskedImage);
                    
                    %extend lsst::afw::image::MaskedImage {
    
    49 f8edfe90 - %pythoncode {
    49 81c3bd10 + %pythoncode %{
    ? +
    50 f8edfe90 - def set(self, x, y=None, values=None):
    ? ----
    50 81c3bd10 + def set(self, x, y=None, values=None):
    51 f8edfe90 - """Set the point (x, y) to a triple (value, mask, variance)"""
    ? ----
    51 81c3bd10 + """Set the point (x, y) to a triple (value, mask, variance)"""
    53 f8edfe90 - if values is None:
    ? ----
    53 81c3bd10 + if values is None:
    54 f8edfe90 - assert (y is None)
    ? ----
    54 81c3bd10 + assert (y is None)
    55 f8edfe90 - values = x
    ? ----
    55 81c3bd10 + values = x
    56 f8edfe90 - try:
    ? ----
    56 81c3bd10 + try:
    57 f8edfe90 - self.getImage().set(values[0])
    ? ----
    57 81c3bd10 + self.getImage().set(values[0])
    58 f8edfe90 - self.getMask().set(values[1])
    ? ----
    58 81c3bd10 + self.getMask().set(values[1])
    59 f8edfe90 - self.getVariance().set(values[2])
    ? ----
    59 81c3bd10 + self.getVariance().set(values[2])
    60 f8edfe90 - except TypeError:
    ? ----
    60 81c3bd10 + except TypeError:
    61 f8edfe90 - self.getImage().set(values)
    ? ----
    61 81c3bd10 + self.getImage().set(values)
    62 f8edfe90 - self.getMask().set(0)
    ? ----
    62 81c3bd10 + self.getMask().set(0)
    63 f8edfe90 - self.getVariance().set(0)
    ? ----
    63 81c3bd10 + self.getVariance().set(0)
    64 f8edfe90 - else:
    ? ----
    64 81c3bd10 + else:
    65 f8edfe90 - try:
    ? ----
    65 81c3bd10 + try:
    66 f8edfe90 - self.getImage().set(x, y, values[0])
    ? ----
    66 81c3bd10 + self.getImage().set(x, y, values[0])
    67 0877b6e3 - if len(values) > 1:
    ? ----
    67 81c3bd10 + if len(values) > 1:
    68 0877b6e3 - self.getMask().set(x, y, values[1])
    ? ----
    68 81c3bd10 + self.getMask().set(x, y, values[1])
    69 0877b6e3 - if len(values) > 2:
    ? ----
    69 81c3bd10 + if len(values) > 2:
    70 0877b6e3 - self.getVariance().set(x, y, values[2])
    ? ----
    70 81c3bd10 + self.getVariance().set(x, y, values[2])
    71 f8edfe90 - except TypeError:
    ? ----
    71 81c3bd10 + except TypeError:
    72 f8edfe90 - self.getImage().set(x)
    ? ----
    72 81c3bd10 + self.getImage().set(x)
    73 f8edfe90 - self.getMask().set(y)
    ? ----
    73 81c3bd10 + self.getMask().set(y)
    74 f8edfe90 - self.getVariance().set(values)
    ? ----
    74 81c3bd10 + self.getVariance().set(values)
    76 f8edfe90 - def get(self, x, y):
    ? ----
    76 81c3bd10 + def get(self, x, y):
    77 f8edfe90 - """Return a triple (value, mask, variance) at the point (x, y)"""
    ? ----
    77 81c3bd10 + """Return a triple (value, mask, variance) at the point (x, y)"""
    78 f8edfe90 - return (self.getImage().get(x, y),
    ? ----
    78 81c3bd10 + return (self.getImage().get(x, y),
    79 f8edfe90 - self.getMask().get(x, y),
    ? ----
    79 81c3bd10 + self.getMask().get(x, y),
    80 f8edfe90 - self.getVariance().get(x, y))
    ? ----
    80 81c3bd10 + self.getVariance().get(x, y))
    83 54a43c29 - def getArrays(self):
    ? ----
    83 81c3bd10 + def getArrays(self):
    84 54a43c29 - """Return a tuple (value, mask, variance) numpy arrays."""
    ? ----
    84 81c3bd10 + """Return a tuple (value, mask, variance) numpy arrays."""
    85 54a43c29 - return (self.getImage().getArray() if self.getImage() else None,
    ? ----
    85 81c3bd10 + return (self.getImage().getArray() if self.getImage() else None,
    86 54a43c29 - self.getMask().getArray() if self.getMask() else None,
    ? ----
    86 81c3bd10 + self.getMask().getArray() if self.getMask() else None,
    87 54a43c29 - self.getVariance().getArray() if self.getVariance() else None)
    ? ----
    87 81c3bd10 + self.getVariance().getArray() if self.getVariance() else None)
    89 f8edfe90 - #
    89 81c3bd10 + #
    90 f8edfe90 - # Deal with incorrect swig wrappers for C++ "void operator op=()"
    ? ----
    90 81c3bd10 + # Deal with incorrect swig wrappers for C++ "void operator op=()"
    91 f8edfe90 - #
    91 81c3bd10 + #
    92 f8edfe90 - def __ilshift__(*args):
    ? ----
    92 81c3bd10 + def __ilshift__(*args):
    93 f8edfe90 - """__ilshift__(self, NAME##TYPE src) -> self"""
    ? ----
    93 81c3bd10 + """__ilshift__(self, NAME##TYPE src) -> self"""
    94 f8edfe90 - _imageLib.MaskedImage##TYPE##___ilshift__(*args)
    ? ----
    94 81c3bd10 + _imageLib.MaskedImage##TYPE##___ilshift__(*args)
    95 f8edfe90 - return args[0]
    ? ----
    95 81c3bd10 + return args[0]
    97 f8edfe90 - def __ior__(*args):
    ? ----
    97 81c3bd10 + def __ior__(*args):
    98 f8edfe90 - """__ior__(self, NAME##TYPE src) -> self"""
    ? ----
    98 81c3bd10 + """__ior__(self, NAME##TYPE src) -> self"""
    99 f8edfe90 - _imageLib.NAME##TYPE##___ior__(*args)
    ? ----
    99 81c3bd10 + _imageLib.NAME##TYPE##___ior__(*args)
    100 f8edfe90 - return args[0]
    ? ----
    100 81c3bd10 + return args[0]
    102 f8edfe90 - def __iand__(*args):
    ? ----
    102 81c3bd10 + def __iand__(*args):
    103 f8edfe90 - """__iand__(self, NAME##TYPE src) -> self"""
    ? ----
    103 81c3bd10 + """__iand__(self, NAME##TYPE src) -> self"""
    104 f8edfe90 - _imageLib.NAME##TYPE##___iand__(*args)
    ? ----
    104 81c3bd10 + _imageLib.NAME##TYPE##___iand__(*args)
    105 f8edfe90 - return args[0]
    ? ----
    105 81c3bd10 + return args[0]
    107 f8edfe90 - def __iadd__(*args):
    ? ----
    107 81c3bd10 + def __iadd__(*args):
    108 f8edfe90 - """
    ? ----
    108 81c3bd10 + """
    109 f8edfe90 - __iadd__(self, float scalar) -> self
    ? ----
    109 81c3bd10 + __iadd__(self, float scalar) -> self
    110 f8edfe90 - __iadd__(self, NAME##TYPE inputImage) -> self
    ? ----
    110 81c3bd10 + __iadd__(self, NAME##TYPE inputImage) -> self
    111 f8edfe90 - """
    ? ----
    111 81c3bd10 + """
    112 f8edfe90 - _imageLib.NAME##TYPE##___iadd__(*args)
    ? ----
    112 81c3bd10 + _imageLib.NAME##TYPE##___iadd__(*args)
    113 f8edfe90 - return args[0]
    ? ----
    113 81c3bd10 + return args[0]
    115 f8edfe90 - def __isub__(*args):
    ? ----
    115 81c3bd10 + def __isub__(*args):
    116 f8edfe90 - """
    ? ----
    116 81c3bd10 + """
    117 f8edfe90 - __isub__(self, float scalar)
    ? ----
    117 81c3bd10 + __isub__(self, float scalar)
    118 f8edfe90 - __isub__(self, NAME##TYPE inputImage)
    ? ----
    118 81c3bd10 + __isub__(self, NAME##TYPE inputImage)
    119 f8edfe90 - """
    ? ----
    119 81c3bd10 + """
    120 f8edfe90 - _imageLib.NAME##TYPE##___isub__(*args)
    ? ----
    120 81c3bd10 + _imageLib.NAME##TYPE##___isub__(*args)
    121 f8edfe90 - return args[0]
    ? ----
    121 81c3bd10 + return args[0]
    122 f8edfe90 -
    123 81c3bd10 +
    124 f8edfe90 - def __imul__(*args):
    ? ----
    124 81c3bd10 + def __imul__(*args):
    125 f8edfe90 - """
    ? ----
    125 81c3bd10 + """
    126 f8edfe90 - __imul__(self, float scalar)
    ? ----
    126 81c3bd10 + __imul__(self, float scalar)
    127 f8edfe90 - __imul__(self, NAME##TYPE inputImage)
    ? ----
    127 81c3bd10 + __imul__(self, NAME##TYPE inputImage)
    128 f8edfe90 - """
    ? ----
    128 81c3bd10 + """
    129 f8edfe90 - _imageLib.NAME##TYPE##___imul__(*args)
    ? ----
    129 81c3bd10 + _imageLib.NAME##TYPE##___imul__(*args)
    130 f8edfe90 - return args[0]
    ? ----
    130 81c3bd10 + return args[0]
    132 f8edfe90 - def __idiv__(*args):
    ? ----
    132 81c3bd10 + def __idiv__(*args):
    133 f8edfe90 - """
    ? ----
    133 81c3bd10 + """
    134 f8edfe90 - __idiv__(self, float scalar)
    ? ----
    134 81c3bd10 + __idiv__(self, float scalar)
    135 f8edfe90 - __idiv__(self, NAME##TYPE inputImage)
    ? ----
    135 81c3bd10 + __idiv__(self, NAME##TYPE inputImage)
    136 f8edfe90 - """
    ? ----
    136 81c3bd10 + """
    137 f8edfe90 - _imageLib.NAME##TYPE##___idiv__(*args)
    ? ----
    137 81c3bd10 + _imageLib.NAME##TYPE##___idiv__(*args)
    138 f8edfe90 - return args[0]
    ? ----
    138 81c3bd10 + return args[0]
    139 81c3bd10 +
    140 81c3bd10 + # support "__from__ future import division" in Python 2 (not needed for Python 3)
    141 81c3bd10 + __itruediv__ = __idiv__
    139 f8edfe90 - }
    142 81c3bd10 + %}
    ? + } %defineClone(NAME##TYPE, lsst::afw::image::MaskedImage, PIXEL_TYPES); %supportSlicing(lsst::afw::image::MaskedImage, PIXEL_TYPES); %enddef /************************************************************************************************************/ %ignore lsst::afw::image::MaskedImage::operator(); %ignore lsst::afw::image::MaskedImage::begin; %ignore lsst::afw::image::MaskedImage::end; %ignore lsst::afw::image::MaskedImage::at; %ignore lsst::afw::image::MaskedImage::rbegin; %ignore lsst::afw::image::MaskedImage::rend; %ignore lsst::afw::image::MaskedImage::col_begin; %ignore lsst::afw::image::MaskedImage::col_end; %ignore lsst::afw::image::MaskedImage::y_at; %ignore lsst::afw::image::MaskedImage::row_begin; %ignore lsst::afw::image::MaskedImage::row_end; %ignore lsst::afw::image::MaskedImage::x_at; %ignore lsst::afw::image::MaskedImage::xy_at; %maskedImagePtr(MaskedImage, F, float, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %maskedImagePtr(MaskedImage, D, double, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %maskedImagePtr(MaskedImage, I, int, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %maskedImagePtr(MaskedImage, U, boost::uint16_t, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %include "lsst/afw/image/MaskedImage.h" %maskedImage(MaskedImage, D, double, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %maskedImage(MaskedImage, F, float, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %maskedImage(MaskedImage, I, int, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %maskedImage(MaskedImage, U, boost::uint16_t, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %extend lsst::afw::image::MaskedImage { %newobject convertD; lsst::afw::image::MaskedImage convertD() { return lsst::afw::image::MaskedImage(*self, true); }
    180 e020773b - %pythoncode {
    183 81c3bd10 + %pythoncode %{
    ? + def convertDouble(self, *args): """Alias for convertD""" return self.convertD(*args)
    185 e020773b - }
    188 81c3bd10 + %}
    ? + } %extend lsst::afw::image::MaskedImage { %newobject convertF; lsst::afw::image::MaskedImage convertF() { return lsst::afw::image::MaskedImage(*self, true); }
    195 e020773b - %pythoncode {
    198 81c3bd10 + %pythoncode %{
    ? + def convertFloat(self, *args): """Alias for convertF""" return self.convertF(*args)
    200 e020773b - }
    203 81c3bd10 + %}
    ? + }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    e020773b

    commit e020773b0ed266a438b033d9c6fa67e7a34e1a25
    Author: rhl 
    Date:   Fri Apr 9 17:28:58 2010 +0000
    
        Add converter for MaskedImageU -> MaskedImageF; change names e.g. convertFloat -> convertF (but preserve old names as aliases)
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    0877b6e3

    commit 0877b6e33ff68b967beece2ed24801c3625978ab
    Author: rhl 
    Date:   Mon Mar 9 23:58:04 2009 +0000
    
        Allow a tuple with <= 3 elements to set MaskedImage pixels
    

    54a43c29

    commit 54a43c297a84a2586aa62781b9b01bbf8884d5bd
    Author: jbosch 
    Date:   Sat Mar 5 04:29:47 2011 +0000
    
        afw #1556 - added ndarray/numpy constructors for Image and friends, removed slower numpy conversions in image/testUtils.py, adjusted unit tests accordingly.
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    include/lsst/afw/image/MaskedImage.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * \file
                     * \brief Implementation of the Class MaskedImage
                     */
                    
                    #ifndef LSST_IMAGE_MASKEDIMAGE_H
                    #define LSST_IMAGE_MASKEDIMAGE_H
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/shared_ptr.hpp"
                    #include "boost/mpl/at.hpp"
                    #include "boost/iterator/zip_iterator.hpp"
                    
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/daf/base/Persistable.h"
                    #include "lsst/afw/formatters/MaskedImageFormatter.h"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/image/Mask.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace image {
                        namespace detail {
                            /// A traits class for MaskedImage
                            struct MaskedImage_tag : public basic_tag { };
                            /// A class used to identify classes that represent MaskedImage pixels
                            struct MaskedImagePixel_tag { };
                    
                            std::string const fitsFile_RE = "\\.fits(\\.[fg]z)?$"; /// regexp to identify when MaskedImages should
                                                                               /// be written as MEFs
                            std::string const compressedFileNoMEF_RE = "(\\.gz)$";   /// regexp to identify compressed files that we can't write MEFs to
                        }
                    }}}
                    
                    #include "lsst/afw/image/Pixel.h"
                    #include "lsst/afw/image/LsstImageTypes.h"
                    
                    namespace lsst {
                    namespace afw {
                        namespace formatters {
                            template class MaskedImageFormatter;
                        }
                    
                    namespace image {
                    
                    /// A class to manipulate images, masks, and variance as a single object
                    template
                    class MaskedImage : public lsst::daf::base::Persistable,
                                        public lsst::daf::base::Citizen {
                    public:
                        /// shared pointer to the Image
                        typedef typename Image::Ptr ImagePtr;
                        /// shared pointer to the Mask
                        typedef typename Mask::Ptr MaskPtr;
                        /// shared pointer to the variance Image
                        typedef typename Image::Ptr VariancePtr;
                        /// shared pointer to a MaskedImage
                        typedef boost::shared_ptr Ptr;
                        typedef boost::shared_ptr ConstPtr;
                        /// The Mask's MaskPlaneDict
                        typedef typename Mask::MaskPlaneDict MaskPlaneDict;
                    
                        typedef lsst::afw::image::Image Variance; // These need to be here, and in this order, as
                        typedef lsst::afw::image::Image Image;       // "typedef Image::Ptr ImagePtr;" confuses swig (it can't
                        typedef lsst::afw::image::Mask Mask;          // find ImagePtr) and we can't use Image<> after these typedefs
                    
                        typedef detail::MaskedImage_tag image_category;
                    
                    #if !defined(SWIG)
                        /// A templated class to return this classes' type (present in Image/Mask/MaskedImage)
                        template
                        struct ImageTypeFactory {
                            /// Return the desired type
                            typedef MaskedImage type;
                        };
                    #endif
                    
                        /************************************************************************************************************/
                        /// An iterator to the MaskedImage
                        template class MaskedImageIterator;
                        /// An const iterator to the MaskedImage
                        template class const_MaskedImageIterator;
                        /// A locator for the MaskedImage
                        template class MaskedImageLocator;
                        /// A const locator for the MaskedImage
                        template class const_MaskedImageLocator;
                    
                        /************************************************************************************************************/
                    
                    #if !defined(SWIG)
                        /// A Pixel in the MaskedImage
                        typedef lsst::afw::image::pixel::Pixel Pixel;
                        /// A single Pixel of the same type as those in the MaskedImage
                        typedef lsst::afw::image::pixel::SinglePixel SinglePixel;
                    
                        /************************************************************************************************************/
                        /// The base class for MaskedImageIterators (const and non-const)
                        template class Ref=Reference>
                        class MaskedImageIteratorBase {
                            typedef boost::tuple IMV_iterator_tuple;
                    
                        public:
                            /// The underlying iterator tuple
                            /// \note not really for public consumption;  could be made protected
                            typedef typename boost::zip_iterator::reference IMV_tuple;
                            /// The underlying const iterator tuple
                            /// \note not really for public consumption;  could be made protected
                            template friend class const_MaskedImageIterator;
                            /// Type pointed to by the iterator
                            typedef Pixel type;
                    
                            /// Construct a MaskedImageIteratorBase from the image/mask/variance iterators
                            MaskedImageIteratorBase(ImageIterator const& img, MaskIterator const& msk, VarianceIterator const &var) :
                                _iter(boost::make_zip_iterator(boost::make_tuple(img, msk, var))) {
                            }
                            /// Return (a reference to) the image part of the Pixel pointed at by the iterator
                            typename Ref::type image() {
                                return _iter->template get<0>()[0];
                            }
                    
                            /// Return (a reference to) the mask part of the Pixel pointed at by the iterator
                            typename Ref::type mask() {
                                return _iter->template get<1>()[0];
                            }
                    
                            /// Return (a reference to) the variance part of the Pixel pointed at by the iterator
                            typename Ref::type variance() {
                                return _iter->template get<2>()[0];
                            }
                    
                            /// Return the underlying iterator tuple
                            /// \note not really for public consumption;  could be made protected
                            const IMV_iterator_tuple get_iterator_tuple() const {
                                return _iter.get_iterator_tuple();
                            }
                    
                            /// Increment the iterator by \c delta
                            void operator+=(std::ptrdiff_t delta ///< how far to move the iterator
                                           ) {
                                _iter += delta;
                            }
                            /// Decrement the iterator by \c delta
                            void operator-=(std::ptrdiff_t delta ///< how far to move the iterator
                                           ) {
                                _iter -= delta;
                            }
                            /// Increment the iterator (prefix)
                            void operator++() {         // prefix
                                ++_iter;
                            }
                            /// Increment the iterator (postfix)
                            void operator++(int) {      // postfix
                                _iter++;
                            }
                            /// Return the distance between two iterators
                            std::ptrdiff_t operator-(MaskedImageIteratorBase const& rhs) {
                                return &this->_iter->template get<0>() - &rhs._iter->template get<0>();
                            }
                            /// Return true if the lhs equals the rhs
                            bool operator==(MaskedImageIteratorBase const& rhs) {
                                return &this->_iter->template get<0>() == &rhs._iter->template get<0>();
                            }
                            /// Return true if the lhs doesn't equal the rhs
                            bool operator!=(MaskedImageIteratorBase const& rhs) {
                                return &this->_iter->template get<0>() != &rhs._iter->template get<0>();
                            }
                            /// Return true if the lhs is less than the rhs
                            bool operator<(MaskedImageIteratorBase const& rhs) {
                                return &this->_iter->template get<0>() < &rhs._iter->template get<0>();
                            }
                            /// Convert an iterator to a Pixel
                            operator Pixel() const {
                                return Pixel(_iter->template get<0>()[0],
                                             _iter->template get<1>()[0],
                                             _iter->template get<2>()[0]);
                            }
                    
                            /// Dereference the iterator, returning a Pixel
                            Pixel operator*() {
                                return Pixel(image(), mask(), variance());
                            }
                            /// Dereference the iterator, returning a const Pixel
                            const Pixel operator*() const {
                                return Pixel(image(), mask(), variance());
                            }
                    
                        protected:
                            typename boost::zip_iterator _iter;
                        };
                    
                        /// An iterator for a MaskedImage
                        template
                        class MaskedImageIterator :
                            public  MaskedImageIteratorBase {
                            typedef MaskedImageIteratorBase MaskedImageIteratorBase_t;
                        public:
                            MaskedImageIterator(ImageIterator& img, MaskIterator& msk, VarianceIterator &var) :
                                MaskedImageIteratorBase_t(img, msk, var) {
                            }
                            /// Return a MaskedImageIterator that's delta beyond this
                            MaskedImageIterator operator+(std::ptrdiff_t delta) {
                                MaskedImageIterator lhs = *this;
                                lhs += delta;
                    
                                return lhs;
                            }
                        };
                    
                        /// An const iterator for a MaskedImage
                        template
                        class const_MaskedImageIterator :
                            public  MaskedImageIteratorBase::type,
                                                            typename detail::const_iterator_type::type,
                                                            typename detail::const_iterator_type::type,
                                                            ConstReference> {
                    
                            typedef typename detail::const_iterator_type::type const_ImageIterator;
                            typedef typename detail::const_iterator_type::type const_MaskIterator;
                            typedef typename detail::const_iterator_type::type const_VarianceIterator;
                    
                            typedef MaskedImageIteratorBase MaskedImageIteratorBase_t;
                        public:
                            const_MaskedImageIterator(MaskedImageIterator const& iter) :
                                MaskedImageIteratorBase_t(const_ImageIterator(iter.get_iterator_tuple().template get<0>()),
                                                          const_MaskIterator(iter.get_iterator_tuple().template get<1>()),
                                                          const_VarianceIterator(iter.get_iterator_tuple().template get<2>())
                                                         ) {
                                ;
                            }
                            /// Return a const_MaskedImageIterator that's delta beyond this
                            const_MaskedImageIterator& operator+(std::ptrdiff_t delta) {
                                const_MaskedImageIterator lhs = *this;
                                lhs += delta;
                    
                                return lhs;
                            }
                        };
                    
                        /************************************************************************************************************/
                        /// The base class for MaskedImageLocator%s (const and non-const)
                        template class Ref=Reference>
                        class MaskedImageLocatorBase {
                            typedef typename boost::tuple IMVLocator;
                            //
                            // A class to provide _[xy]_iterator for MaskedImageLocator.  We can't just use
                            // a zip_iterator as moving this iterator must be the same as moving the locator
                            // itself, for consistency with {Image,Mask}::xy_locator
                            //
                            template class X_OR_Y >
                            class _x_or_y_iterator {
                            public:
                                _x_or_y_iterator(MaskedImageLocatorBase* mil) : _mil(mil) {}
                    
                                void operator+=(const int di) {
                                    // Equivalent to "_mil->_loc.template get<0>().x() += di;"
                                    X_OR_Y(_mil->_loc.template get<0>())() += di;
                                    X_OR_Y(_mil->_loc.template get<1>())() += di;
                                    X_OR_Y(_mil->_loc.template get<2>())() += di;
                                }
                    
                                void operator++() {     // prefix
                                    // Equivalent to "++_mil->_loc.template get<0>().x();"
                                    ++X_OR_Y(_mil->_loc.template get<0>())();
                                    ++X_OR_Y(_mil->_loc.template get<1>())();
                                    ++X_OR_Y(_mil->_loc.template get<2>())();
                                }
                    
                                bool operator==(_x_or_y_iterator const& rhs) {
                                    return
                                        X_OR_Y(_mil->_loc.template get<0>())() ==
                                        X_OR_Y(rhs._mil->_loc.template get<0>())();
                    
                                }
                                bool operator!=(_x_or_y_iterator const& rhs) {
                                    return
                                        X_OR_Y(_mil->_loc.template get<0>())() !=
                                        X_OR_Y(rhs._mil->_loc.template get<0>())();
                    
                                }
                                bool operator<(_x_or_y_iterator const& rhs) {
                                    return
                                        X_OR_Y(_mil->_loc.template get<0>())() <
                                        X_OR_Y(rhs._mil->_loc.template get<0>())();
                    
                                }
                    
                                Pixel operator*() {
                                    return Pixel((*(X_OR_Y(_mil->_loc.template get<0>())()))[0],
                                                 (*(X_OR_Y(_mil->_loc.template get<1>())()))[0],
                                                 (*(X_OR_Y(_mil->_loc.template get<2>())()))[0]);
                                }
                    
                                typename Ref::type image() {
                                    // Equivalent to "return (*_mil->_loc.template get<0>().x())[0];"
                    
                                    return (*(X_OR_Y(_mil->_loc.template get<0>())()))[0];
                                }
                                typename Ref::type mask() {
                                    return (*(X_OR_Y(_mil->_loc.template get<1>())()))[0];
                                }
                                typename Ref::type variance() {
                                    return (*(X_OR_Y(_mil->_loc.template get<2>())()))[0];
                                }
                            protected:
                                MaskedImageLocatorBase *_mil;
                            };
                    
                            // Two classes to provide .x() and .y() in _x_or_y_iterator
                            template
                            class apply_x {
                                typedef typename LocT::x_iterator IterT;
                            public:
                                apply_x(LocT &loc) : _loc(loc) { }
                                IterT& operator()() { return _loc.x(); }
                            private:
                                LocT& _loc;
                            };
                    
                            template
                            class apply_y {
                                typedef typename LocT::y_iterator IterT;
                            public:
                                apply_y(LocT &loc) : _loc(loc) { }
                                IterT& operator()() { return _loc.y(); }
                            private:
                                LocT& _loc;
                            };
                    
                        public:
                            template friend class const_MaskedImageLocator;
                    
                            typedef typename boost::tuple IMVCachedLocation;
                            /// An x_iterator that provides a view of the xy_locator (i.e. advancing one advances the other)
                            typedef _x_or_y_iterator x_iterator;
                            /// A y_iterator that provides a view of the xy_locator (i.e. advancing one advances the other)
                            typedef _x_or_y_iterator y_iterator;
                            /// A saved relative position, providing efficient access to neighbouring pixels
                            class cached_location_t {
                            public:
                                //template class> friend class MaskedImageLocatorBase;
                                template friend class const_MaskedImageLocator;
                    
                                /// Create a cached_location_t that can be used to access pixels (x, y) away from \c loc
                                cached_location_t(IMVLocator const& loc, int x, int y) :
                                    _imv(loc.template get<0>().cache_location(x, y),
                                         loc.template get<1>().cache_location(x, y),
                                         loc.template get<2>().cache_location(x, y)) {
                                    ;
                                }
                                //protected:
                                IMVCachedLocation _imv;
                            };
                            /// Construct a MaskedImageLocator from %image/mask/variance locators
                            MaskedImageLocatorBase(ImageLocator const& img, MaskLocator const& msk, VarianceLocator const& var) :
                                _loc(img, msk, var) {
                                ;
                            }
                    
                            /// Dereference a locator, returning a Pixel
                            Pixel operator*() {
                                return Pixel(_loc.template get<0>().x()[0][0],
                                             _loc.template get<1>().x()[0][0],
                                             _loc.template get<2>().x()[0][0]);
                            }
                    
                            /// Dereference a locator, returning a Pixel offset by (x, y) from the locator
                            Pixel operator()(int x, int y) {
                                return Pixel(_loc.template get<0>()(x, y)[0],
                                             _loc.template get<1>()(x, y)[0],
                                             _loc.template get<2>()(x, y)[0]);
                            }
                    
                            /// Dereference a locator, returning a Pixel offset by the amount set when we created the \c cached_location_t
                            Pixel operator[](cached_location_t const& cached_loc) {
                                return Pixel(_loc.template get<0>()[cached_loc._imv.template get<0>()][0],
                                             _loc.template get<1>()[cached_loc._imv.template get<1>()][0],
                                             _loc.template get<2>()[cached_loc._imv.template get<2>()][0]);
                            }
                            /// Return an iterator that can be used to move (or dereference) a locator
                            ///
                            /// \note this x_locator is xy_locator::x_locator, not MaskedImage::x_locator
                            x_iterator x() {
                                return x_iterator(this);
                            }
                    
                            /// Return an iterator that can be used to move (or dereference) a locator
                            ///
                            /// \note this y_locator is xy_locator::y_locator, not MaskedImage::y_locator
                            y_iterator y() {
                                return y_iterator(this);
                            }
                    
                            /// Create a cached_location_t offset by (x, y) from locator
                            cached_location_t cache_location(int x, int y) const {
                                return cached_location_t(_loc, x, y);
                            }
                            //
                            // We don't want to duplicate code for image/mask/variance -- but the boost::mpl stuff isn't pretty
                            // as we can't say int_ within a template.  So define a set of functions apply_IMV
                            // to do the dirty work
                            //
                            typedef typename boost::mpl::vector PixelTVec;
                    
                            template
                            typename Ref::type>::type apply_IMV(cached_location_t const& cached_loc) {
                                return _loc.template get()[cached_loc._imv.template get()][0];
                            }
                    
                            template
                            typename Ref::type>::type apply_IMV() {
                                return _loc.template get()[0][0];
                            }
                    
                            template
                            typename Ref::type>::type apply_IMV(int x, int y) {
                                return _loc.template get()(x, y)[0];
                            }
                            //
                            // Use those templated classes to implement image/mask/variance
                            //
                            /// Return a reference to the %image at the offset set when we created the \c cached_location_t
                            typename Ref::type image(cached_location_t const& cached_loc) {
                                return apply_IMV >(cached_loc);
                            }
                            /// Return a reference to the %image at the current position of the locator
                            typename Ref::type image() {
                                return apply_IMV >();
                            }
                            /// Return a reference to the %image offset by (x, y) from the current position of the locator
                            typename Ref::type image(int x, int y) {
                                return apply_IMV >(x, y);
                            }
                    
                            /// Return a reference to the mask at the offset set when we created the \c cached_location_t
                            typename Ref::type mask(cached_location_t const& cached_loc) {
                                return apply_IMV >(cached_loc);
                            }
                            /// Return a reference to the mask at the current position of the locator
                            typename Ref::type mask() {
                                return apply_IMV >();
                            }
                            /// Return a reference to the mask offset by (x, y) from the current position of the locator
                            typename Ref::type mask(int x, int y) {
                                return apply_IMV >(x, y);
                            }
                    
                            /// Return a reference to the variance at the offset set when we created the \c cached_location_t
                            typename Ref::type variance(cached_location_t const& cached_loc) {
                                return apply_IMV >(cached_loc);
                            }
                            /// Return a reference to the variance at the current position of the locator
                            typename Ref::type variance() {
                                return apply_IMV >();
                            }
                            /// Return a reference to the variance offset by (x, y) from the current position of the locator
                            typename Ref::type variance(int x, int y) {
                                return apply_IMV >(x, y);
                            }
                    
                            /// Return true iff two locators are equal
                            bool operator==(MaskedImageLocatorBase const& rhs) {
                                return _loc.template get<0>() == rhs._loc.template get<0>();
                            }
                            /// Return true iff two locators are not equal
                            bool operator!=(MaskedImageLocatorBase const& rhs) {
                                return !(*this == rhs);
                            }
                            /// Return true iff lhs is less than rhs
                            bool operator<(MaskedImageLocatorBase const& rhs) {
                                return _loc.template get<0>() < rhs._loc.template get<0>();
                            }
                    
                            /// Increment the locator's \c x and \c y positions by \c p
                            MaskedImageLocatorBase& operator+=(pair2I const& p) {
                                return operator+=(detail::difference_type(p.first, p.second));
                            }
                    
                            /// Increment the locator's \c x and \c y positions by \c p
                            MaskedImageLocatorBase& operator+=(detail::difference_type p) {
                                _loc.template get<0>() += p;
                                _loc.template get<1>() += p;
                                _loc.template get<2>() += p;
                    
                                return *this;
                            }
                        protected:
                            IMVLocator _loc;
                        };
                    
                        /// A locator for a MaskedImage
                        template
                        class MaskedImageLocator :
                            public  MaskedImageLocatorBase {
                            typedef MaskedImageLocatorBase MaskedImageLocatorBase_t;
                        public:
                            MaskedImageLocator(ImageLocator& img, MaskLocator& msk, VarianceLocator &var) :
                                MaskedImageLocatorBase_t(img, msk, var) {
                            }
                        };
                    
                        /// A const locator for a MaskedImage
                        template
                        class const_MaskedImageLocator :
                            public  MaskedImageLocatorBase::type,
                                                           typename detail::const_locator_type::type,
                                                           typename detail::const_locator_type::type,
                                                           ConstReference> {
                    
                            typedef typename detail::const_locator_type::type const_ImageLocator;
                            typedef typename detail::const_locator_type::type const_MaskLocator;
                            typedef typename detail::const_locator_type::type const_VarianceLocator;
                    
                            typedef MaskedImageLocatorBase MaskedImageLocatorBase_t;
                        public:
                            const_MaskedImageLocator(MaskedImageLocator const& iter) :
                                MaskedImageLocatorBase_t(const_ImageLocator(iter._loc.template get<0>()),
                                                         const_MaskLocator(iter._loc.template get<1>()),
                                                         const_VarianceLocator(iter._loc.template get<2>())
                                                        ) {
                                ;
                            }
                        };
                    
                    #endif  // !defined(SWIG)
                    
                    /************************************************************************************************************/
                        // An iterator to a MaskedImage
                        typedef MaskedImageIterator iterator;
                        // A const_iterator to a MaskedImage
                        typedef const_MaskedImageIterator const_iterator;
                        // A reverse_iterator to a MaskedImage
                        typedef MaskedImageIterator reverse_iterator;
                    #if 0                                   // doesn't compile.  I should fix this, but it's low priority. RHL
                        /// a const_reverse_iterator
                        typedef const_MaskedImageIterator const_reverse_iterator;
                    #endif
                        /// An iterator to a row of a MaskedImage
                        typedef MaskedImageIterator x_iterator;
                        /// A const_iterator to a row of a MaskedImage
                        typedef const_MaskedImageIterator const_x_iterator;
                        /// A fast STL compliant iterator for contiguous images
                        /// N.b. The order of pixel access is undefined
                        typedef x_iterator fast_iterator;
                        /// An iterator to a column of a MaskedImage
                        typedef MaskedImageIterator y_iterator;
                        /// A const_iterator to a column of a MaskedImage
                        typedef const_MaskedImageIterator const_y_iterator;
                    
                        /// A locator for a MaskedImage
                        typedef MaskedImageLocator xy_locator;
                        /// A const_locator for a MaskedImage
                        typedef const_MaskedImageLocator const_xy_locator;
                    
                        /// an x_iterator associated with an xy_locator
                        typedef typename MaskedImageLocator::x_iterator xy_x_iterator;
                        /// an y_iterator associated with an xy_locator
                        typedef typename MaskedImageLocator::y_iterator xy_y_iterator;
                    
                        /************************************************************************************************************/
                    
                        // Constructors
                        explicit MaskedImage(
                            unsigned int width, unsigned int height,
                            MaskPlaneDict const& planeDict=MaskPlaneDict()
                        );
                        explicit MaskedImage(
                            geom::Extent2I const & dimensions=geom::Extent2I(),
                            MaskPlaneDict const& planeDict=MaskPlaneDict()
                        );
                        explicit MaskedImage(
                            ImagePtr image,
                            MaskPtr mask = MaskPtr(),
                            VariancePtr variance = VariancePtr()
                        );
                        explicit MaskedImage(
                            geom::Box2I const & bbox,
                            MaskPlaneDict const& planeDict=MaskPlaneDict()
                        );
                    
                        /**
                         *  @brief Construct a MaskedImage by reading a regular FITS file.
                         *
                         *  @param[in]      fileName      File to read.
                         *  @param[in,out]  metadata      Metadata read from the primary HDU header.
                         *  @param[in]      bbox          If non-empty, read only the pixels within the bounding box.
                         *  @param[in]      origin        Coordinate system of the bounding box; if PARENT, the bounding box
                         *                                should take into account the xy0 saved with the image.
                         *  @param[in]      conformMasks  If true, make Mask conform to the mask layout in the file.
                         *  @param[in]      needAllHdus   If true, throw fits::FitsError if the mask and/or variance plane is
                         *                                missing.  If false, silently initialize them to zero.
                         *  @param[in,out]  imageMetadata      Metadata read from the image HDU header.
                         *  @param[in,out]  maskMetadata       Metadata read from the mask HDU header.
                         *  @param[in,out]  varianceMetadata   Metadata read from the variance HDU header.
                         */
                        explicit MaskedImage(
                            std::string const & fileName,
                            PTR(daf::base::PropertySet) metadata=PTR(daf::base::PropertySet)(),
    
    645 271e8097 - geom::Box2I const & bbox=geom::Box2I(), ImageOrigin origin=LOCAL,
    ? ^^^ ^
    645 93994d54 + geom::Box2I const & bbox=geom::Box2I(), ImageOrigin origin=PARENT,
    ? ^ ^^^^ bool conformMasks=false, bool needAllHdus=false, PTR(daf::base::PropertySet) imageMetadata=PTR(daf::base::PropertySet)(), PTR(daf::base::PropertySet) maskMetadata=PTR(daf::base::PropertySet)(), PTR(daf::base::PropertySet) varianceMetadata=PTR(daf::base::PropertySet)() ); /** * @brief Construct a MaskedImage by reading a FITS image in memory. * * @param[in] manager An object that manages the memory buffer to read. * @param[in,out] metadata Metadata read from the primary HDU header. * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. * @param[in] conformMasks If true, make Mask conform to the mask layout in the file. * @param[in] needAllHdus If true, throw fits::FitsError if the mask and/or variance plane is * missing. If false, silently initialize them to zero. * @param[in,out] imageMetadata Metadata read from the image HDU header. * @param[in,out] maskMetadata Metadata read from the mask HDU header. * @param[in,out] varianceMetadata Metadata read from the variance HDU header. */ explicit MaskedImage( fits::MemFileManager & manager, PTR(daf::base::PropertySet) metadata=PTR(daf::base::PropertySet)(),
    670 271e8097 - geom::Box2I const & bbox=geom::Box2I(), ImageOrigin origin=LOCAL,
    ? ^^^ ^
    670 93994d54 + geom::Box2I const & bbox=geom::Box2I(), ImageOrigin origin=PARENT,
    ? ^ ^^^^ bool conformMasks=false, bool needAllHdus=false, PTR(daf::base::PropertySet) imageMetadata=PTR(daf::base::PropertySet)(), PTR(daf::base::PropertySet) maskMetadata=PTR(daf::base::PropertySet)(), PTR(daf::base::PropertySet) varianceMetadata=PTR(daf::base::PropertySet)() ); /** * @brief Construct a MaskedImage from an already-open FITS object. * * @param[in] fitsfile A FITS object to read from. Current HDU is ignored. * @param[in,out] metadata Metadata read from the primary HDU header. * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. * @param[in] conformMasks If true, make Mask conform to the mask layout in the file. * @param[in] needAllHdus If true, throw fits::FitsError if the mask and/or variance plane is * missing. If false, silently initialize them to zero. * @param[in,out] imageMetadata Metadata read from the image HDU header. * @param[in,out] maskMetadata Metadata read from the mask HDU header. * @param[in,out] varianceMetadata Metadata read from the variance HDU header. */ explicit MaskedImage( fits::Fits & fitsfile, PTR(daf::base::PropertySet) metadata=PTR(daf::base::PropertySet)(),
    695 271e8097 - geom::Box2I const & bbox=geom::Box2I(), ImageOrigin origin=LOCAL,
    ? ^^^ ^
    695 93994d54 + geom::Box2I const & bbox=geom::Box2I(), ImageOrigin origin=PARENT,
    ? ^ ^^^^ bool conformMasks=false, bool needAllHdus=false, PTR(daf::base::PropertySet) imageMetadata=PTR(daf::base::PropertySet)(), PTR(daf::base::PropertySet) maskMetadata=PTR(daf::base::PropertySet)(), PTR(daf::base::PropertySet) varianceMetadata=PTR(daf::base::PropertySet)() ); MaskedImage( MaskedImage const& rhs, bool const deep=false ); MaskedImage( MaskedImage const & rhs, geom::Box2I const & bbox,
    709 bdc29e6a - ImageOrigin const origin=LOCAL,
    ? ^^^ ^
    709 93994d54 + ImageOrigin const origin=PARENT,
    ? ^ ^^^^ bool const deep=false ); /// generalised copy constructor; defined here in the header so that the compiler can instantiate /// N(N-1)/2 conversions between N ImageBase types. /// /// We only support converting the Image part template MaskedImage( MaskedImage const& rhs, //!< Input image const bool deep //!< Must be true; needed to disambiguate ) : lsst::daf::base::Citizen(typeid(this)), _image(), _mask(), _variance() { if (!deep) {
    724 3263f939 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    724 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Only deep copies are permitted for MaskedImages with different pixel types"); } _image = typename Image::Ptr(new Image(*rhs.getImage(), deep)); _mask = typename Mask::Ptr(new Mask(*rhs.getMask(), deep)); _variance = typename Variance::Ptr(new Variance(*rhs.getVariance(), deep)); } #if defined(DOXYGEN) MaskedImage& operator=(MaskedImage const& rhs); #endif virtual ~MaskedImage() {} void swap(MaskedImage &rhs); // Operators MaskedImage& operator=(Pixel const& rhs); MaskedImage& operator=(SinglePixel const& rhs); void operator<<=(MaskedImage const& rhs); void operator+=(ImagePixelT const rhs); void operator+=(MaskedImage const& rhs); void operator+=(lsst::afw::image::Image const& rhs) { *_image += rhs; } void operator+=(lsst::afw::math::Function2 const& function) { *_image += function; } void scaledPlus(double const c, MaskedImage const& rhs); void operator-=(ImagePixelT const rhs); void operator-=(MaskedImage const& rhs); void operator-=(lsst::afw::image::Image const& rhs) { *_image -= rhs; } void operator-=(lsst::afw::math::Function2 const& function) { *_image -= function; } void scaledMinus(double const c, MaskedImage const& rhs); void operator*=(ImagePixelT const rhs); void operator*=(MaskedImage const& rhs); void operator*=(lsst::afw::image::Image const& rhs) { *_image *= rhs; *_variance *= rhs; // yes, multiply twice *_variance *= rhs; } void scaledMultiplies(double const c, MaskedImage const& rhs); void operator/=(ImagePixelT const rhs); void operator/=(MaskedImage const& rhs); void operator/=(lsst::afw::image::Image const& rhs) { *_image /= rhs; *_variance /= rhs; // yes, divide twice *_variance /= rhs; } void scaledDivides(double const c, MaskedImage const& rhs); /** * @brief Write a MaskedImage to a regular FITS file. * * @param[in] fileName Name of the file to write. When writing separate files, this is * the "base" of the filename (e.g. foo reads foo_{img.msk.var}.fits). * @param[in] metadata Additional values to write to the primary HDU header (may be null). * @param[in] imageMetadata Metadata to be written to the image header. * @param[in] maskMetadata Metadata to be written to the mask header. * @param[in] varianceMetadata Metadata to be written to the variance header. * * The FITS file will have four HDUs; the primary HDU will contain only metadata, * while the image, mask, and variance HDU headers will use the "INHERIT='T'" convention * to indicate that the primary metadata applies to those HDUs as well. */ void writeFits( std::string const & fileName, CONST_PTR(daf::base::PropertySet) metadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) imageMetadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) maskMetadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) varianceMetadata = CONST_PTR(daf::base::PropertySet)() ) const; /** * @brief Write a MaskedImage to a FITS RAM file. * * @param[in] manager Manager object for the memory block to write to. * @param[in] metadata Additional values to write to the primary HDU header (may be null). * @param[in] imageMetadata Metadata to be written to the image header. * @param[in] maskMetadata Metadata to be written to the mask header. * @param[in] varianceMetadata Metadata to be written to the variance header. * * The FITS file will have four HDUs; the primary HDU will contain only metadata, * while the image, mask, and variance HDU headers will use the "INHERIT='T'" convention * to indicate that the primary metadata applies to those HDUs as well. */ void writeFits( fits::MemFileManager & manager, CONST_PTR(daf::base::PropertySet) metadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) imageMetadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) maskMetadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) varianceMetadata = CONST_PTR(daf::base::PropertySet)() ) const; /** * @brief Write a MaskedImage to a FITS RAM file. * * @param[in] fitsfile An empty FITS file object. * @param[in] metadata Additional values to write to the primary HDU header (may be null). * @param[in] imageMetadata Metadata to be written to the image header. * @param[in] maskMetadata Metadata to be written to the mask header. * @param[in] varianceMetadata Metadata to be written to the variance header. * * The FITS file will have four HDUs; the primary HDU will contain only metadata, * while the image, mask, and variance HDU headers will use the "INHERIT='T'" convention * to indicate that the primary metadata applies to those HDUs as well. */ void writeFits( fits::Fits & fitsfile, CONST_PTR(daf::base::PropertySet) metadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) imageMetadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) maskMetadata = CONST_PTR(daf::base::PropertySet)(), CONST_PTR(daf::base::PropertySet) varianceMetadata = CONST_PTR(daf::base::PropertySet)() ) const; /** * @brief Read a MaskedImage from a regular FITS file. * * @param[in] filename Name of the file to read. */ static MaskedImage readFits(std::string const & filename) { return MaskedImage(filename); } /** * @brief Read a MaskedImage from a FITS RAM file. * * @param[in] manager Object that manages the memory to be read. */ static MaskedImage readFits(fits::MemFileManager & manager) { return MaskedImage(manager); } // Getters /// Return a (Ptr to) the MaskedImage's %image ImagePtr getImage(bool const noThrow=false) const { if (!_image && !noThrow) { throw LSST_EXCEPT(
    872 bdc29e6a - lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    872 21597d88 + lsst::pex::exceptions::RuntimeError,
    "MaskedImage's Image is NULL" ); } return _image; } /// Return a (Ptr to) the MaskedImage's %mask MaskPtr getMask(bool const noThrow=false) const { if (!_mask && !noThrow) { throw LSST_EXCEPT(
    882 bdc29e6a - lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    882 21597d88 + lsst::pex::exceptions::RuntimeError,
    "MaskedImage's Mask is NULL" ); } return _mask; } /// Return a (Ptr to) the MaskedImage's variance VariancePtr getVariance(bool const noThrow=false) const { if (!_variance && !noThrow) { throw LSST_EXCEPT(
    893 bdc29e6a - lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    893 21597d88 + lsst::pex::exceptions::RuntimeError,
    "MaskedImage's Variance is NULL" ); } return _variance; } /// Return the number of columns in the %image int getWidth() const { return _image->getWidth(); } /// Return the number of rows in the %image int getHeight() const { return _image->getHeight(); } geom::Extent2I getDimensions() const {return _image->getDimensions();}
    905 2035d06f - geom::Box2I getBBox(ImageOrigin const origin=LOCAL) const {return _image->getBBox(origin);}
    ? ^^^ ^
    905 93994d54 + geom::Box2I getBBox(ImageOrigin const origin=PARENT) const {return _image->getBBox(origin);}
    ? ^ ^^^^ /** * Return the %image's row-origin * * This will usually be 0 except for images created using the * MaskedImage(fileName, hdu, BBox, mode) ctor or MaskedImage(ImageBase, BBox) cctor * The origin can be reset with setXY0() */ int getX0() const { return _image->getX0(); } /** * Return the %image's column-origin * * This will usually be 0 except for images created using the * MaskedImage(fileName, hdu, BBox, mode) ctor or MaskedImage(ImageBase, BBox) cctor * The origin can be reset with setXY0() */ int getY0() const { return _image->getY0(); } /** * Return the %image's origin * * This will usually be (0, 0) except for images created using the * MaskedImage(fileName, hdu, BBox, mode) ctor or MaskedImage(ImageBase, BBox) cctor * The origin can be reset with \c setXY0 */ geom::Point2I getXY0() const { return _image->getXY0(); } /** * Set the MaskedImage's origin * * The origin is usually set by the constructor, so you shouldn't need this function * * \note There are use cases (e.g. memory overlays) that may want to set these values, but * don't do so unless you are an Expert. */ void setXY0(int const x0, int const y0) { setXY0(geom::Point2I(x0,y0)); } /** * Set the MaskedImage's origin * * The origin is usually set by the constructor, so you shouldn't need this function * * \note There are use cases (e.g. memory overlays) that may want to set these values, but * don't do so unless you are an Expert. */ void setXY0(geom::Point2I const origin) { if (_image) { _image->setXY0(origin); } if (_mask) { _mask->setXY0(origin); } if (_variance) { _variance->setXY0(origin); } } /** * @brief Convert image index to image position (see Image::indexToPosition) * * @return image position */ inline double indexToPosition( double ind, ///< image index lsst::afw::image::xOrY const xy ///< Is this a column or row coordinate? ) const { return getImage()->indexToPosition(ind, xy); } /** * @brief Convert image position to index (see Image::positionToIndex) * * @return std::pair(nearest integer index, fractional part) */ std::pair positionToIndex( double const pos, ///< image position lsst::afw::image::xOrY const xy ///< Is this a column or row coordinate? ) const { return getImage()->positionToIndex(pos, xy); } // // Iterators and Locators // iterator begin() const; iterator end() const; iterator at(int const x, int const y) const; reverse_iterator rbegin() const; reverse_iterator rend() const; fast_iterator begin(bool) const; fast_iterator end(bool) const; x_iterator row_begin(int y) const; x_iterator row_end(int y) const; /// Return an \c x_iterator at the point (x, y) x_iterator x_at(int x, int y) const { #if 0 typename Image::x_iterator imageEnd = getImage()->x_at(x, y); typename Mask::x_iterator maskEnd = getMask()->x_at(x, y); typename Variance::x_iterator varianceEnd = getVariance()->x_at(x, y); #else // bypass checks for non-NULL pointers typename Image::x_iterator imageEnd = _image->x_at(x, y); typename Mask::x_iterator maskEnd = _mask->x_at(x, y); typename Variance::x_iterator varianceEnd = _variance->x_at(x, y); #endif return x_iterator(imageEnd, maskEnd, varianceEnd); } y_iterator col_begin(int x) const; y_iterator col_end(int x) const; /// Return an \c y_iterator at the point (x, y) y_iterator y_at(int x, int y) const { #if 0 typename Image::y_iterator imageEnd = getImage()->y_at(x, y); typename Mask::y_iterator maskEnd = getMask()->y_at(x, y); typename Variance::y_iterator varianceEnd = getVariance()->y_at(x, y); #else // bypass checks for non-NULL pointers typename Image::y_iterator imageEnd = _image->y_at(x, y); typename Mask::y_iterator maskEnd = _mask->y_at(x, y); typename Variance::y_iterator varianceEnd = _variance->y_at(x, y); #endif return y_iterator(imageEnd, maskEnd, varianceEnd); } /// Return an \c xy_locator at the point (x, y) xy_locator xy_at(int x, int y) const { #if 0 typename Image::xy_locator imageEnd = getImage()->xy_at(x, y); typename Mask::xy_locator maskEnd = getMask()->xy_at(x, y); typename Variance::xy_locator varianceEnd = getVariance()->xy_at(x, y); #else // bypass checks for non-NULL pointers typename Image::xy_locator imageEnd = _image->xy_at(x, y); typename Mask::xy_locator maskEnd = _mask->xy_at(x, y); typename Variance::xy_locator varianceEnd = _variance->xy_at(x, y); #endif return xy_locator(imageEnd, maskEnd, varianceEnd); } private: LSST_PERSIST_FORMATTER(lsst::afw::formatters::MaskedImageFormatter) void conformSizes(); ImagePtr _image; MaskPtr _mask; VariancePtr _variance; }; /** * A function to return a MaskedImage of the correct type (cf. std::make_pair) */ template MaskedImage* makeMaskedImage( typename Image::Ptr image, ///< %image typename Mask::Ptr mask = typename Mask::Ptr(), ///< mask typename Image::Ptr variance = typename Image::Ptr() ///< variance ) { return new MaskedImage(image, mask, variance); } /* * Some metafunctions to extract an Image::Ptr from a MaskedImage::Ptr (or return the original Image::Ptr) * * GetImage is the public interface (it forwards the tag --- just for the sake of the UI); the real work * is in GetImage_ which defines a typedef for the Image and a static function, getImage * * E.g. * In the function * * template * void func(typename ImageT::Ptr image) { * typename GetImage::type::Ptr im = GetImage::getImage(image); * } * * "im" is an Image::Ptr irrespective of whether ImageT is Masked or not. */ namespace { template struct GetImage_ { typedef ImageT type; static typename type::Ptr getImage(typename ImageT::Ptr image) { return image; } }; template struct GetImage_ { typedef typename ImageT::Image type; static typename type::Ptr getImage(typename ImageT::Ptr image) { return image->getImage(); } }; } // anonymous namespace template struct GetImage : public GetImage_ { }; }}} // lsst::afw::image #endif // LSST_IMAGE_MASKEDIMAGE_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    bdc29e6a

    commit bdc29e6ad86424c77ce94df33957b3ee950deb92
    Author: Jim Bosch 
    Date:   Mon Nov 19 11:47:11 2012 -0500
    
        Re-enable RAM FITS reading, remove test cases that just test cfitsio.
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    2035d06f

    commit 2035d06f093eae708fc33e59f8733d7ed9303872
    Author: rhl 
    Date:   Mon Aug 22 19:16:06 2011 +0000
    
        Provided default of LOCAL for ImageOrigin in cctors
    

    271e8097

    commit 271e8097c7ebbadd88d2d43588a80148fdce619a
    Author: Jim Bosch 
    Date:   Mon Nov 19 12:50:21 2012 -0500
    
        Fix up and relocate doxygen for FITS-reading ctors.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    src/formatters/Utils.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    //
                    //##====----------------                                ----------------====##/
                    //
                    //! \file
                    //! \brief Support for formatters
                    //
                    //##====----------------                                ----------------====##/
                    
                    #include "boost/cstdint.hpp"
                    #include "boost/format.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/daf/base/PropertySet.h"
                    #include "lsst/daf/persistence/LogicalLocation.h"
                    #include "lsst/daf/persistence/DbTsvStorage.h"
                    #include "lsst/afw/formatters/Utils.h"
                    
                    using boost::int64_t;
                    namespace ex = lsst::pex::exceptions;
                    using lsst::daf::base::PropertySet;
                    using lsst::pex::policy::Policy;
                    using lsst::daf::persistence::LogicalLocation;
                    
                    namespace lsst {
                    namespace afw {
                    namespace formatters {
                    
                    int extractSliceId(CONST_PTR(PropertySet) const& properties) {
                        if (properties->isArray("sliceId")) {
    
    54 3771b5eb - throw LSST_EXCEPT(ex::RuntimeErrorException, "\"sliceId\" property has multiple values");
    ? ---------
    54 21597d88 + throw LSST_EXCEPT(ex::RuntimeError, "\"sliceId\" property has multiple values");
    } int sliceId = properties->getAsInt("sliceId"); if (sliceId < 0) {
    58 3771b5eb - throw LSST_EXCEPT(ex::RangeErrorException, "negative \"sliceId\"");
    ? ---------
    58 21597d88 + throw LSST_EXCEPT(ex::RangeError, "negative \"sliceId\"");
    } if (properties->exists("universeSize") && !properties->isArray("universeSize")) { int universeSize = properties->getAsInt("universeSize"); if (sliceId >= universeSize) {
    63 3771b5eb - throw LSST_EXCEPT(ex::RangeErrorException, "\"sliceId\" must be less than \"universeSize \"");
    ? ---------
    63 21597d88 + throw LSST_EXCEPT(ex::RangeError, "\"sliceId\" must be less than \"universeSize \"");
    } } return sliceId; } int extractVisitId(CONST_PTR(PropertySet) const& properties) { if (properties->isArray("visitId")) {
    71 3771b5eb - throw LSST_EXCEPT(ex::RuntimeErrorException, "\"visitId\" property has multiple values");
    ? ---------
    71 21597d88 + throw LSST_EXCEPT(ex::RuntimeError, "\"visitId\" property has multiple values");
    } int visitId = properties->getAsInt("visitId"); if (visitId < 0) {
    75 3771b5eb - throw LSST_EXCEPT(ex::RangeErrorException, "negative \"visitId\"");
    ? ---------
    75 21597d88 + throw LSST_EXCEPT(ex::RangeError, "negative \"visitId\"");
    } return visitId; } int64_t extractFpaExposureId(CONST_PTR(PropertySet) const& properties) { if (properties->isArray("fpaExposureId")) {
    82 5eb2a46a - throw LSST_EXCEPT(ex::RuntimeErrorException, "\"fpaExposureId\" property has multiple values");
    ? ---------
    82 21597d88 + throw LSST_EXCEPT(ex::RuntimeError, "\"fpaExposureId\" property has multiple values");
    } int64_t fpaExposureId = properties->getAsInt64("fpaExposureId"); if (fpaExposureId < 0) {
    86 5eb2a46a - throw LSST_EXCEPT(ex::RangeErrorException, "negative \"fpaExposureId\"");
    ? ---------
    86 21597d88 + throw LSST_EXCEPT(ex::RangeError, "negative \"fpaExposureId\"");
    } if ((fpaExposureId & 0xfffffffe00000000LL) != 0LL) {
    89 5eb2a46a - throw LSST_EXCEPT(ex::RangeErrorException, "\"fpaExposureId\" is too large");
    ? ---------
    89 21597d88 + throw LSST_EXCEPT(ex::RangeError, "\"fpaExposureId\" is too large");
    } return fpaExposureId; } int extractCcdId(CONST_PTR(PropertySet) const& properties) { if (properties->isArray("ccdId")) {
    96 3771b5eb - throw LSST_EXCEPT(ex::RuntimeErrorException, "\"ccdId\" property has multiple values");
    ? ---------
    96 21597d88 + throw LSST_EXCEPT(ex::RuntimeError, "\"ccdId\" property has multiple values");
    } int ccdId = properties->getAsInt("ccdId"); if (ccdId < 0) {
    100 0c5aa969 - throw LSST_EXCEPT(ex::RangeErrorException, "negative \"ccdId\"");
    ? ---------
    100 21597d88 + throw LSST_EXCEPT(ex::RangeError, "negative \"ccdId\"");
    } if (ccdId > 255) {
    103 3771b5eb - throw LSST_EXCEPT(ex::RangeErrorException, "\"ccdId\" is too large");
    ? ---------
    103 21597d88 + throw LSST_EXCEPT(ex::RangeError, "\"ccdId\" is too large");
    } return static_cast(ccdId); } int extractAmpId(CONST_PTR(PropertySet) const& properties) { if (properties->isArray("ampId")) {
    110 1d4373d7 - throw LSST_EXCEPT(ex::RuntimeErrorException, "\"ampId\" property has multiple values");
    ? ---------
    110 21597d88 + throw LSST_EXCEPT(ex::RuntimeError, "\"ampId\" property has multiple values");
    } int ampId = properties->getAsInt("ampId"); if (ampId < 0) {
    114 1d4373d7 - throw LSST_EXCEPT(ex::RangeErrorException, "negative \"ampId\"");
    ? ---------
    114 21597d88 + throw LSST_EXCEPT(ex::RangeError, "negative \"ampId\"");
    } if (ampId > 63) {
    117 1d4373d7 - throw LSST_EXCEPT(ex::RangeErrorException, "\"ampId\" is too large");
    ? ---------
    117 21597d88 + throw LSST_EXCEPT(ex::RangeError, "\"ampId\" is too large");
    } return (extractCcdId(properties) << 6) + ampId; } int64_t extractCcdExposureId(CONST_PTR(PropertySet) const& properties) { if (properties->isArray("ccdExposureId")) {
    124 88a1923c - throw LSST_EXCEPT(ex::RuntimeErrorException, "\"ccdExposureId\" property has multiple values");
    ? ---------
    124 21597d88 + throw LSST_EXCEPT(ex::RuntimeError, "\"ccdExposureId\" property has multiple values");
    } int64_t ccdExposureId = properties->getAsInt64("ccdExposureId"); if (ccdExposureId < 0) {
    128 88a1923c - throw LSST_EXCEPT(ex::RangeErrorException, "negative \"ccdExposureId\"");
    ? ---------
    128 21597d88 + throw LSST_EXCEPT(ex::RangeError, "negative \"ccdExposureId\"");
    } return ccdExposureId; } int64_t extractAmpExposureId(CONST_PTR(PropertySet) const& properties) { if (properties->isArray("ampExposureId")) {
    135 88a1923c - throw LSST_EXCEPT(ex::RuntimeErrorException, "\"ampExposureId\" property has multiple values");
    ? ---------
    135 21597d88 + throw LSST_EXCEPT(ex::RuntimeError, "\"ampExposureId\" property has multiple values");
    } int64_t ampExposureId = properties->getAsInt64("ampExposureId"); if (ampExposureId < 0) {
    139 88a1923c - throw LSST_EXCEPT(ex::RangeErrorException, "negative \"ampExposureId\"");
    ? ---------
    139 21597d88 + throw LSST_EXCEPT(ex::RangeError, "negative \"ampExposureId\"");
    } return ampExposureId; } /** * Extracts and returns the string-valued @c "itemName" property from the given data property object. *
    147 3771b5eb - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    147 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * If the given pointer is null, or the @c PropertySet pointed * to does not contain a unique property named @c "itemName". */ std::string const getItemName(CONST_PTR(PropertySet) const& properties) { if (!properties) {
    153 3771b5eb - throw LSST_EXCEPT(ex::InvalidParameterException, "Null PropertySet::Ptr");
    ? ^^^^^^ ^
    153 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError, "Null PropertySet::Ptr");
    ? ^^ ^ } if (properties->isArray("itemName")) {
    156 3771b5eb - throw LSST_EXCEPT(ex::InvalidParameterException, "\"itemName\" property has multiple values");
    ? ^^^^^^ ^
    156 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError, "\"itemName\" property has multiple values");
    ? ^^ ^ } return properties->getAsString("itemName"); } /** * Returns @c true if and only if @a properties is non-null and contains a * unique property with the given name that has type @c bool and a value of @c true. */ bool extractOptionalFlag( CONST_PTR(PropertySet) const& properties, std::string const & name ) { if (properties && properties->exists(name)) { return properties->getAsBool(name); } return false; } /** * Returns the name of the table that a single slice of a pipeline involved in the processing * of a single visit should use for persistence of a particular output. All slices can be * configured to use the same (per-visit) table name using policy parameters. * * @param[in] policy The @c Policy containing the table name pattern ("${itemName}.tableNamePattern", * where ${itemName} is looked up in @a properties using the "itemName" key) * from which the the actual table name is derived. This pattern may contain * a set of parameters in @c %(key) format - these are interpolated by looking up @c "key" in * the @a properties PropertySet. * * @param[in] properties Provides runtime specific properties necessary to construct the * output table name. * @return table name */ std::string const getTableName( CONST_PTR(Policy) const& policy, CONST_PTR(PropertySet) const& properties ) { std::string itemName(getItemName(properties)); return LogicalLocation(policy->getString(itemName + ".tableNamePattern"), properties).locString(); } /** * Stores the name of the table that each slice of a pipeline involved in processing a visit * used for persistence of its outputs. If slices were configured to all use the same (per-visit) * table name, a single name is stored. * * @param[in] policy The @c Policy containing the table name pattern ("${itemName}.tableNamePattern", * where ${itemName} is looked up in @a properties using the "itemName" key) * from which the the actual table name is derived. This pattern may contain * a set of parameters in @c %(key) format - these are interpolated by looking up @c "key" in * the @a properties PropertySet. * * @param[in] properties The runtime specific properties necessary to construct the table names. * * string. The @c "visitId" property must also be present, and shall be a non-negative integer of type * @c int64_t uniquely identifying the current LSST visit. If the @c "${itemName}.isPerSliceTable" * property is present, is of type @c bool and is set to @c true, then it is assumed that * @c "${itemName}.numSlices" (a positive integer of type @c int) output tables exist and * are to be read in. * * @return a list of table names * @sa getTableName() */ std::vector getAllSliceTableNames( CONST_PTR(Policy) const& policy, CONST_PTR(PropertySet) const& properties ) { std::string itemName(getItemName(properties)); std::string pattern(policy->getString(itemName + ".tableNamePattern")); int numSlices = 1; if (properties->exists(itemName + ".numSlices")) { numSlices = properties->getAsInt(itemName + ".numSlices"); } if (numSlices <= 0) {
    234 88a1923c - throw LSST_EXCEPT(ex::RuntimeErrorException,
    ? ---------
    234 21597d88 + throw LSST_EXCEPT(ex::RuntimeError,
    itemName + " \".numSlices\" property value must be positive"); } std::vector names; names.reserve(numSlices); PTR(PropertySet) props = properties->deepCopy(); for (int i = 0; i < numSlices; ++i) { props->set("sliceId", i); names.push_back(LogicalLocation(pattern, props).locString()); } return names; } /** * Creates the table identified by calling getTableName() with the given @a policy and @a properties. * A key named @c "${itemName}.templateTableName" (where @c ${itemName} refers to the value of a * property named @c "itemName" extracted from @a properties) must be available and set to the name * of the template table to use for creation. * * Note that the template table must exist in the database identified by @a location, and that if * the desired table already exists, an exception is thrown. */ void createTable( lsst::daf::persistence::LogicalLocation const & location, CONST_PTR(lsst::pex::policy::Policy) const& policy, CONST_PTR(PropertySet) const& properties ) { std::string itemName(getItemName(properties)); std::string name(getTableName(policy, properties)); std::string model(policy->getString(itemName + ".templateTableName")); lsst::daf::persistence::DbTsvStorage db; db.setPersistLocation(location); db.createTableFromTemplate(name, model); } /** Drops the database table(s) identified by getAllSliceTables(). */ void dropAllSliceTables( lsst::daf::persistence::LogicalLocation const & location, CONST_PTR(lsst::pex::policy::Policy) const& policy, CONST_PTR(PropertySet) const& properties ) { std::vector names = getAllSliceTableNames(policy, properties); lsst::daf::persistence::DbTsvStorage db; db.setPersistLocation(location); for (std::vector::const_iterator i(names.begin()), end(names.end()); i != end; ++i) { db.dropTable(*i); } } std::string formatFitsProperties(CONST_PTR(lsst::daf::base::PropertySet) const& prop) { typedef std::vector NameList; std::string sout; NameList paramNames = prop->paramNames(false); for (NameList::const_iterator i = paramNames.begin(), end = paramNames.end(); i != end; ++i) { std::size_t lastPeriod = i->rfind(char('.')); std::string name = (lastPeriod == std::string::npos) ? *i : i->substr(lastPeriod + 1); std::type_info const & type = prop->typeOf(*i); std::string out = ""; if (name.size() > 8) { // Oh dear; too long for a FITS keyword out += "HIERARCH = " + name; } else { out = (boost::format("%-8s= ") % name).str(); } if (type == typeid(int)) { out += (boost::format("%20d") % prop->get(*i)).str(); } else if (type == typeid(double)) { out += (boost::format("%20.15g") % prop->get(*i)).str(); } else if (type == typeid(std::string)) { out += (boost::format("'%-67s' ") % prop->get(*i)).str(); } int const len = out.size(); if (len < 80) { out += std::string(80 - len, ' '); } else { out = out.substr(0, 80); } sout += out; } return sout.c_str(); } int countFitsHeaderCards(CONST_PTR(lsst::daf::base::PropertySet) const& prop) { return prop->paramNames(false).size(); } }}} // namespace lsst::afw::formatters

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0c5aa969

    commit 0c5aa969a8d49e0422238f9470056cb2d7ba9ced
    Author: smm 
    Date:   Tue Mar 10 00:53:16 2009 +0000
    
        Fix formatters to work with altered pex_policy API, include package level policy header in SWIG files to pick up policy exceptions
    

    5eb2a46a

    commit 5eb2a46abf3360c30731562a46dc55ab3f662687
    Author: ktlim 
    Date:   Thu Apr 9 23:49:33 2009 +0000
    
        Clarify exposureId vs. fpaExposureId.  Include fpaExposureId in database.
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    1d4373d7

    commit 1d4373d77681dd6f2c42254606dfcb7a8b549bc1
    Author: ktlim 
    Date:   Fri Mar 6 23:28:48 2009 +0000
    
        Add support for extracting subimages from FITS files using additionalData keys to specify the HDU and bounding box.  Fix identifier generation to match DC3a proposal.
    

    88a1923c

    commit 88a1923c4cf6a95e4e8fe0f7f6368f90630c8f35
    Author: smm 
    Date:   Fri Mar 13 18:52:36 2009 +0000
    
        Use ampExposureId to generate DIASource and Source ids. Use LogicalLocation to do string interpolation for table name patterns
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/math/Integrate.h

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #if !defined(LSST_AFW_MATH_INTEGRATE_H)
                    #define LSST_AFW_MATH_INTEGRATE_H 1
                    /**
                     * @file Integrate.h
                     * @brief Compute 1d and 2d integral
                     * @ingroup afw
                     * @author Mike Jarvis (original), included in LSST code by Steve Bickerton
                     *
                     */
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    
                    #include "lsst/afw/math/IntGKPData10.h"
                    
                    // == The following is Mike Jarvis original comment ==
                    //
                    // Basic Usage:
                    //
                    // First, define a function object, which should derive from 
                    // std::unary_function.  For example, to integrate a
                    // Gaussian, use something along the lines of this:
                    //
                    // class Gauss :
                    //   public std::unary_function
                    // {   
                    //   public :
                    // 
                    //     Gauss(double _mu, double _sig) :   
                    //       mu(_mu), sig(_sig), sigsq(_sig*_sig) {}
                    // 
                    //     double operator()(double x) const
                    //     {
                    //       const double SQRTTWOPI = 2.50662827463;
                    //       return exp(-pow(x-mu,2)/2./sigsq)/SQRTTWOPI/sig;
                    //     }
                    // 
                    //   private :
                    //     double mu,sig,sigsq;
                    // };
                    //
                    // Next, make an IntRegion object with the bounds of the integration region.
                    // You need to give it the type to use for the bounds and the value of the
                    // functions (which need to be the same currently - some day I'll allow 
                    // complex functions...).  
                    //
                    // For example, to integrate something from -1 to 1, use:
                    //
                    // integ::IntRegion reg1(-1.,1.);
                    //
                    // (The integ:: is because everything here is in the integ namespace to
                    // help prevent name conflicts with other header files.)
                    //
                    // If a value is > 1.e10 or < -1.e10, then these values are taken to be
                    // infinity, rather than the actual value.  
                    // So to integrate from 0 to infinity:
                    //
                    // integ::IntRegion reg2(0.,1.e100);
                    //
                    // Or, you can use the variable integ::MOCK_INF which might be clearer.
                    //
                    //
                    // Finally, to perform the integral, the line would be:
                    //
                    // double integ1 = int1d(Gauss(0.,1.),reg1,1.e-10,1.e-4);
                    // double integ2 = int1d(Gauss(0.,2.),reg2,1.e-10,1.e-4);
                    //
                    // which should yield 0.68 and 0.5 in our case.
                    //
                    // Those last two numbers indicate the precision required.  
                    // 1.e-10 is the required absolute error, and 
                    // 1.e-4 is the required relative error.
                    //
                    // If you want, you can omit these and 1.e-15,1.e-6 will be used as the 
                    // default precision (which are generally fine for most purposes).
                    //
                    // The absolute error only comes into play for results which are close to 
                    // 0 to prevent requiring an error of 0 for integrals which evaluate to 0 
                    // or very close to it.
                    //
                    //
                    //
                    // Advanced Usage:
                    //
                    // When an integration fails to converge with the usual GKP algorithm,
                    // it splits the region into 2 (or more) and tries again with each sub-region.
                    // The default is to just bisect the region (or something similarly smart for
                    // infinite regions), but if you know of a good place to split the region,
                    // you can tell it using:
                    //
                    // reg.AddSplit(10.)
                    //
                    // For example, if you know that you have a singularity somewhere in your
                    // region, it would help the program a lot to split there, so you 
                    // should add that as a split point.  Zeros can also be good choices.
                    //
                    // In addition to the integral being returned from int1d, int2d, or int3d as
                    // the return value, the value is also stored in the region itself. 
                    // You can access it using:
                    //
                    // reg.Area();
                    //
                    // There is also an estimate of the error in the value:
                    //
                    // reg.Err();
                    //
                    // (It is intended to be an overestimate of the actual error, 
                    // but it doesn't always get it completely right.)
                    //
                    //
                    // 
                    // Two- and Three-Dimensional Integrals:
                    //
                    // These are slightly more complicated.  The easiest case is when the
                    // bounds of the integral are a rectangle or 3d box.  In this case,
                    // you can still use the regular IntRegion.  The only new thing then
                    // is the definition of the function.  For example, to integrate 
                    // int(3x^2 + xy + y , x=0..1, y=0..1):
                    //
                    // struct Integrand :
                    //   public std::binary_function
                    // {
                    //   double operator()(double x, double y) const
                    //   { return x*(3.*x + y) + y; }
                    // };
                    //
                    // integ::IntRegion reg3(0.,1.);
                    // double integ3 = int2d(Integrand(),reg3,reg3);
                    //
                    // (Which should give 1.75 as the result.)
                    // 
                    //
                    //
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    
                    double const MOCK_INF = 1.e10;
                    
                    #ifdef NDEBUG
                    #define integ_dbg1 if (false) (*_dbgout)
                    #define integ_dbg2 if (false) (*(reg.getDbgout()))
                    #define integ_dbg3 if (false) (*(tempreg.getDbgout()))
                    #else
                    #define integ_dbg1 if (_dbgout) (*_dbgout)
                    #define integ_dbg2 if (reg.getDbgout()) (*(reg.getDbgout()))
                    #define integ_dbg3 if (tempreg.getDbgout()) (*(tempreg.getDbgout()))
                    #endif
                    
                    //#define COUNTFEVAL 
                    // If defined, then count the number of function evaluations
                                
                    namespace details {            
                    template  inline T norm(const T& x) { return x*x; }
                    using std::norm;
                    template  inline T real(const T& x) { return x; }
                    using std::real;
                    #ifdef COUNTFEVAL
                        int nfeval = 0;
                    #endif
                    }
                                
                                
                    template 
                    struct IntRegion {
                    
                    public:
                        IntRegion(T const a, T const b, std::ostream* dbgout = 0) :
                            _a(a), _b(b), _error(0.0), _area(0), _dbgout(dbgout) {}
                        
                        bool operator<(IntRegion const &r2) const { return _error < r2._error; }
                        bool operator>(IntRegion const &r2) const { return _error > r2._error; }
                        
                        void SubDivide(std::vector >* children) {
                            assert(children->size() == 0);
                            if (_splitpoints.size() == 0) { Bisect(); }
                            if (_splitpoints.size() > 1) {
                                std::sort(_splitpoints.begin(), _splitpoints.end());
                            }
                            
                    #if 0
                            if (_a > _splitpoints[0] || _b < _splitpoints.back()) {
                                std::cerr << "a, b = " << _a << ', ' << _b << std::endl;
                                std::cerr << "_splitpoints = ";
                                for (size_t i = 0; i<_splitpoints.size(); i++)  {
                                    std::cerr << _splitpoints[i] << "  ";
                                }
                                std::cerr << std::endl;
                            }
                    #endif
                            assert(_splitpoints[0] >= _a);
                            assert(_splitpoints.back() <= _b);
                            children->push_back(IntRegion(_a, _splitpoints[0], _dbgout));
                            for (size_t i = 1; i<_splitpoints.size(); i++) {
                                children->push_back(IntRegion(_splitpoints[i-1], _splitpoints[i], _dbgout));
                            }
                            children->push_back(IntRegion(_splitpoints.back(), _b, _dbgout));
                        }
                        
                        void Bisect() { _splitpoints.push_back((_a + _b)/2.0); }
                        void AddSplit(const T x) { _splitpoints.push_back(x); }
                        size_t NSplit() const { return _splitpoints.size(); }
                        
                        T const &Left() const { return _a; }
                        T const &Right() const  {return _b; }
                        T const &Err() const { return _error; }
                        T const &Area() const { return _area; }
                        void SetArea(const T& a, const T& e) {
                            _area = a;
                            _error = e;
                        }
                    
                        std::ostream* getDbgout() { return _dbgout; }
                    
                    private:
                        T _a, _b, _error, _area;
                        std::vector _splitpoints;
                        std::ostream* _dbgout;
                        
                    };
                                
                                
                    double const DEFABSERR = 1.e-15;
                    double const DEFRELERR = 1.e-6;
                     
                    namespace details {            
                                
                    template 
                    inline T Epsilon() { return std::numeric_limits::epsilon(); }
                    template 
                    inline T MinRep()  { return std::numeric_limits::min(); }
                    
                    
                    #ifdef EXTRA_PREC_H
                    template <>
                    inline Quad Epsilon() { return 3.08148791094e-33; }
                    template <>
                    inline Quad MinRep()  { return 2.2250738585072014e-308; }
                    #endif
                    
                        
                    template 
                    inline T rescale_error (T err, T const &resabs, T const &resasc) {
                        if (resasc != 0.0 && err != 0.0) {
                            T const scale = (200.0 * err / resasc);
                            if (scale < 1.0) {
                                err = resasc * scale * sqrt(scale);
                            }
                            else {
                                err = resasc;
                            }
                        }
                        if (resabs > MinRep() / (50.0 * Epsilon())) {
                            T const min_err = 50.0 * Epsilon() * resabs;
                            if (min_err > err) {
                                err = min_err;
                            }
                        }
                        return err;
                    }
                    
                    /**
                     * @brief Non-adaptive integration of the function f over the region 'reg'.
                     * 
                     * @note The algorithm computes first a Gaussian quadrature value
                     *       then successive Kronrod/Patterson extensions to this result.
                     *       The functions terminates when the difference between successive
                     *       approximations (rescaled according to rescale_error) is less than 
                     *       either epsabs or epsrel * I, where I is the latest estimate of the 
                     *       integral.
                     *       The order of the Gauss/Kronron/Patterson scheme is determined
                     *       by which file is included above.  Currently schemes starting 
                     *       with order 1 and order 10 are calculated.  There seems to be 
                     *       little practical difference in the integration times using 
                     *       the two schemes, so I haven't bothered to calculate any more.
                     */
                        
                    template 
                    inline bool intGKPNA(
                                         UF const &func, IntRegion& reg,
                                         typename UF::result_type const epsabs, 
                                         typename UF::result_type const epsrel,
                                         std::map* fxmap = 0) {
                        
                        typedef typename UF::result_type UfResult;
                        UfResult const a = reg.Left();
                        UfResult const b = reg.Right();
                                       
                        UfResult const halfLength =  0.5 * (b - a);
                        UfResult const absHalfLength = fabs (halfLength);
                        UfResult const center = 0.5 * (b + a);
                        UfResult const fCenter = func(center);
                    #ifdef COUNTFEVAL
                        nfeval++;
                    #endif
                        
                        assert(gkp_wb(0).size() == gkp_x(0).size() + 1);
                        UfResult area1 = gkp_wb(0).back() * fCenter;
                        std::vector fv1, fv2;
                        fv1.reserve(2*gkp_x(0).size() + 1);
                        fv2.reserve(2*gkp_x(0).size() + 1);
                        for (size_t k = 0; k(0).size(); k++) {
                            UfResult const abscissa = halfLength * gkp_x(0)[k];
                            UfResult const fval1 = func(center - abscissa);
                            UfResult const fval2 = func(center + abscissa);
                            area1 += gkp_wb(0)[k] * (fval1 + fval2);
                            fv1.push_back(fval1);
                            fv2.push_back(fval2);
                            if (fxmap) {
                                (*fxmap)[center - abscissa] = fval1;
                                (*fxmap)[center + abscissa] = fval2;
                            }
                        }
                    #ifdef COUNTFEVAL
                        nfeval += gkp_x(0).size()*2;
                    #endif
                        
                        integ_dbg2 << "level 0 rule: area = " << area1 << std::endl;
                        
                        UfResult err = 0; 
                        bool calcabsasc = true;
                        UfResult resabs = 0.0, resasc = 0.0;
                        for (int level = 1; level < NGKPLEVELS; level++) {
                            assert(gkp_wa(level).size() == fv1.size());
                            assert(gkp_wa(level).size() == fv2.size());
                            assert(gkp_wb(level).size() == gkp_x(level).size() + 1);
                            UfResult area2 = gkp_wb(level).back() * fCenter;
                            // resabs = approximation to integral of abs(f)
                            if (calcabsasc) {
                                resabs = fabs(area2);
                            }
                            for (size_t k = 0; k < fv1.size(); k++) {
                                area2 += gkp_wa(level)[k] * (fv1[k] + fv2[k]);
                                if (calcabsasc) {
                                    resabs += gkp_wa(level)[k] * (fabs(fv1[k]) + fabs(fv2[k]));
                                }
                            }
                            for (size_t k = 0; k < gkp_x(level).size(); k++) {
                                UfResult const abscissa = halfLength * gkp_x(level)[k];
                                UfResult const fval1 = func(center - abscissa);
                                UfResult const fval2 = func(center + abscissa);
                                UfResult const fval = fval1 + fval2;
                                area2 += gkp_wb(level)[k] * fval;
                                if (calcabsasc) {
                                    resabs += gkp_wb(level)[k] * (fabs(fval1) + fabs(fval2));
                                }
                                fv1.push_back(fval1);
                                fv2.push_back(fval2);
                                if (fxmap) {
                                    (*fxmap)[center - abscissa] = fval1;
                                    (*fxmap)[center + abscissa] = fval2;
                                }
                            }
                    #ifdef COUNTFEVAL
                            nfeval += gkp_x(level).size()*2;
                    #endif
                            if (calcabsasc) {
                                UfResult const mean = area1*UfResult(0.5);
                                // resasc = approximation to the integral of abs(f-mean) 
                                resasc = gkp_wb(level).back() * fabs(fCenter - mean);
                                for (size_t k = 0; k(level).size(); k++) {
                                    resasc += gkp_wa(level)[k] * (fabs(fv1[k] - mean) + fabs(fv2[k] - mean));
                                }
                                for (size_t k = 0; k(level).size(); k++) {
                                    resasc += gkp_wb(level)[k] * (fabs(fv1[k] - mean) + fabs(fv2[k] - mean));
                                }
                                resasc *= absHalfLength;
                                resabs *= absHalfLength;
                            }
                            area2 *= halfLength;
                            err = rescale_error (fabs(area2 - area1), resabs, resasc) ;
                            if (err < resasc) {
                                calcabsasc = false;
                            }
                            
                            integ_dbg2 << "at level " << level << " area2 = " << area2;
                            integ_dbg2 << " +- " << err << std::endl;
                            
                            //   test for convergence.
                            if (err < epsabs || err < epsrel * fabs (area2)) {
                                reg.SetArea(area2, err);
                                return true;
                            }
                            area1 = area2;
                        }
                        
                        // failed to converge 
                        reg.SetArea(area1, err);
                        
                        integ_dbg2 << "Failed to reach tolerance with highest-order GKP rule";
                        
                        return false;
                    }
                    
                    
                    /**
                     * @brief An adaptive integration algorithm which computes the integral of f over the region reg.
                     *
                     * @note First the non-adaptive GKP algorithm is tried.
                     *       If that is not accurate enough (according to the absolute and
                     *       relative accuracies, epsabs and epsrel),
                     *       the region is split in half, and each new region is integrated.
                     *       The routine continues by successively splitting the subregion
                     *       which gave the largest absolute error until the integral converges.
                     *       
                     *       The area and estimated error are returned as reg.Area() and reg.Err()
                     *       If desired, *retx and *retf return std::vectors of x,f(x) respectively
                     *       They only include the evaluations in the non-adaptive pass, so they
                     *       do not give an accurate estimate of the number of function evaluations.
                     */
                        
                    template 
                    inline void intGKP (
                                        UF const &func, IntRegion ®,
                                        typename UF::result_type const epsabs,
                                        typename UF::result_type const epsrel,
                                        std::map* fxmap = 0) {
                    
                        typedef typename UF::result_type UfResult;
                        integ_dbg2 << "Start intGKP\n";
                        
                        assert(epsabs >= 0.0);
                        assert(epsrel > 0.0);
                        
                        // perform the first integration 
                        bool done = intGKPNA(func, reg, epsabs, epsrel, fxmap);
                        if (done) return;
                        
                        integ_dbg2 << "In adaptive GKP, failed first pass... subdividing\n";
                        integ_dbg2 << "Intial range = " << reg.Left() << ".." << reg.Right() << std::endl;
                        
                        int roundoffType1 = 0, errorType = 0;
                        UfResult roundoffType2 = 0;
                        size_t iteration = 1;
                        
                        std::priority_queue, std::vector > > allregions;
                        allregions.push(reg);
                        UfResult finalarea = reg.Area();
                        UfResult finalerr = reg.Err();
                        UfResult tolerance = std::max(epsabs, epsrel * fabs(finalarea));
                        assert(finalerr > tolerance);
                        
                        while (!errorType && finalerr > tolerance) {
                            // Bisect the subinterval with the largest error estimate 
                            integ_dbg2 << "Current answer = " << finalarea << " +- " << finalerr;
                            integ_dbg2 << "  (tol = " << tolerance << ")\n";
                            IntRegion parent = allregions.top(); 
                            allregions.pop();
                            integ_dbg2 << "Subdividing largest error region ";
                            integ_dbg2 << parent.Left() << ".." << parent.Right() << std::endl;
                            integ_dbg2 << "parent area = " << parent.Area();
                            integ_dbg2 << " +- " << parent.Err() << std::endl;
                            std::vector > children;
                            parent.SubDivide(&children);
                            // For "GKP", there are only two, but for GKPOSC, there is one 
                            // for each oscillation in region
                            
                            // Try to do at least 3x better with the children
                            UfResult factor = 3*children.size()*finalerr/tolerance;
                            UfResult newepsabs = fabs(parent.Err()/factor);
                            UfResult newepsrel = newepsabs/fabs(parent.Area());
                            integ_dbg2 << "New epsabs, rel = " << newepsabs << ", " << newepsrel;
                            integ_dbg2 << "  (" << children.size() << " children)\n";
                            
                            UfResult newarea = UfResult(0.0);
                            UfResult newerror = 0.0;
                            for (size_t i = 0; i& child = children[i];
                                integ_dbg2 << "Integrating child " << child.Left();
                                integ_dbg2 << ".." << child.Right() << std::endl;
                                bool hasConverged;
                                hasConverged = intGKPNA(func, child, newepsabs, newepsrel);
                                integ_dbg2 << "child (" << i + 1 << '/' << children.size() << ") ";
                                if (hasConverged) {
                                    integ_dbg2 << " converged.";
                                } else {
                                    integ_dbg2 << " failed.";
                                }
                                integ_dbg2 << "  Area = " << child.Area() << " +- " << child.Err() << std::endl;
                                
                                newarea += child.Area();
                                newerror += child.Err();
                            }
                            integ_dbg2 << "Compare: newerr = " << newerror;
                            integ_dbg2 << " to parent err = " << parent.Err() << std::endl;
                            
                            finalerr += (newerror - parent.Err());
                            finalarea += newarea - parent.Area();
                            
                            UfResult delta = parent.Area() - newarea;
                            if (newerror <= parent.Err() && fabs (delta) <=  parent.Err()
                                && newerror >= 0.99 * parent.Err()) {
                                integ_dbg2 << "roundoff type 1: delta/newarea = ";
                                integ_dbg2 << fabs(delta)/fabs(newarea);
                                integ_dbg2 << ", newerror/error = " << newerror/parent.Err() << std::endl;
                                roundoffType1++;
                            }
                            if (iteration >= 10 && newerror > parent.Err() && 
                                fabs(delta) <= newerror - parent.Err()) {
                                integ_dbg2 << "roundoff type 2: newerror/error = ";
                                integ_dbg2 << newerror/parent.Err() << std::endl;
                                roundoffType2 += std::min(newerror/parent.Err() - 1.0, UfResult(1.0));
                            }
                            
                            tolerance = std::max(epsabs, epsrel * fabs(finalarea));
                            if (finalerr > tolerance) {
                                if (roundoffType1 >= 200) {
                                    errorType = 1; // round off error 
                                    integ_dbg2 << "GKP: Round off error 1\n";
                                }
                                if (roundoffType2 >= 200.0) {
                                    errorType = 2; // round off error 
                                    integ_dbg2 << "GKP: Round off error 2\n";
                                }
                                if (fabs((parent.Right() - parent.Left())/(reg.Right() - reg.Left())) 
                                    < Epsilon()) {
                                    errorType = 3; // found singularity
                                    integ_dbg2 << "GKP: Probable singularity\n";
                                }
                            }
                            for (size_t i = 0; i const &r = allregions.top();
                            finalarea += r.Area();
                            finalerr += r.Err();
                            allregions.pop();
                        }
                        reg.SetArea(finalarea, finalerr);
                        
                        if (errorType == 1) {
                            std::ostringstream s;
                            s << "Type 1 roundoff's = " << roundoffType1;
                            s << ", Type 2 = " << roundoffType2 << std::endl;
                            s << "Roundoff error 1 prevents tolerance from being achieved ";
                            s << "in intGKP\n";
    
    581 9964091c - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, s.str());
    ? ---------
    581 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, s.str());
    } else if (errorType == 2) { std::ostringstream s; s << "Type 1 roundoff's = " << roundoffType1; s << ", Type 2 = " << roundoffType2 << std::endl; s << "Roundoff error 2 prevents tolerance from being achieved "; s << "in intGKP\n";
    588 9964091c - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, s.str());
    ? ---------
    588 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, s.str());
    } else if (errorType == 3) { std::ostringstream s; s << "Bad integrand behavior found in the integration interval "; s << "in intGKP\n";
    593 9964091c - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, s.str());
    ? ---------
    593 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, s.str());
    } } /** * @brief Auxiliary struct 1 * */ template struct AuxFunc1 : // f(1/x-1) for int(a..infinity) public std::unary_function { public: AuxFunc1(const UF& f) : _f(f) {} typename UF::result_type operator()(typename UF::argument_type x) const { return _f(1.0/x - 1.0)/(x*x); } private: UF const &_f; }; /** * @brief Auxiliary function 1 * */ template AuxFunc1 inline Aux1(UF uf) { return AuxFunc1(uf); } template struct AuxFunc2 : // f(1/x+1) for int(-infinity..b) public std::unary_function { public: AuxFunc2(UF const &f) : _f(f) {} typename UF::result_type operator()(typename UF::argument_type x) const { return _f(1.0/x + 1.0)/(x*x); } private: UF const &_f; }; /** * @brief Auxiliary function 2 * */ template AuxFunc2 inline Aux2(UF uf) { return AuxFunc2(uf); } /** * @brief Helpers for constant regions for int2d, int3d: * */ template struct ConstantReg1 : public std::unary_function > { ConstantReg1(T a, T b) : ir(a, b) {} ConstantReg1(IntRegion const &r) : ir(r) {} IntRegion operator()(T) const { return ir; } IntRegion ir; }; template struct ConstantReg2 : public std::binary_function > { ConstantReg2(T a, T b) : ir(a, b) {} ConstantReg2(IntRegion const &r) : ir(r) {} IntRegion operator()(T x, T y) const { return ir; } IntRegion ir; }; // pulled from MoreFunctional.h. Needed in class Int2DAuxType and Int3DAuxType template class binder2_1 : public std::unary_function { public: binder2_1(const BF& oper, typename BF::first_argument_type val) : _oper(oper), _value(val) {} typename BF::result_type operator()(const typename BF::second_argument_type& x) const { return _oper(_value, x); } protected: BF _oper; typename BF::first_argument_type _value; }; template inline binder2_1 bind21(const BF& oper, const Tp& x) { typedef typename BF::first_argument_type Arg; return binder2_1(oper, static_cast(x)); } template class Int2DAuxType : public std::unary_function { public: Int2DAuxType(BF const &func, YREG const &yreg, typename BF::result_type const &abserr, typename BF::result_type const &relerr) : _func(func), _yreg(yreg), _abserr(abserr), _relerr(relerr) {} typename BF::result_type operator()(typename BF::first_argument_type x) const { typename YREG::result_type tempreg = _yreg(x); typename BF::result_type result = int1d(bind21(_func, x), tempreg, _abserr, _relerr); integ_dbg3 << "Evaluated int2dAux at x = " << x; integ_dbg3 << ": f = " << result << " +- " << tempreg.Err() << std::endl; return result; } private: BF const &_func; YREG const &_yreg; typename BF::result_type _abserr, _relerr; }; // pulled from MoreFunctional.h. Needed in class Int3DAuxtype template class binder3_1 : public std::binary_function { public: binder3_1(const TF& oper, typename TF::firstof3_argument_type val) : _oper(oper), _value(val) {} typename TF::result_type operator()(typename TF::secondof3_argument_type const &x1, typename TF::thirdof3_argument_type const &x2) const { return _oper(_value, x1, x2); } protected: TF _oper; typename TF::firstof3_argument_type _value; }; template inline binder3_1 bind31(const TF& oper, const Tp& x) { typedef typename TF::firstof3_argument_type Arg; return binder3_1(oper, static_cast(x)); } template class Int3DAuxType : public std::unary_function { public: Int3DAuxType(const TF& func, const YREG& yreg, const ZREG& zreg, const typename TF::result_type& abserr, const typename TF::result_type& relerr) : _func(func), _yreg(yreg), _zreg(zreg), _abserr(abserr), _relerr(relerr) {} typename TF::result_type operator()(typename TF::firstof3_argument_type x) const { typename YREG::result_type tempreg = _yreg(x); typename TF::result_type result = int2d(bind31(_func, x), tempreg, bind21(_zreg, x), _abserr, _relerr); integ_dbg3 << "Evaluated int3dAux at x = " << x; integ_dbg3 << ": f = " << result << " +- " << tempreg.Err() << std::endl; return result; } private: const TF& _func; const YREG& _yreg; const ZREG& _zreg; typename TF::result_type _abserr, _relerr; }; } // end namespace details /** * @brief Front end for the 1d integrator */ template inline typename UF::result_type int1d( UF const &func, IntRegion& reg, typename UF::result_type const &abserr = DEFABSERR, typename UF::result_type const &relerr = DEFRELERR) { typedef typename UF::result_type UfResult; using namespace details; integ_dbg2 << "start int1d: " << reg.Left() << ".." << reg.Right() << std::endl; if ((reg.Left() <= -MOCK_INF && reg.Right() > 0) || (reg.Right() >= MOCK_INF && reg.Left() < 0)) { reg.AddSplit(0); } if (reg.NSplit() > 0) { std::vector > children; reg.SubDivide(&children); integ_dbg2 << "Subdivided into " << children.size() << " children\n"; UfResult answer = UfResult(); UfResult err = 0; for (size_t i = 0; i& child = children[i]; integ_dbg2 << "i = " << i; integ_dbg2 << ": bounds = " << child.Left() << ", " << child.Right() << std::endl; answer += int1d(func, child, abserr, relerr); err += child.Err(); integ_dbg2 << "subint = " << child.Area() << " +- " << child.Err() << std::endl; } reg.SetArea(answer, err); return answer; } else { if (reg.Left() <= -MOCK_INF) { integ_dbg2 << "left = -infinity, right = " << reg.Right() << std::endl; assert(reg.Right() <= 0.0); IntRegion modreg(1.0/(reg.Right() - 1.0), 0.0, reg.getDbgout()); intGKP(Aux2(func), modreg, abserr, relerr); reg.SetArea(modreg.Area(), modreg.Err()); } else if (reg.Right() >= MOCK_INF) { integ_dbg2 << "left = " << reg.Left() << ", right = infinity\n"; assert(reg.Left() >= 0.0); IntRegion modreg(0.0, 1.0/(reg.Left() + 1.0), reg.getDbgout()); intGKP(Aux1(func), modreg, abserr, relerr); reg.SetArea(modreg.Area(), modreg.Err()); } else { integ_dbg2 << "left = " << reg.Left(); integ_dbg2 << ", right = " << reg.Right() << std::endl; intGKP(func, reg, abserr, relerr); } integ_dbg2 << "done int1d answer = " << reg.Area(); integ_dbg2 << " +- " << reg.Err() << std::endl; return reg.Area(); } } /** * @brief Front end for the 2d integrator */ template inline typename BF::result_type int2d( BF const &func, IntRegion ®, YREG const &yreg, typename BF::result_type const &abserr = DEFABSERR, typename BF::result_type const &relerr = DEFRELERR) { using namespace details; integ_dbg2 << "Starting int2d: range = "; integ_dbg2 << reg.Left() << ".." << reg.Right() << std::endl; Int2DAuxType faux(func, yreg, abserr*1.0e-3, relerr*1.0e-3); typename BF::result_type answer = int1d(faux, reg, abserr, relerr); integ_dbg2 << "done int2d answer = " << answer << " +- " << reg.Err() << std::endl; return answer; } /** * @brief Front end for the 3d integrator */ template inline typename TF::result_type int3d( TF const &func, IntRegion& reg, YREG const &yreg, ZREG const &zreg, typename TF::result_type const &abserr = DEFABSERR, typename TF::result_type const &relerr = DEFRELERR) { using namespace details; integ_dbg2 << "Starting int3d: range = "; integ_dbg2 << reg.Left() << ".." << reg.Right() << std::endl; Int3DAuxType faux(func, yreg, zreg, abserr*1.e-3, relerr*1.e-3); typename TF::result_type answer = int1d(faux, reg, abserr, relerr); integ_dbg2 << "done int3d answer = " << answer << " +- " << reg.Err() << std::endl; return answer; } /** * @brief Front end for the 2d integrator */ template inline typename BF::result_type int2d( BF const &func, IntRegion ®, IntRegion &yreg, typename BF::result_type const &abserr = DEFABSERR, typename BF::result_type const &relerr = DEFRELERR) { using namespace details; return int2d(func, reg, ConstantReg1(yreg), abserr, relerr); } /** * @brief Front end for the 3d integrator */ template inline typename TF::result_type int3d( TF const &func, IntRegion ®, IntRegion &yreg, IntRegion &zreg, typename TF::result_type const &abserr = DEFABSERR, typename TF::result_type const &relerr = DEFRELERR) { using namespace details; return int3d(func, reg, ConstantReg1(yreg), ConstantReg2(zreg), abserr, relerr); } // ============================================================= /** * @brief The 1D integrator * * @note This simply wraps the int1d function above and handles the * instantiation of the intRegion. * */ template typename UnaryFunctionT::result_type integrate(UnaryFunctionT func, typename UnaryFunctionT::argument_type const a, typename UnaryFunctionT::argument_type const b, double eps = 1.0e-6) { typedef typename UnaryFunctionT::argument_type Arg; IntRegion region(a, b); return int1d(func, region, DEFABSERR, eps); } namespace details { /** * @class FunctionWrapper * * @brief Wrap an integrand in a call to a 1D integrator: romberg() * * When romberg2D() is called, it wraps the integrand it was given * in a FunctionWrapper functor. This wrapper calls romberg() on the integrand * to get a 1D (along the x-coord, for constant y) result . * romberg2D() then calls romberg() with the FunctionWrapper functor as an * integrand. * * @author S. Bickerton (adapted from RHL's SDSS C code) */ template class FunctionWrapper : public std::unary_function { public: FunctionWrapper(BinaryFunctionT func, typename BinaryFunctionT::first_argument_type const x1, typename BinaryFunctionT::first_argument_type const x2, double const eps = 1.0e-6) : _func(func), _x1(x1), _x2(x2), _eps(eps) {} typename BinaryFunctionT::result_type operator()(typename BinaryFunctionT::second_argument_type const y) const { return integrate(std::bind2nd(_func, y), _x1, _x2, _eps); } private: BinaryFunctionT _func; typename BinaryFunctionT::first_argument_type _x1, _x2; double _eps; }; } // end of namespace afw::math::details // ============================================================= /** * @brief The 2D integrator * * @note Adapted from RHL's SDSS code */ template typename BinaryFunctionT::result_type integrate2d(BinaryFunctionT func, typename BinaryFunctionT::first_argument_type const x1, typename BinaryFunctionT::first_argument_type const x2, typename BinaryFunctionT::second_argument_type const y1, typename BinaryFunctionT::second_argument_type const y2, double eps = 1.0e-6) { using namespace details; // note the more stringent eps requirement to ensure the requested limit // can be reached. FunctionWrapper fwrap(func, x1, x2, eps); return integrate(fwrap, y1, y2, eps); } }}} // end namespaces lsst/afw/math #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9964091c

    commit 9964091c98bc6b9daa98b6379ea1b22c6fa85e91
    Author: rowen 
    Date:   Wed Mar 16 23:04:33 2011 +0000
    
        I tried to eliminate doxygen warnings in afw 1556. I came pretty close. There are two known issues:
        - Doxygen has a bug that prevents documenting template specializations. There are two of these in
           src/geom/Extent.cc
           that I hide from Doxygen with a note and \cond BUG406027
        - src/coord/Coord.cc produces two Doxygen warnings that I've not been able to eliminate. I don't have any idea what is causing them.
        
        Unfortunately, fixing Doxygen warnings requires some cluttering up the the code, in particular spelling out namespaces in arguments.
        
        
        Other changes:
        - std::osstream operator<< functions in AffineTransform.h and LinearTransform.h were friend functions, but did not need to be. I changed this, partly because Doxygen was unhappy.
        - I removed all use of "namespace foo=lsst::..."  in header files.
        - I replaced daf::base:: with lsst::daf::base:: in some header files. I'm surprised the former worked; I've reported it as a bug against daf_base.
        
        BTW: this code fails on Mac OS X Leopard; the tests/footprintArray.cc fails to compile.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/geom/SConscript

    Diff:

                    # -*- python -*-
                    from lsst.sconsUtils import scripts
                    scripts.BasicSConscript.python(['geomLib'])
    
    4 c2b0c503 -

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    c2b0c503

    commit c2b0c503a629b28be7ecee948d082b72516cecb7
    Author: Bob Armstrong 
    Date:   Fri Sep 5 16:33:15 2014 -0400
    
        Polygon: Add table based persistance for Polygon.
        
        This required a split of the Python wrappers for Polygon into a separate module, in its
        own namespace, to resolve a circular dependency.  As part of this, Polygons are now passed around
        by shared_pointer instead of by-value.
    

    Commits in /Users/nate/repos_lsst/afw/

    Return to list

    include/lsst/afw/detection/Footprint.h

    Diff:

                    /* 
                     * LSST Data Management System
    
    3 a6d55f08 - * Copyright 2008, 2009, 2010 LSST Corporation.
    ? ^^^^^^^^ ^
    3 c839d0f2 + * Copyright 2008-2015 LSST Corporation.
    ? ^ ^ * * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the LSST License Statement and * the GNU General Public License along with this program. If not, * see . */ #if !defined(LSST_DETECTION_FOOTPRINT_H) #define LSST_DETECTION_FOOTPRINT_H /** * \file * \brief Represent a set of pixels of an arbitrary shape and size * * Footprint is fundamental in astronomical image processing, as it defines what * is meant by a Source. */ #include #include #include #include #include #include #include "ndarray.h" #include "lsst/base.h" #include "lsst/pex/policy/Policy.h" #include "lsst/afw/image/MaskedImage.h" #include "lsst/afw/image/Wcs.h" #include "lsst/afw/detection/Peak.h" #include "lsst/afw/geom.h" #include "lsst/afw/geom/ellipses.h" #include "lsst/afw/table/fwd.h" #include "lsst/afw/table/io/Persistable.h"
    49 c839d0f2 + namespace lsst { namespace afw { namespace detection {
    49 35570270 - namespace lsst {
    50 17d1d529 - namespace afw {
    51 17d1d529 - namespace detection {
    using geom::Span; /************************************************************************************************************/ /*! * \brief A set of pixels in an Image * * A Footprint is a set of pixels, usually but not necessarily contiguous. * There are constructors to find Footprints above some threshold in an Image * (see FootprintSet), or to create Footprints in the shape of various * geometrical figures */ class Footprint : public lsst::daf::base::Citizen, public afw::table::io::PersistableFacade, public afw::table::io::Persistable { public: typedef boost::shared_ptr Ptr; typedef boost::shared_ptr ConstPtr; /// The Footprint's Span list typedef std::vector SpanList;
    73 94770baf + /**
    74 94770baf + * Create a Footprint
    75 94770baf + *
    76 94770baf + * \throws lsst::pex::exceptions::InvalidParameterException in nspan is < 0
    77 94770baf + *
    78 94770baf + * nspan: initial number of Span%s in this Footprint
    79 94770baf + * region: Bounding box of MaskedImage footprint
    80 94770baf + */
    explicit Footprint(int nspan = 0, geom::Box2I const & region=geom::Box2I());
    83 94770baf + /**
    84 94770baf + * Create a rectangular Footprint
    85 94770baf + */
    explicit Footprint(afw::table::Schema const & peakSchema, int nspan=0, geom::Box2I const & region=geom::Box2I()); explicit Footprint(geom::Box2I const & bbox, geom::Box2I const & region=geom::Box2I()); Footprint(geom::Point2I const & center, double const radius, geom::Box2I const & = geom::Box2I()); explicit Footprint(geom::ellipses::Ellipse const & ellipse, geom::Box2I const & region=geom::Box2I()); explicit Footprint(SpanList const & spans, geom::Box2I const & region=geom::Box2I());
    94 94770baf +
    95 94770baf + /**
    96 94770baf + * Construct a footprint from a list of spans. Resulting Footprint is
    97 94770baf + * not normalized.
    98 94770baf + */
    Footprint(Footprint const & other);
    100 94770baf +
    virtual ~Footprint();
    103 94770baf + /**
    104 94770baf + * Is this a HeavyFootprint?
    105 94770baf + */
    virtual bool isHeavy() const { return false; }
    90 f8edfe90 - int getId() const { return _fid; } //!< Return the Footprint's unique ID
    91 9fdf87da - SpanList& getSpans() { return _spans; } //!< return the Span%s contained in this Footprint
    92 9fdf87da - const SpanList& getSpans() const { return _spans; } //!< return the Span%s contained in this Footprint
    108 94770baf + /** Return the Footprint's unique ID. */
    109 94770baf + int getId() const { return _fid; }
    110 94770baf +
    111 94770baf + /** Return the Span%s contained in this Footprint. */
    112 94770baf + SpanList& getSpans() { return _spans; }
    113 94770baf +
    114 94770baf + /** Return the Span%s contained in this Footprint. */
    115 94770baf + const SpanList& getSpans() const { return _spans; }
    /** * Return the Peaks contained in this Footprint * * The peaks should be ordered by decreasing pixel intensity at the peak position (so the most negative * peak appears last). Users that add new Peaks manually are responsible for maintaining this sorting. */ PeakCatalog & getPeaks() { return _peaks; } const PeakCatalog & getPeaks() const { return _peaks; } /// Convenience function to add a peak (since that'd now be multiple lines without this function) PTR(PeakRecord) addPeak(float fx, float fy, float value);
    105 6ac35e07 -
    106 4dface89 - /**
    107 4dface89 - * Sort Peaks from most positive value to most negative.
    108 4dface89 - *
    109 4dface89 - * If the key passed is invalid (the default) PeakTable::getPeakValueKey() will be used.
    110 4dface89 - */
    111 4dface89 - void sortPeaks(afw::table::Key const & key=afw::table::Key());
    /// Set the Schema used by the PeakCatalog (will throw if PeakCatalog is not empty). void setPeakSchema(afw::table::Schema const & peakSchema) { if (!getPeaks().empty()) { throw LSST_EXCEPT(
    117 a64e361f - pex::exceptions::LogicErrorException,
    ? ---------
    133 c12d3b48 + pex::exceptions::LogicError,
    "Cannot change the PeakCatalog schema unless it is empty" ); } // this syntax doesn't work in Python, which is why this method has to exist getPeaks() = PeakCatalog(peakSchema); }
    125 b3dcd175 - int getNpix() const { return _area; } //!< Return the number of pixels in this Footprint (the real number of pixels, not the area of the bbox)
    141 94770baf + /**
    142 94770baf + * Return the number of pixels in this Footprint (the real number
    143 007ca4a2 + * of pixels, not the area of the bbox).
    144 94770baf + */
    145 94770baf + int getNpix() const { return _area; }
    int getArea() const { return _area; }
    147 94770baf +
    148 94770baf + /**
    149 94770baf + * Return the Footprint's centroid
    150 94770baf + *
    151 94770baf + * The centroid is calculated as the mean of the pixel centers
    152 94770baf + */
    geom::Point2D getCentroid() const;
    154 94770baf +
    155 94770baf + /**
    156 94770baf + * Return the Footprint's shape (interpreted as an ellipse)
    157 94770baf + *
    158 94770baf + * The shape is determined by measuring the moments of the pixel
    159 94770baf + * centers about its centroid (cf. getCentroid)
    160 94770baf + */
    geom::ellipses::Quadrupole getShape() const;
    163 94770baf + /**
    164 94770baf + * Add a Span to a footprint, returning a reference to the new Span.
    165 94770baf + */
    const Span& addSpan(const int y, const int x0, const int x1);
    167 94770baf + /**
    168 94770baf + * Add a Span to a Footprint returning a reference to the new Span
    169 94770baf + */
    const Span& addSpan(Span const& span);
    171 94770baf + /**
    172 94770baf + * Add a Span to a Footprint returning a reference to the new Span
    173 94770baf + */
    const Span& addSpan(Span const& span, int dx, int dy);
    176 94770baf + /**
    177 94770baf + * Add a Span to a Footprint, where the Spans MUST be added in order
    178 94770baf + * (first in increasing y, then increasing x), and MUST NOT be
    179 94770baf + * overlapping. This method does NOT reset the _normalized boolean.
    180 94770baf + *
    181 94770baf + * This method is useful when a Footprint is being constructed in
    182 94770baf + * such a way that Spans are guaranteed to be produced in order.
    183 94770baf + * In that case, it is not necessary to normalize() the Footprint
    184 94770baf + * after all the Spans have been added. This can save some
    185 94770baf + * computation.
    186 94770baf + */
    const Span& addSpanInSeries(const int y, const int x0, const int x1);
    189 94770baf + /**
    190 94770baf + * Shift a Footprint by (dx, dy)
    191 94770baf + *
    192 94770baf + * dx: How much to move footprint in column direction
    193 94770baf + * dy: How much to move in row direction
    194 94770baf + */
    void shift(int dx, int dy); void shift(geom::ExtentI d) {shift(d.getX(), d.getY());} /// Return the Footprint's bounding box geom::Box2I getBBox() const { return _bbox; } /// Return the corners of the MaskedImage the footprints live in geom::Box2I const & getRegion() const { return _region; } /// Set the corners of the MaskedImage wherein the footprints dwell void setRegion(geom::Box2I const & region) { _region = region; } void clipTo(geom::Box2I const & bbox);
    209 94770baf + /**
    210 94770baf + * Clips the given *Footprint* to the region in the *Image*
    211 94770baf + * containing non-zero values. The clipping drops spans that are
    212 94770baf + * totally zero, and moves endpoints to non-zero; it does not
    213 94770baf + * split spans that have internal zeros.
    214 94770baf + */
    template void clipToNonzero(lsst::afw::image::Image const& img);
    218 94770baf + /**
    219 94770baf + * Does this Footprint contain this pixel?
    220 94770baf + */
    bool contains(geom::Point2I const& pix) const;
    223 94770baf + /**
    224 94770baf + * Normalise a Footprint, sorting spans and setting the BBox
    225 94770baf + */
    void normalize(); bool isNormalized() const {return _normalized;}
    229 94770baf + /**
    230 94770baf + * Set the pixels in idImage that are in Footprint by adding the
    231 94770baf + * specified value to the Image.
    232 94770baf + *
    233 94770baf + * idImage: Image to contain the footprint
    234 94770baf + * id: Add id to idImage for pixels in the Footprint
    235 94770baf + * region: Footprint's region (default: getRegion())
    236 94770baf + */
    template void insertIntoImage(typename lsst::afw::image::Image& idImage, boost::uint64_t const id, geom::Box2I const& region=geom::Box2I() ) const;
    242 94770baf +
    243 94770baf + /**
    244 94770baf + * Set the pixels in idImage which are in Footprint by adding the
    245 94770baf + * specified value to the Image.
    246 94770baf + *
    247 94770baf + * The list of ids found under the new Footprint are returned.
    248 94770baf + *
    249 94770baf + * idImage: Image to contain the footprint
    250 94770baf + * id: Add id to idImage for pixels in the Footprint
    251 94770baf + * overwriteId: should id replace any value already in idImage?
    252 94770baf + * idMask: Don't overwrite ID bits in this mask
    253 94770baf + * oldIds: if non-NULL, set the IDs that were overwritten
    254 94770baf + * region: Footprint's region (default: getRegion())
    255 94770baf + */
    template void insertIntoImage(typename lsst::afw::image::Image& idImage, boost::uint64_t const id, bool const overwriteId, long const idMask, typename std::set *oldIds, geom::Box2I const& region=geom::Box2I() ) const;
    264 94770baf + /**
    265 94770baf + * Assignment operator. Will not change the id
    266 94770baf + */
    Footprint & operator=(Footprint & other);
    269 94770baf + /**
    270 94770baf + * \brief Intersect the Footprint with a Mask
    271 94770baf + *
    272 94770baf + * The resulting Footprint contains only pixels for which (mask & bitMask) == 0;
    273 94770baf + * it may have disjoint pieces. Any part of the footprint that falls outside the
    274 94770baf + * bounds of the mask will be clipped.
    275 94770baf + *
    276 94770baf + */
    template void intersectMask( image::Mask const & mask, MaskPixelT bitmask=~0x0 ); /** * @brief Transform the footprint from one WCS to another * * @param[in] source Wcs that defines the coordinate system of the input footprint. * @param[in] target Wcs that defines that desired coordinate system of the returned footprint. * @param[in] region Used to set the "region" box of the returned footprint; note that this is * NOT the same as the footprint's bounding box. * @param[in] doClip If true, clip the new footprint to the region bbox before returning it. */ PTR(Footprint) transform( image::Wcs const & source, image::Wcs const & target, geom::Box2I const & region, bool doClip=true ) const; /**
    196 5d1934cc - * @brief Update the Footprint in-place to be the union of itself and all its children
    ? ------- - ^
    300 de65f62a + * @brief Update the Footprint in-place to be the union of itself and all others provided
    ? +++++++++++ ^
    197 5d1934cc - *
    198 ddb75eb2 - * Only spans will be modified; peaks will be left unchanged. If ignoreSelf is true it
    199 ddb75eb2 - * will only be the union of all its children.
    200 5d1934cc - */
    ? -
    301 0b2457bc + *
    302 0b2457bc + * Only spans will be modified; peaks will be left unchanged.
    303 0b2457bc + *
    304 de65f62a + * NOTE: this is for the case of contiguous sets of footprints.
    305 c12d3b48 + * If the union is disjoint, throw RuntimeError Exception.
    306 0b2457bc + */
    201 ddb75eb2 - void include(std::vector const & children, bool ignoreSelf=false);
    ? ^ ^^^ ----------------------- -
    307 de65f62a + void include(std::vector const & others);
    ? ^^ ^ bool isPersistable() const { return true; } protected: virtual std::string getPersistenceName() const; virtual std::string getPythonModule() const; virtual void write(OutputArchiveHandle & handle) const; //@{ /// Persistence implementation functions made available for derived classes void readSpans(afw::table::BaseCatalog const & spanCat); void readPeaks(afw::table::BaseCatalog const & peakCat); //@} friend class FootprintFactory; private: friend class FootprintMerge; static int id; mutable int _fid; //!< unique ID int _area; //!< number of pixels in this Footprint (not the area of the bbox) SpanList _spans; //!< the Spans contained in this Footprint geom::Box2I _bbox; //!< the Footprint's bounding box PeakCatalog _peaks; //!< the Peaks lying in this footprint mutable geom::Box2I _region; //!< The corners of the MaskedImage the footprints live in bool _normalized; //!< Are the spans sorted? };
    342 94770baf + /**
    343 94770baf + Given a vector of Footprints, fills the output "argmin" and "dist"
    344 94770baf + images to contain the Manhattan distance to the nearest footprint (in
    345 94770baf + "dist") and the identity of the nearest footprint (in "argmin").
    346 94770baf +
    347 94770baf + For example, if there are two footprints at y=0 covering x=[1,2] and [7,7],
    348 94770baf +
    349 94770baf + Index : 0 1 2 3 4 5 6 7
    350 94770baf +
    351 94770baf + Footprints: . 0 0 . . . . 1
    352 94770baf +
    353 94770baf + Argmin : 0 0 0 0 0 1 1 1
    354 94770baf +
    355 94770baf + Dist : 1 0 0 1 2 2 1 0
    356 94770baf +
    357 94770baf + "argmin" gives the index of the nearest footprint, and "dist" its
    358 94770baf + Manhattan (L_1 norm) distance. The pixel at index 4 is closest to
    359 94770baf + footprint 0, and its distance is 2.
    360 94770baf + */
    236 9337578a - void nearestFootprint(std::vector const& foots,
    ? ^^^^^
    361 94770baf + void nearestFootprint(std::vector const& foots,
    ? ++++ ^ lsst::afw::image::Image::Ptr argmin, lsst::afw::image::Image::Ptr dist);
    365 94770baf + /**
    366 94770baf + Merges two Footprints -- appends their peaks, and unions their
    367 94770baf + spans, returning a new Footprint.
    368 94770baf +
    369 94770baf + This const version requires that both input footprints are
    370 94770baf + normalized (and will raise an exception if not).
    371 94770baf + */
    240 61b6195c - Footprint::Ptr mergeFootprints(Footprint const& foot1, Footprint const& foot2);
    ? ^^^^^
    372 94770baf + PTR(Footprint) mergeFootprints(Footprint const& foot1, Footprint const& foot2);
    ? ++++ ^
    373 94770baf +
    374 94770baf + /**
    375 94770baf + Merges two Footprints -- appends their peaks, and unions their
    376 94770baf + spans, returning a new Footprint.
    377 94770baf + */
    241 61b6195c - Footprint::Ptr mergeFootprints(Footprint& foot1, Footprint& foot2);
    ? ^^^^^
    378 94770baf + PTR(Footprint) mergeFootprints(Footprint& foot1, Footprint& foot2);
    ? ++++ ^
    380 94770baf + /**
    381 9e8aab29 + * Shrink a footprint isotropically by nGrow pixels, returning a new Footprint.
    382 89e96d0e + */
    383 ae20e2b5 + PTR(Footprint) shrinkFootprint(Footprint const& foot, int nGrow, bool isotropic);
    384 89e96d0e +
    385 89e96d0e + /**
    386 9e8aab29 + * Grow a Footprint by nGrow pixels, returning a new Footprint.
    387 94770baf + */
    243 61b6195c - Footprint::Ptr growFootprint(Footprint const& foot, int ngrow, bool isotropic=true);
    ? ^^^^^ ^
    388 dddc9b36 + PTR(Footprint) growFootprint(Footprint const& foot, int nGrow, bool isotropic=true);
    ? ++++ ^ ^
    389 574e0785 +
    390 94770baf + /**
    391 9e8aab29 + * \note Deprecated interface; use the Footprint const& version.
    392 94770baf + */
    244 61b6195c - Footprint::Ptr growFootprint(Footprint::Ptr const& foot, int ngrow, bool isotropic=true);
    ? ^^^^^ ^^^^^ ^
    393 dddc9b36 + PTR(Footprint) growFootprint(PTR(Footprint) const& foot, int nGrow, bool isotropic=true);
    ? ++++ ^ ++++ ^ ^
    394 94770baf +
    395 94770baf + /**
    396 94770baf + * \brief Grow a Footprint in at least one of the cardinal directions,
    397 94770baf + * returning a new Footprint
    398 94770baf + *
    399 94770baf + * Note that any left/right grow is done prior to the up/down grow, so
    400 94770baf + * any left/right grown pixels \em are subject to a further up/down
    401 94770baf + * grow (i.e. an initial single pixel Footprint will end up as a
    402 94770baf + * square, not a cross.
    403 94770baf + */
    245 61b6195c - Footprint::Ptr growFootprint(Footprint const& foot, int ngrow,
    ? ^^^^^ ^
    404 dddc9b36 + PTR(Footprint) growFootprint(Footprint const& foot, int nGrow,
    ? ++++ ^ ^ bool left, bool right, bool up, bool down);
    407 94770baf + /**
    408 94770baf + * Return a list of BBox%s, whose union contains exactly the pixels in
    409 94770baf + * foot, neither more nor less
    410 94770baf + *
    411 94770baf + * Useful in generating sets of meas::algorithms::Defects for the ISR
    412 94770baf + */
    std::vector footprintToBBoxList(Footprint const& foot);
    415 94770baf + /**
    416 94770baf + * \brief Set all image pixels in a Footprint to a given value
    417 94770baf + *
    418 94770baf + * \return value
    419 94770baf + */
    template typename ImageT::Pixel setImageFromFootprint(ImageT *image, Footprint const& footprint, typename ImageT::Pixel const value);
    424 94770baf +
    425 94770baf + /**
    426 94770baf + * \brief Set all image pixels in a set of Footprint%s to a given value
    427 94770baf + *
    428 94770baf + * \return value
    429 94770baf + */
    template typename ImageT::Pixel setImageFromFootprintList(ImageT *image,
    256 f9d4c054 - CONST_PTR(std::vector) footprints,
    ? ^^^^^
    432 94770baf + CONST_PTR(std::vector) footprints,
    ? ++++ ^ typename ImageT::Pixel const value);
    434 94770baf +
    435 94770baf + /**
    436 94770baf + * \brief Set all image pixels in a set of Footprint%s to a given value
    437 94770baf + *
    438 94770baf + * \return value
    439 94770baf + */
    template typename ImageT::Pixel setImageFromFootprintList(ImageT *image,
    260 2eb9dac3 - std::vector const& footprints,
    ? ^^^^^
    442 94770baf + std::vector const& footprints,
    ? ++++ ^ typename ImageT::Pixel const value);
    444 94770baf +
    445 94770baf + /**
    446 94770baf + * \brief OR bitmask into all the Mask's pixels that are in the Footprint
    447 94770baf + *
    448 94770baf + * \return bitmask
    449 94770baf + */
    template MaskT setMaskFromFootprint(lsst::afw::image::Mask *mask, Footprint const& footprint, MaskT const bitmask);
    454 94770baf +
    455 94770baf + /**
    456 94770baf + * \brief (AND ~bitmask) all the Mask's pixels that are in the
    457 94770baf + * Footprint; that is, set to zero in the Mask-intersecting-Footprint
    458 94770baf + * all bits that are 1 in then bitmask.
    459 94770baf + *
    460 94770baf + * \return bitmask
    461 94770baf + */
    template MaskT clearMaskFromFootprint(lsst::afw::image::Mask *mask, Footprint const& footprint, MaskT const bitmask);
    271 76f3706f - /// Copy pixels defined by a footprint between images
    272 76f3706f - ///
    273 76f3706f - /// Respects image xy0, so the footprints should be defined in the
    274 76f3706f - /// "PARENT" frame.
    275 76f3706f - ///
    276 76f3706f - /// Pixels that are in the footprint but do not overlap with both
    277 76f3706f - /// images are not copied.
    467 94770baf + /**
    468 94770baf + Copies pixels from input image to output image within the Footprint's
    469 94770baf + area.
    470 94770baf +
    471 94770baf + The input and output image must be the same type -- either Image or
    472 94770baf + MaskedImage.
    473 94770baf + */
    template void copyWithinFootprint(Footprint const& foot, PTR(ImageOrMaskedImageT) const input, PTR(ImageOrMaskedImageT) output); /************************************************************************************************************/ /** * \brief OR bitmask into all the Mask's pixels which are in the set of Footprint%s * * \return bitmask */ template MaskT setMaskFromFootprintList(lsst::afw::image::Mask *mask,
    291 2eb9dac3 - std::vector const& footprints,
    ? ^^^^^
    487 94770baf + std::vector const& footprints,
    ? ++++ ^ MaskT const bitmask);
    489 94770baf +
    490 94770baf + /**
    491 94770baf + * \brief OR bitmask into all the Mask's pixels which are in the set of Footprint%s
    492 94770baf + *
    493 94770baf + * \return bitmask
    494 94770baf + */
    template MaskT setMaskFromFootprintList(lsst::afw::image::Mask *mask,
    295 a8f86353 - CONST_PTR(std::vector) const & footprints,
    ? ^^^^^ -
    497 94770baf + CONST_PTR(std::vector) const& footprints,
    ? ++++ ^ MaskT const bitmask);
    499 94770baf +
    500 94770baf + /**
    501 94770baf + * \brief Return a Footprint that's the intersection of a Footprint with a Mask
    502 94770baf + *
    503 94770baf + * The resulting Footprint contains only pixels for which (mask & bitMask) != 0;
    504 94770baf + * it may have disjoint pieces
    505 94770baf + *
    506 94770baf + * \note This isn't a member of Footprint as Footprint isn't templated over MaskT
    507 94770baf + *
    508 94770baf + * foot: The initial Footprint
    509 94770baf + * mask: The mask to & with foot
    510 94770baf + * bitmask: Only consider these bits
    511 94770baf + *
    512 94770baf + * \returns Returns the new Footprint
    513 94770baf + */
    template
    298 9fdf87da - Footprint::Ptr footprintAndMask(Footprint::Ptr const& foot,
    ? ^^^^^ ^^^^^ -
    515 94770baf + PTR(Footprint) footprintAndMask(PTR(Footprint) const& foot,
    ? ++++ ^ ++++ ^
    299 9fdf87da - typename image::Mask::Ptr const& mask,
    ? -
    516 94770baf + typename image::Mask::Ptr const& mask,
    MaskT const bitmask); /************************************************************************************************************/
    304 f8edfe90 - }}}
    521 c839d0f2 + }}} // namespace lsst::afw::detection
    #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    4dface89

    commit 4dface89496957978717e5a72752ca15609287a6
    Author: Jim Bosch 
    Date:   Thu Apr 16 11:48:49 2015 -0400
    
        Add method to sort Peaks within a Footprint.
        
        Peaks should almost always be sorted from most positive to most negative.
        While Footprint doesn't enforce that condition, we need to make it easier
        for external code to do so.
    

    6ac35e07

    commit 6ac35e07a70a600e59ed290a1b8fb3173bdbf21d
    Author: Jim Bosch 
    Date:   Thu Nov 13 16:22:23 2014 -0500
    
        Replace Peak with PeakRecord
        
        By using afw::table objects to store Peaks, we allow additional
        information to be added to Peaks without requiring further changes
        to persistence.
    

    2eb9dac3

    commit 2eb9dac33eec6f13a73c03cc2827aa9884ff06cc
    Author: rowen 
    Date:   Mon Sep 28 22:55:55 2009 +0000
    
        Removed all tabs.
    

    ddb75eb2

    commit ddb75eb2dc0ce9b2871dc265597db934b75531e5
    Author: Bob Armstrong 
    Date:   Fri May 1 14:03:26 2015 -0400
    
        Footprint: modify include method to ignore itself.
        
        This modification allows you to modify a footprint in-place to be the union
        of a list of footprints that are not necessarily contiguous.
    

    f9d4c054

    commit f9d4c0544640f89e818122e41c8d262c8369d540
    Author: rhl 
    Date:   Mon Feb 28 10:56:53 2011 +0000
    
        getFootprints was returning a potentially dangling reference... (blame a younger RHL).  Swig doesn't like mixing shared pointers to const with shared pointers to Foo
    

    76f3706f

    commit 76f3706f6688b23d5b0c71e66af3e94095a9f821
    Author: Paul Price 
    Date:   Wed Sep 17 12:30:21 2014 -0400
    
        copyWithinFootprint: respect image size
        
        copyWithinFootprint could produce a segfault (or at least corrupt
        memory) when copying a Footprint that is larger than either of the
        images.  Changed so that pixels outside either image are ignored
        (i.e., it copies every pixel it is able to).  Added test of this
        behaviour and documented the function's behaviour.
    

    5d1934cc

    commit 5d1934cc9fe7d8c43aa8f9318a1ac9a3ce85e94e
    Author: Jim Bosch 
    Date:   Wed Apr 16 17:20:02 2014 -0400
    
        Add Footprint method to merge with neighbors
    

    17d1d529

    commit 17d1d529ed63e98f98e5d1a7a7da4811e95fc26c
    Author: dubcovsky 
    Date:   Tue Feb 15 00:00:43 2011 +0000
    
        #1556 Split Footprint.h into Threshold.h, FootprintSet.h, and FootprintFunctor.h, to correspond with class names. Added a constructors to Footprint which use geom objects (BoxI and Ellipse) to construct footprints. Footprints now exclusively use geom::PointI and geom::BoxI internally. (but still accept image::PointI and image::BBox for backwards compatibility wherever possible). FootprintArray.h contains a static functions to flatten and expand ndarrays using a Footprint to map between 2-d and 1-d indices.
    

    9337578a

    commit 9337578a740b1b809c3e65eb8e52fa91254cfffd
    Author: Dustin Lang 
    Date:   Fri Apr 11 13:54:58 2014 -0400
    
        add nearesteFootprint() function; instantiate a broader range of Footprint functions for int images
    

    a8f86353

    commit a8f86353b4d794d8e2accd0ce6950e72a06c3f66
    Merge: a128aac 246b6dd
    Author: dubcovsky 
    Date:   Thu Mar 31 20:50:37 2011 +0000
    
        #1556 trunk merged to ticket branch
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    35570270

    commit 355702709fadee7ac3db15237924fa3283ec298b
    Author: rhl 
    Date:   Thu Aug 19 21:02:50 2010 +0000
    
        Implement Footprint.contains()
    

    b3dcd175

    commit b3dcd17547b9491944f77e4fe31128b569aaf7fe
    Author: Dustin Lang 
    Date:   Fri May 18 23:06:14 2012 -0400
    
        save HeavyFootprints to FITS, with extra junk
    

    9fdf87da

    commit 9fdf87da399be2fb3e9e4bc41984a2b5c6c2f838
    Author: jarvis 
    Date:   Thu Jun 24 05:21:13 2010 +0000
    
        Made a few changes to Footprint and FootprintSet to get rid of
        bare pointers which are not exception safe and were causing memory leaks.
        
        In Footprint:
        Changed _spans and _peaks to std::vector, rather than std::vector&
        (which were both initialized as *new std::vector<...> and then the address
        of the reference was deleted in the destructor).  These didn't require any
        such functionality, so leave them as normal vector's and let std::vector
        do the memory management itself.
        
        By the way, it doesn't seem like _peaks is being used.  The only use is
        in a line that is commented out.  Should this member be removed?
        
        In FootprintSet:
        Changed _footprints and _region to be boost::shared_ptr<> rather than
        a reference (which again was initialized with *new, and only _footprints
        was being deleted).  I think these could probably also switch to being
        stored by value, but that would technically change some of the functionality
        of the class -- specifically shallow copies.  I believe storing these
        values as shared_ptr's keeps the shallow copy behavior, but now without
        the memory leaks.  (It is also more exception safe now.)  However, it
        should be considered whether this is the desired behavior for this class
        or if shallow copies were an oversight.
        
        
        Furthermore, I checked that no other pieces of code in afw contain the
        string "*new ", so I believe there aren't any other similar
        memory leaks lurking in other parts of afw at least.  I didn't grep
        through all the other modules, though.
    

    a64e361f

    commit a64e361f0310e27a7afbf6dbd99ca88d8ac19e84
    Author: Jim Bosch 
    Date:   Fri Dec 19 15:00:08 2014 -0500
    
        Make it easier to control Peak schemas in Footprint
        
        For backwards compatibility, we're keeping around
        all the old Footprint constructors, which use the
        default Peak minimal schema.  But we now have a
        ctor that accepts a custom schema, and a Python
        accessible way to change the schema.
    

    61b6195c

    commit 61b6195c87e9320e84ffff47c38353a6d945d173
    Author: Robert Lupton the Good 
    Date:   Sat May 9 16:53:20 2015 -0400
    
        Overwrote master with files checked out from HSC-1246
    

    Commits in /Users/nate/repos_lsst/afw/

    c12d3b48

    commit c12d3b4824bcbb203135218e908325e47e99698f
    Author: Jim Bosch 
    Date:   Fri Dec 19 15:00:08 2014 -0500
    
        Make it easier to control Peak schemas in Footprint
        
        For backwards compatibility, we're keeping around
        all the old Footprint constructors, which use the
        default Peak minimal schema.  But we now have a
        ctor that accepts a custom schema, and a Python
        accessible way to change the schema.
        
        Conflicts:
            include/lsst/afw/detection/Footprint.h
            src/detection/Footprint.cc
    

    89e96d0e

    commit 89e96d0e1b2e80141039a3d51b153af8d5fc7f22
    Author: John Swinbank 
    Date:   Fri Nov 28 17:31:26 2014 -0600
    
        RLE-based Footprint erosion
    

    007ca4a2

    commit 007ca4a24b6bb73d9d63d427ae579cc433dc616a
    Author: Jim Bosch 
    Date:   Thu Nov 13 16:22:23 2014 -0500
    
        Replace Peak with PeakRecord
        
        By using afw::table objects to store Peaks, we allow additional
        information to be added to Peaks without requiring further changes
        to persistence.
        
        Conflicts:
            include/lsst/afw/detection/Footprint.h
            include/lsst/afw/detection/FootprintSet.h
            src/detection/Footprint.cc
            src/detection/FootprintSet.cc
            tests/footprint1.py
    

    c839d0f2

    commit c839d0f28287875df3e43b674f1da3f140a33250
    Author: Lauren MacArthur 
    Date:   Mon Mar 16 16:34:35 2015 -0400
    
        Update copyright and remove whitespace
    

    574e0785

    commit 574e0785d1ceee9e3f1560d221e139bdff15a703
    Author: Dustin Lang 
    Date:   Fri Mar 7 10:56:45 2014 -0500
    
        add afw::detection::mergeFootprints()
    

    0b2457bc

    commit 0b2457bc72484e8cfb78f471f6d6d7e7fc1f6437
    Author: Jim Bosch 
    Date:   Wed Apr 16 17:20:02 2014 -0400
    
        Add Footprint method to merge with neighbors
        
        Conflicts:
            tests/footprint1.py
    

    dddc9b36

    commit dddc9b36d166bc85774ff34c38c134fcf6206508
    Author: John Swinbank 
    Date:   Thu Nov 20 15:43:44 2014 -0600
    
        Use a class for the structuring element in Footprint grows.
        
        This replaces the previous definition, based on std::map, and makes it
        possible to have asymmetric structuring elements. We can therefore use the
        RLE-based technique to grow in any (or all) of the up/down/left/right
        directions.
    

    ae20e2b5

    commit ae20e2b580e6d2a9e785dc0d4f471b7ebed2fb45
    Author: John Swinbank 
    Date:   Fri Nov 28 17:10:45 2014 -0600
    
        Support shrinks with a Manhattan metric
    

    94770baf

    commit 94770bafec04976204f56cf3aed80fa02bece412
    Author: Dustin Lang 
    Date:   Mon Jun 23 17:17:08 2014 -0500
    
        Address various issues from Paul Price's in-depth review.
        
        Footprint.h:
            No documentation for new methods and functions.
        
        Footprint.cc:
            Move documentation to header file.
            Indentation is inconsistent. Should always be 4.
            Don't use this-> when there is no need for it, e.g., this->addSpan should be addSpan.
            Paren following LSST_EXCEPT *must* cuddle --- it certainly may not be on the next line.
            Breaks 110 column limit.
            PixelT zero = 0; should be PixelT const zero = 0; Add const also for ix0 and iy0 --- *anywhere* the value will never change, as it helps the compiler write faster code.
            You're iterating with the postfix operator (s++) instead of prefix (++s); this can adversely affect performance in C++.
            What does the comment Ugly! refer to?
            Names foota and footb don't follow naming rules, and are a bit hard to read. Suggest aFoot and bFoot. Similarly with pka, etc.
            const Footprint::PeakList& --> Footprint::PeakList const& (throughout).
            while (1) --> while (true)
            nearestFootprint isn't documented.
            Why do you call INSTANTIATE_FLOAT on integer types???  [I renamed it -- it instantiated functions that were appropriate for *numeric*, not necessarily floating-point, types!]
            remove gratuitous 'typename'
            prefer PTR(Foo) to Foo::Ptr and CONST_PTR(Foo) to Foo:ConstPtr.
        
        HeavyFootprint?.cc:
            Some lines exceed 110 columns.
            Commented out code should be removed
        
        footprint1.py:
            Instead of self.assertTrue(a > b) use self.assertGreater(a, b). This provides a more useful message when it fails.
            Why is the trailing F required on clipToNonzeroF? It should be able to tell from the type of the image.  [fixed]
        
        Also removed stray Footprint.mergeWith() function that got messed up during rebase
    

    de65f62a

    commit de65f62aca09357adaa7952610f62167077ede34
    Author: Lauren MacArthur 
    Date:   Mon Mar 16 14:12:56 2015 -0400
    
        Clarify comments describing include function and homogenize variable names
    

    9e8aab29

    commit 9e8aab2900686514febd0d74cdbdd79461e94ee9
    Author: John Swinbank 
    Date:   Mon Jan 26 14:52:17 2015 -0500
    
        Correct documentation to match code
    

    Return to list

    tests/footprintArray.cc

    Diff:

                    // -*- lsst-c++ -*-
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #define BOOST_TEST_DYN_LINK
                    #define BOOST_TEST_MODULE FootprintArray
                    
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/test/unit_test.hpp"
                    #pragma clang diagnostic pop
                    #include "boost/test/floating_point_comparison.hpp"
                    
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/detection.h"
                    #include "lsst/afw/detection/FootprintArray.cc"
                    
                    #include "ndarray/eigen.h"
                    
                    #include "Eigen/Core"
                    
                    namespace image = lsst::afw::image;
                    namespace detection = lsst::afw::detection;
                    namespace geom = lsst::afw::geom;
                    namespace nd = ndarray;
                    
                    void doRoundTrip(
                        detection::Footprint const & footprint,
                        nd::Array const & v,
                        geom::Box2I const & box
                    ) {
                        nd::Array i1 = detection::expandArray(footprint, v, box);
                        nd::Array v1 = detection::flattenArray(footprint, i1, box.getMin());
                        BOOST_CHECK( std::equal(v1.begin(), v1.end(), v.begin()) );
                    }
                    
                    BOOST_AUTO_TEST_CASE(conversion) {
                    
                        detection::Footprint footprint;
                        footprint.addSpan(4, 3, 9);
                        footprint.addSpan(5, 2, 8);
                        footprint.addSpan(7, 4, 5);
                        footprint.addSpan(7, 7, 9);
                        footprint.addSpan(8, 2, 7);
                        footprint.addSpan(9, 0, 5);
                    
                        int oldArea = footprint.getArea();
                    
                        footprint.normalize();
                    
                        BOOST_CHECK_EQUAL( oldArea, footprint.getArea() );
                    
                        nd::Array v = nd::allocate(footprint.getArea());
                        v.asEigen().setRandom();
                    
                        doRoundTrip(footprint, v, geom::Box2I(geom::Point2I(0, 0), geom::Extent2I(10, 10)));
                    
                        doRoundTrip(footprint, v, geom::Box2I(geom::Point2I(0, 2), geom::Extent2I(15, 12)));
                    
                        BOOST_CHECK_THROW( 
                            detection::expandArray(footprint, v, geom::Box2I(geom::Point2I(1, 0), geom::Extent2I(9, 10))),
    
    82 d8bc9758 - lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    82 21597d88 + lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ ); BOOST_CHECK_THROW( detection::expandArray(footprint, v, geom::Box2I(geom::Point2I(0, 5), geom::Extent2I(10, 5))),
    87 d8bc9758 - lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    87 21597d88 + lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ ); BOOST_CHECK_THROW( detection::expandArray(footprint, v, geom::Box2I(geom::Point2I(0, 0), geom::Extent2I(9, 10))),
    92 d8bc9758 - lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    92 21597d88 + lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ ); BOOST_CHECK_THROW( detection::expandArray(footprint, v, geom::Box2I(geom::Point2I(0, 0), geom::Extent2I(10, 9))),
    97 d8bc9758 - lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    97 21597d88 + lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ ); footprint.shift(20, 30); doRoundTrip(footprint, v, geom::Box2I(geom::Point2I(10, 15), geom::Extent2I(50, 60))); doRoundTrip(footprint, v, geom::Box2I(geom::Point2I(20, 30), geom::Extent2I(10, 10))); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d8bc9758

    commit d8bc9758c23bd29f99dba1f69ccf82055f852829
    Author: jbosch 
    Date:   Fri Mar 11 01:43:16 2011 +0000
    
        afw #1556 - added tests and fixes for FootprintArray (including an incorrect-area bug in Footprint itself), tweaked LocalPsf API
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/math/spatialCell.i

    Diff:

                    // -*- lsst-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    //
                    // A couple of macros (%IMAGE and %MASKEDIMAGE) to provide MaskedImage's default arguments,
                    // We'll use these to define meta-macros (e.g. %SpatialCellImageCandidatePtr)
                    //
                    %define %IMAGE(PIXTYPE)
                    lsst::afw::image::Image
                    %enddef
                    
                    %define %MASKEDIMAGE(PIXTYPE)
                    lsst::afw::image::MaskedImage
                    %enddef
                    
                    //
                    // Must go BEFORE the include
                    //
                    %define %SpatialCellImageCandidatePtrs(TYPE, ...)
                        %shared_ptr(lsst::afw::math::SpatialCellImageCandidate);
                        %shared_ptr(lsst::afw::math::SpatialCellMaskedImageCandidate);
                    %enddef
                    //
                    // Must go AFTER the include
                    //
                    %define %SpatialCellImageCandidates(NAME, TYPE)
                        %template(SpatialCellImageCandidate##NAME) lsst::afw::math::SpatialCellImageCandidate;
                        %template(SpatialCellMaskedImageCandidate##NAME) lsst::afw::math::SpatialCellMaskedImageCandidate;
                    
                        //--------------------------------------------------------
                        // THESE CASTS NOW DEPRECATED IN FAVOR OF %castShared
                        %inline %{
                            boost::shared_ptr >
                            cast_SpatialCellImageCandidate##NAME(boost::shared_ptr candidate) {
                                return boost::dynamic_pointer_cast >(candidate);
                            }
                    
                            boost::shared_ptr >
                            cast_SpatialCellMaskedImageCandidate##NAME(boost::shared_ptr candidate) {
                                 return boost::dynamic_pointer_cast >(candidate);
                            }
                        %}
                        //--------------------------------------------------------
                    
                        %castShared(lsst::afw::math::SpatialCellImageCandidate, lsst::afw::math::SpatialCellCandidate)
                        %castShared(lsst::afw::math::SpatialCellMaskedImageCandidate, lsst::afw::math::SpatialCellCandidate)
                    
                    %enddef
                    
                    //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                    //
                    // OK, now we'll generate some code
                    //
                    
                    %{
                    #include "boost/shared_ptr.hpp"
                    #include "lsst/afw/math/SpatialCell.h"
                    %}
                    
                    %shared_ptr(lsst::afw::math::CandidateVisitor)
                    %shared_ptr(lsst::afw::math::SpatialCellCandidate);
                    %shared_ptr(lsst::afw::math::SpatialCell);
                    
                    %SpatialCellImageCandidatePtrs(float);
                    %SpatialCellImageCandidatePtrs(double);
                    
                    %rename(__incr__) lsst::afw::math::SpatialCellCandidateIterator::operator++;
                    %rename(__deref__) lsst::afw::math::SpatialCellCandidateIterator::operator*;
                    %rename(__eq__) lsst::afw::math::SpatialCellCandidateIterator::operator==;
                    %rename(__ne__) lsst::afw::math::SpatialCellCandidateIterator::operator!=;
                    
                    %include "lsst/afw/math/SpatialCell.h"
                    
                    %template(SpatialCellCandidateList) std::vector >;
                    %template(SpatialCellList) std::vector >;
                    
                    %SpatialCellImageCandidates(F, float);
                    %SpatialCellImageCandidates(D, double);
                    
                    
                    %extend lsst::afw::math::SpatialCell {
    
    103 4194637c - %pythoncode {
    103 81c3bd10 + %pythoncode %{
    ? + def __getitem__(self, ind): return [c for c in self.begin()][ind] def __iter__(self): return self.begin().__iter__()
    109 4194637c - }
    109 81c3bd10 + %}
    ? + } %extend lsst::afw::math::SpatialCellCandidateIterator {
    113 4194637c - %pythoncode {
    113 81c3bd10 + %pythoncode %{
    ? + def __iter__(self): while True: try: yield self.__deref__() except: raise StopIteration self.__incr__()
    122 4194637c - }
    122 81c3bd10 + %}
    ? + }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4194637c

    commit 4194637c5379bf25666c138cc8683860295f51ae
    Author: rhl 
    Date:   Thu Mar 5 22:05:02 2009 +0000
    
        Rework SpatialCell to present an iterator-based view of lists of candidates
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    tests/convolve.py

    Diff:

    1 6812a8c3 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """Test lsst.afwMath.convolve Tests convolution of various kernels with Images and MaskedImages. """ import math import os import os.path import unittest import string import numpy
    37 456d42a8 - import eups
    38 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests import lsst.pex.logging as pexLog import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.math.detail as mathDetail import lsst.afw.image.testUtils as imTestUtils from kernel import makeDeltaFunctionKernelList, makeGaussianKernelList VERBOSITY = 0 # increase to see trace; 3 will show the convolutions specializations being used pexLog.Debug("lsst.afw", VERBOSITY) try: display except NameError: display = False import lsst.afw.display.ds9 as ds9 import lsst.afw.display.utils as displayUtils
    59 76505c6a - dataDir = os.path.join(eups.productDir("afwdata"), "data")
    ? ^ ^ ^^^^^ ^
    60 7cbb2bb9 + dataDir = os.path.join(lsst.utils.getPackageDir("afwdata"), "data")
    ? ^^^^^ ^^^ ^^^^^ ^^^^
    60 61855404 - if not dataDir:
    61 456d42a8 - raise RuntimeError("Must set up afwdata to run these tests")
    # input image contains a saturated star, a bad column, and a faint star InputMaskedImagePath = os.path.join(dataDir, "medexp.fits") InputBBox = afwGeom.Box2I(afwGeom.Point2I(52, 574), afwGeom.Extent2I(76, 80)) # the shifted BBox is for a same-sized region containing different pixels; # this is used to initialize the convolved image, to make sure convolve fully overwrites it ShiftedBBox = afwGeom.Box2I(afwGeom.Point2I(0, 460), afwGeom.Extent2I(76, 80)) FullMaskedImage = afwImage.MaskedImageF(InputMaskedImagePath) EdgeMaskPixel = 1 << afwImage.MaskU.getMaskPlane("EDGE")
    72 7ae55f93 - NoDataMaskPixel = afwImage.MaskU.getPlaneBitMask("NO_DATA")
    # Ignore kernel pixels whose value is exactly 0 when smearing the mask plane? # Set this to match the afw code IgnoreKernelZeroPixels = True NullTranslator = string.maketrans("", "") GarbageChars = string.punctuation + string.whitespace #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def refConvolve(imMaskVar, xy0, kernel, doNormalize, doCopyEdge): """Reference code to convolve a kernel with a masked image. Warning: slow (especially for spatially varying kernels). Inputs: - imMaskVar: (image, mask, variance) numpy arrays - xy0: xy offset of imMaskVar relative to parent image - kernel: lsst::afw::Core.Kernel object - doNormalize: normalize the kernel - doCopyEdge: if True: copy edge pixels from input image to convolved image; if False: set edge pixels to the standard edge pixel (image=nan, var=inf, mask=EDGE) """ # Note: the original version of this function was written when numpy/image conversions were the # transpose of what they are today. Rather than transpose the logic in this function or put # transposes throughout the rest of the file, I have transposed only the inputs and outputs. # - Jim Bosch, 3/4/2011 image, mask, variance = (imMaskVar[0].transpose(), imMaskVar[1].transpose(), imMaskVar[2].transpose()) if doCopyEdge: # copy input arrays to output arrays and set EDGE bit of mask; non-edge pixels are overwritten below retImage = image.copy() retMask = mask.copy() retMask += EdgeMaskPixel retVariance = variance.copy() else: # initialize output arrays to all edge pixels; non-edge pixels will be overwritten below retImage = numpy.zeros(image.shape, dtype=image.dtype) retImage[:, :] = numpy.nan retMask = numpy.zeros(mask.shape, dtype=mask.dtype)
    113 7ae55f93 - retMask[:, :] = NoDataMaskPixel
    ? ^^^^^^
    111 a7aa0c91 + retMask[:, :] = EdgeMaskPixel
    ? ^^^^ retVariance = numpy.zeros(variance.shape, dtype=image.dtype) retVariance[:, :] = numpy.inf kWidth = kernel.getWidth() kHeight = kernel.getHeight() numCols = image.shape[0] + 1 - kWidth numRows = image.shape[1] + 1 - kHeight if numCols < 0 or numRows < 0: raise RuntimeError("image must be larger than kernel in both dimensions") colRange = range(numCols) kImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) isSpatiallyVarying = kernel.isSpatiallyVarying() if not isSpatiallyVarying: kernel.computeImage(kImage, doNormalize) kImArr = kImage.getArray().transpose() retRow = kernel.getCtrY() for inRowBeg in range(numRows): inRowEnd = inRowBeg + kHeight retCol = kernel.getCtrX() if isSpatiallyVarying: rowPos = afwImage.indexToPosition(retRow) + xy0[1] for inColBeg in colRange: if isSpatiallyVarying: colPos = afwImage.indexToPosition(retCol) + xy0[0] kernel.computeImage(kImage, doNormalize, colPos, rowPos) kImArr = kImage.getArray().transpose() inColEnd = inColBeg + kWidth subImage = image[inColBeg:inColEnd, inRowBeg:inRowEnd] subVariance = variance[inColBeg:inColEnd, inRowBeg:inRowEnd] subMask = mask[inColBeg:inColEnd, inRowBeg:inRowEnd] retImage[retCol, retRow] = numpy.add.reduce((kImArr * subImage).flat) retVariance[retCol, retRow] = numpy.add.reduce((kImArr * kImArr * subVariance).flat) if IgnoreKernelZeroPixels: retMask[retCol, retRow] = numpy.bitwise_or.reduce((subMask * (kImArr != 0)).flat) else: retMask[retCol, retRow] = numpy.bitwise_or.reduce(subMask.flat) retCol += 1 retRow += 1 return (retImage.transpose(), retMask.transpose(), retVariance.transpose()) def sameMaskPlaneDicts(maskedImageA, maskedImageB): """Return True if the mask plane dicts are the same, False otherwise. Handles the fact that one cannot directly compare maskPlaneDicts using == """ mpDictA = maskedImageA.getMask().getMaskPlaneDict() mpDictB = maskedImageB.getMask().getMaskPlaneDict() if mpDictA.keys() != mpDictB.keys(): print "mpDictA.keys() ", mpDictA.keys() print "mpDictB.keys() ", mpDictB.keys() return False if mpDictA.values() != mpDictB.values(): print "mpDictA.values()", mpDictA.values() print "mpDictB.values()", mpDictB.values() return False return True class ConvolveTestCase(unittest.TestCase): def setUp(self):
    176 f8edfe90 + tmp = afwImage.MaskU() # clearMaskPlaneDict isn't static
    177 f8edfe90 + tmp.clearMaskPlaneDict() # reset so tests will be deterministic
    178 f8edfe90 +
    179 f8edfe90 + for p in ("BAD", "SAT", "INTRP", "CR", "EDGE"):
    180 f8edfe90 + afwImage.MaskU_addMaskPlane(p)
    181 f8edfe90 +
    182 f8edfe90 + del tmp
    183 92d6c05e +
    self.maskedImage = afwImage.MaskedImageF(FullMaskedImage, InputBBox, afwImage.LOCAL, True) # use a huge XY0 to make emphasize any errors related to not handling xy0 correctly. self.maskedImage.setXY0(300, 200) self.xy0 = self.maskedImage.getXY0() # provide destinations for the convolved MaskedImage and Image that contain junk # to verify that convolve overwrites all pixels; # make them deep copies so we can mess with them without affecting self.inImage self.cnvMaskedImage = afwImage.MaskedImageF(FullMaskedImage, ShiftedBBox, afwImage.LOCAL, True) self.cnvImage = afwImage.ImageF(FullMaskedImage.getImage(), ShiftedBBox, afwImage.LOCAL, True) self.width = self.maskedImage.getWidth() self.height = self.maskedImage.getHeight() # smask = afwImage.MaskU(self.maskedImage.getMask(), afwGeom.Box2I(afwGeom.Point2I(15, 17), afwGeom.Extent2I(10, 5))) # smask.set(0x8) def tearDown(self): del self.maskedImage del self.cnvMaskedImage del self.cnvImage def runBasicTest(self, kernel, convControl, refKernel=None, kernelDescr="", rtol=1.0e-05, atol=1e-08): """Assert that afwMath::convolve gives the same result as reference convolution for a given kernel. Inputs: - kernel: convolution kernel - convControl: convolution control parameters (afwMath.ConvolutionControl) - refKernel: kernel to use for refConvolve (if None then kernel is used) - kernelDescr: description of kernel - rtol: relative tolerance (see below) - atol: absolute tolerance (see below) rtol and atol are positive, typically very small numbers. The relative difference (rtol * abs(b)) and the absolute difference "atol" are added together to compare against the absolute difference between "a" and "b". """ if refKernel == None: refKernel = kernel # strip garbage characters (whitespace and punctuation) to make a short description for saving files shortKernelDescr = kernelDescr.translate(NullTranslator, GarbageChars) doNormalize = convControl.getDoNormalize() doCopyEdge = convControl.getDoCopyEdge() maxInterpDist = convControl.getMaxInterpolationDistance() imMaskVar = self.maskedImage.getArrays() xy0 = self.maskedImage.getXY0() refCnvImMaskVarArr = refConvolve(imMaskVar, xy0, refKernel, doNormalize, doCopyEdge) afwMath.convolve(self.cnvImage, self.maskedImage.getImage(), kernel, convControl) self.assertEqual(self.cnvImage.getXY0(), self.xy0) cnvImArr = self.cnvImage.getArray() afwMath.convolve(self.cnvMaskedImage, self.maskedImage, kernel, convControl) cnvImMaskVarArr = self.cnvMaskedImage.getArrays() if display and False: refMaskedImage = afwImage.makeMaskedImageFromArrays(*refCnvImMaskVarArr) ds9.mtv(displayUtils.Mosaic().makeMosaic([ self.maskedImage, refMaskedImage, self.cnvMaskedImage]), frame=0) if False: for (x, y) in ((0, 0), (1, 0), (0, 1), (50, 50)): print "Mask(%d,%d) 0x%x 0x%x" % (x, y, refMaskedImage.getMask().get(x, y), self.cnvMaskedImage.getMask().get(x, y)) errStr = imTestUtils.imagesDiffer(cnvImArr, refCnvImMaskVarArr[0], rtol=rtol, atol=atol) if errStr: self.cnvImage.writeFits("act%s.fits" % (shortKernelDescr,)) refMaskedImage = afwImage.makeMaskedImageFromArrays(*refCnvImMaskVarArr) refMaskedImage.getImage().writeFits("des%s.fits" % (shortKernelDescr,)) self.fail("convolve(Image, kernel=%s, doNormalize=%s, doCopyEdge=%s, maxInterpDist=%s) failed:\n%s" % \ (kernelDescr, doNormalize, doCopyEdge, maxInterpDist, errStr)) errStr = imTestUtils.maskedImagesDiffer(cnvImMaskVarArr, refCnvImMaskVarArr, doVariance = True, rtol=rtol, atol=atol) if errStr: self.cnvMaskedImage.writeFits("act%s" % (shortKernelDescr,)) refMaskedImage = afwImage.makeMaskedImageFromArrays(*refCnvImMaskVarArr) refMaskedImage.writeFits("des%s" % (shortKernelDescr,)) self.fail("convolve(MaskedImage, kernel=%s, doNormalize=%s, doCopyEdge=%s, maxInterpDist=%s) failed:\n%s" % \ (kernelDescr, doNormalize, doCopyEdge, maxInterpDist, errStr)) if not sameMaskPlaneDicts(self.cnvMaskedImage, self.maskedImage): self.cnvMaskedImage.writeFits("act%s" % (shortKernelDescr,)) refMaskedImage = afwImage.makeMaskedImageFromArrays(*refCnvImMaskVarArr) refMaskedImage.writeFits("des%s" % (shortKernelDescr,)) self.fail("convolve(MaskedImage, kernel=%s, doNormalize=%s, doCopyEdge=%s, maxInterpDist=%s) failed:\n%s" % \ (kernelDescr, doNormalize, doCopyEdge, maxInterpDist, "convolved mask dictionary does not match input")) def runStdTest(self, kernel, refKernel=None, kernelDescr="", rtol=1.0e-05, atol=1e-08, maxInterpDist=10): """Assert that afwMath::convolve gives the same result as reference convolution for a given kernel. Inputs: - kernel: convolution kernel - refKernel: kernel to use for refConvolve (if None then kernel is used) - kernelDescr: description of kernel - rtol: relative tolerance (see below) - atol: absolute tolerance (see below) - maxInterpDist: maximum allowed distance for linear interpolation during convolution rtol and atol are positive, typically very small numbers. The relative difference (rtol * abs(b)) and the absolute difference "atol" are added together to compare against the absolute difference between "a" and "b". """ if VERBOSITY > 0: print "Test convolution with", kernelDescr convControl = afwMath.ConvolutionControl() convControl.setMaxInterpolationDistance(maxInterpDist) # verify dimension assertions: # - output image dimensions = input image dimensions # - input image width and height >= kernel width and height # Note: the assertion kernel size > 0 is tested elsewhere for inWidth in (kernel.getWidth() - 1, self.width-1, self.width, self.width + 1): for inHeight in (kernel.getHeight() - 1, self.width-1, self.width, self.width + 1): if (inWidth == self.width) and (inHeight == self.height): continue inMaskedImage = afwImage.MaskedImageF(afwGeom.Extent2I(inWidth, inHeight)) self.assertRaises(Exception, afwMath.convolve, self.cnvMaskedImage, inMaskedImage, kernel) for doNormalize in (True,): # (False, True): convControl.setDoNormalize(doNormalize) for doCopyEdge in (False,): # (False, True): convControl.setDoCopyEdge(doCopyEdge) self.runBasicTest(kernel, convControl=convControl, refKernel=refKernel, kernelDescr=kernelDescr, rtol=rtol, atol=atol) # verify that basicConvolve does not write to edge pixels self.runBasicConvolveEdgeTest(kernel, kernelDescr) def runBasicConvolveEdgeTest(self, kernel, kernelDescr): """Verify that basicConvolve does not write to edge pixels for this kind of kernel """ fullBox = afwGeom.Box2I( afwGeom.Point2I(0, 0), ShiftedBBox.getDimensions(), ) goodBox = kernel.shrinkBBox(fullBox) cnvMaskedImage = afwImage.MaskedImageF(FullMaskedImage, ShiftedBBox, afwImage.LOCAL, True) cnvMaskedImageCopy = afwImage.MaskedImageF(cnvMaskedImage, fullBox, afwImage.LOCAL, True) cnvMaskedImageCopyViewOfGoodRegion = afwImage.MaskedImageF(cnvMaskedImageCopy, goodBox, afwImage.LOCAL, False) # convolve with basicConvolve, which should leave the edge pixels alone convControl = afwMath.ConvolutionControl() mathDetail.basicConvolve(cnvMaskedImage, self.maskedImage, kernel, convControl) # reset the good region to the original convolved image; # this should reset the entire convolved image to its original self cnvMaskedImageGoodView = afwImage.MaskedImageF(cnvMaskedImage, goodBox, afwImage.LOCAL, False) cnvMaskedImageGoodView <<= cnvMaskedImageCopyViewOfGoodRegion # assert that these two are equal cnvImMaskVarArr = cnvMaskedImage.getArrays() desCnvImMaskVarArr = cnvMaskedImageCopy.getArrays() errStr = imTestUtils.maskedImagesDiffer(cnvImMaskVarArr, desCnvImMaskVarArr, doVariance = True, rtol=0, atol=0) shortKernelDescr = kernelDescr.translate(NullTranslator, GarbageChars) if errStr: cnvMaskedImage.writeFits("actBasicConvolve%s" % (shortKernelDescr,)) cnvMaskedImageCopy.writeFits("desBasicConvolve%s" % (shortKernelDescr,)) self.fail("basicConvolve(MaskedImage, kernel=%s) wrote to edge pixels:\n%s" % \ (kernelDescr, errStr)) def testConvolutionControl(self): """Test the ConvolutionControl object """ convControl = afwMath.ConvolutionControl() self.assert_(convControl.getDoNormalize()) for doNormalize in (False, True): convControl.setDoNormalize(doNormalize) self.assertEqual(convControl.getDoNormalize(), doNormalize) self.assert_(not convControl.getDoCopyEdge()) for doCopyEdge in (False, True): convControl.setDoCopyEdge(doCopyEdge) self.assert_(convControl.getDoCopyEdge() == doCopyEdge) self.assertEqual(convControl.getMaxInterpolationDistance(), 10) for maxInterpDist in (0, 1, 2, 10, 100): convControl.setMaxInterpolationDistance(maxInterpDist) self.assertEqual(convControl.getMaxInterpolationDistance(), maxInterpDist) def testUnityConvolution(self): """Verify that convolution with a centered delta function reproduces the original. """ # create a delta function kernel that has 1,1 in the center kFunc = afwMath.IntegerDeltaFunction2D(0.0, 0.0) kernel = afwMath.AnalyticKernel(3, 3, kFunc) doNormalize = False doCopyEdge = False afwMath.convolve(self.cnvImage, self.maskedImage.getImage(), kernel, doNormalize, doCopyEdge) cnvImArr = self.cnvImage.getArray() afwMath.convolve(self.cnvMaskedImage, self.maskedImage, kernel, doNormalize, doCopyEdge) cnvImMaskVarArr = self.cnvMaskedImage.getArrays() refCnvImMaskVarArr = self.maskedImage.getArrays() skipMaskArr = numpy.isnan(cnvImMaskVarArr[0]) kernelDescr = "Centered DeltaFunctionKernel (testing unity convolution)" errStr = imTestUtils.imagesDiffer(cnvImArr, refCnvImMaskVarArr[0], skipMaskArr=skipMaskArr) if errStr: self.fail("convolve(Image, kernel=%s, doNormalize=%s, doCopyEdge=%s) failed:\n%s" % \ (kernelDescr, doNormalize, doCopyEdge, errStr)) errStr = imTestUtils.maskedImagesDiffer(cnvImMaskVarArr, refCnvImMaskVarArr, skipMaskArr=skipMaskArr) if errStr: self.fail("convolve(MaskedImage, kernel=%s, doNormalize=%s, doCopyEdge=%s) failed:\n%s" % \ (kernelDescr, doNormalize, doCopyEdge, errStr)) self.assert_(sameMaskPlaneDicts(self.cnvMaskedImage, self.maskedImage), "convolve(MaskedImage, kernel=%s, doNormalize=%s, doCopyEdge=%s) failed:\n%s" % \ (kernelDescr, doNormalize, doCopyEdge, "convolved mask dictionary does not match input")) def testFixedKernelConvolve(self): """Test convolve with a fixed kernel """ kWidth = 6 kHeight = 7 kFunc = afwMath.GaussianFunction2D(2.5, 1.5, 0.5) analyticKernel = afwMath.AnalyticKernel(kWidth, kHeight, kFunc) kernelImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) analyticKernel.computeImage(kernelImage, False) fixedKernel = afwMath.FixedKernel(kernelImage) self.runStdTest(fixedKernel, kernelDescr="Gaussian FixedKernel") def testSeparableConvolve(self): """Test convolve of a separable kernel with a spatially invariant Gaussian function """ kWidth = 7 kHeight = 6 gaussFunc1 = afwMath.GaussianFunction1D(1.0) gaussFunc2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) separableKernel = afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1) analyticKernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc2) self.runStdTest( separableKernel, refKernel = analyticKernel, kernelDescr = "Gaussian Separable Kernel (compared to AnalyticKernel equivalent)") def testSpatiallyInvariantConvolve(self): """Test convolution with a spatially invariant Gaussian function """ kWidth = 6 kHeight = 7 kFunc = afwMath.GaussianFunction2D(2.5, 1.5, 0.5) kernel = afwMath.AnalyticKernel(kWidth, kHeight, kFunc) self.runStdTest(kernel, kernelDescr="Gaussian Analytic Kernel") def testSpatiallyVaryingAnalyticConvolve(self): """Test in-place convolution with a spatially varying AnalyticKernel """ kWidth = 7 kHeight = 6 # create spatial model sFunc = afwMath.PolynomialFunction2D(1) minSigma = 1.5 maxSigma = 1.501 # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (minSigma, (maxSigma - minSigma) / self.width, 0.0), (minSigma, 0.0, (maxSigma - minSigma) / self.height), (0.0, 0.0, 0.0), ) kFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, kFunc, sFunc) kernel.setSpatialParameters(sParams) for maxInterpDist, rtol, methodStr in ( (0, 1.0e-5, "brute force"), (10, 1.0e-5, "interpolation over 10 x 10 pixels"), ): self.runStdTest( kernel, kernelDescr = "Spatially Varying Gaussian Analytic Kernel using %s" % (methodStr,), maxInterpDist = maxInterpDist, rtol = rtol) def testSpatiallyVaryingSeparableConvolve(self): """Test convolution with a spatially varying SeparableKernel """ kWidth = 7 kHeight = 6 # create spatial model sFunc = afwMath.PolynomialFunction2D(1) minSigma = 0.1 maxSigma = 3.0 # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (minSigma, (maxSigma - minSigma) / self.width, 0.0), (minSigma, 0.0, (maxSigma - minSigma) / self.height), (0.0, 0.0, 0.0), ) gaussFunc1 = afwMath.GaussianFunction1D(1.0) gaussFunc2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) separableKernel = afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1, sFunc) analyticKernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc2, sFunc) separableKernel.setSpatialParameters(sParams[0:2]) analyticKernel.setSpatialParameters(sParams) self.runStdTest(separableKernel, refKernel=analyticKernel, kernelDescr="Spatially Varying Gaussian Separable Kernel") def testDeltaConvolve(self): """Test convolution with various delta function kernels using optimized code """ for kWidth in range(1, 4): for kHeight in range(1, 4): for activeCol in range(kWidth): for activeRow in range(kHeight): kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, afwGeom.Point2I(activeCol, activeRow)) if display and False: kim = afwImage.ImageD(kWidth, kHeight); kernel.computeImage(kim, False) ds9.mtv(kim, frame=1) self.runStdTest(kernel, kernelDescr="Delta Function Kernel") def testSpatiallyVaryingGaussianLinerCombination(self): """Test convolution with a spatially varying LinearCombinationKernel of two Gaussian basis kernels. """ kWidth = 5 kHeight = 5 # create spatial model for nBasisKernels in (3, 4): # at 3 the kernel will not be refactored, at 4 it will be sFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (1.0, -0.01/self.width, -0.01/self.height), (0.0, 0.01/self.width, 0.0/self.height), (0.0, 0.0/self.width, 0.01/self.height), (0.5, 0.005/self.width, -0.005/self.height), )[:nBasisKernels] gaussParamsList = ( (1.5, 1.5, 0.0), (2.5, 1.5, 0.0), (2.5, 1.5, math.pi / 2.0), (2.5, 2.5, 0.0), )[:nBasisKernels] basisKernelList = makeGaussianKernelList(kWidth, kHeight, gaussParamsList) kernel = afwMath.LinearCombinationKernel(basisKernelList, sFunc) kernel.setSpatialParameters(sParams) for maxInterpDist, rtol, methodStr in ( (0, 1.0e-5, "brute force"), (10, 1.0e-5, "interpolation over 10 x 10 pixels"), ): self.runStdTest( kernel, kernelDescr = "%s with %d basis kernels convolved using %s" % \ ("Spatially Varying Gaussian Analytic Kernel", nBasisKernels, methodStr), maxInterpDist = maxInterpDist, rtol = rtol) def testSpatiallyVaryingDeltaFunctionLinearCombination(self): """Test convolution with a spatially varying LinearCombinationKernel of delta function basis kernels. """ kWidth = 2 kHeight = 2 # create spatially model sFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (1.0, -0.5/self.width, -0.5/self.height), (0.0, 1.0/self.width, 0.0/self.height), (0.0, 0.0/self.width, 1.0/self.height), (0.5, 0.0, 0.0), ) basisKernelList = makeDeltaFunctionKernelList(kWidth, kHeight) kernel = afwMath.LinearCombinationKernel(basisKernelList, sFunc) kernel.setSpatialParameters(sParams) for maxInterpDist, rtol, methodStr in ( (0, 1.0e-5, "brute force"), (10, 1.0e-3, "interpolation over 10 x 10 pixels"), ): self.runStdTest( kernel, kernelDescr = "Spatially varying LinearCombinationKernel of delta function kernels using %s" %\ (methodStr,), maxInterpDist = maxInterpDist, rtol = rtol) def testZeroWidthKernel(self): """Convolution by a 0x0 kernel should raise an exception. The only way to produce a 0x0 kernel is to use the default constructor (which exists only to support persistence; it does not produce a useful kernel). """ kernelList = [ afwMath.FixedKernel(), afwMath.AnalyticKernel(), afwMath.SeparableKernel(), # afwMath.DeltaFunctionKernel(), # DeltaFunctionKernel has no default constructor afwMath.LinearCombinationKernel(), ] convolutionControl = afwMath.ConvolutionControl() for kernel in kernelList: self.assertRaises(Exception, afwMath.convolve, self.cnvMaskedImage, self.maskedImage, kernel, convolutionControl) def testTicket873(self): """Demonstrate ticket 873: convolution of a MaskedImage with a spatially varying LinearCombinationKernel of basis kernels with low covariance gives incorrect variance. """ # create spatial model sFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (1.0, -0.5/self.width, -0.5/self.height), (0.0, 1.0/self.width, 0.0/self.height), (0.0, 0.0/self.width, 1.0/self.height), ) # create three kernels with some non-overlapping pixels # (non-zero pixels in one kernel vs. zero pixels in other kernels); # note: the extreme example of this is delta function kernels, but this is less extreme basisKernelList = afwMath.KernelList() kImArr = numpy.zeros([5, 5], dtype=float) kImArr[1:4, 1:4] = 0.5 kImArr[2, 2] = 1.0 kImage = afwImage.makeImageFromArray(kImArr) basisKernelList.append(afwMath.FixedKernel(kImage)) kImArr[:, :] = 0.0 kImArr[0:2, 0:2] = 0.125 kImArr[3:5, 3:5] = 0.125 kImage = afwImage.makeImageFromArray(kImArr) basisKernelList.append(afwMath.FixedKernel(kImage)) kImArr[:, :] = 0.0 kImArr[0:2, 3:5] = 0.125 kImArr[3:5, 0:2] = 0.125 kImage = afwImage.makeImageFromArray(kImArr) basisKernelList.append(afwMath.FixedKernel(kImage)) kernel = afwMath.LinearCombinationKernel(basisKernelList, sFunc) kernel.setSpatialParameters(sParams) for maxInterpDist, rtol, methodStr in ( (0, 1.0e-5, "brute force"), (10, 3.0e-3, "interpolation over 10 x 10 pixels"), ): self.runStdTest( kernel, kernelDescr = \ "Spatially varying LinearCombinationKernel of basis kernels with low covariance, using %s" % (methodStr,), maxInterpDist = maxInterpDist, rtol = rtol) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ConvolveTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(doExit=False): """Run the tests""" utilsTests.run(suite(), doExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    456d42a8

    commit 456d42a80026bc8b0961131936d467cf68af2f68
    Author: rowen 
    Date:   Fri Mar 28 17:10:01 2008 +0000
    
        afw reorg:
        - Updated use of fwData -> afwdata
        - Fixed forward declarations of Formatter in image classes
    

    76505c6a

    commit 76505c6a9851eb22e1080810712fbd4b07f2ef02
    Author: Paul Price 
    Date:   Fri Nov 18 17:15:21 2011 -0500
    
        Updating image directory.
    

    61855404

    commit 618554041c03d30fe370e2c3e69c0fb394c93ccb
    Author: nms 
    Date:   Tue Oct 9 00:00:09 2007 +0000
    
        Merged Exposure class code (.cc/.h and exposure.i) to trunk (from Ticket 167).
        Merged modifications made in Ticket 167 to MaskedImage, Kernel, and WCS class code.
        Added and merged final modifications to Exposure, WCS and Kernel class test code
          (associated examples/*.cc & tests/*.py files)
        Deleted all test images from tests/data.
        Added small_MI_corrupt_img.fits to tests/data for temporary storage of a test file used
        in both the WCS and Exposure test suites.
    

    6812a8c3

    commit 6812a8c38838bc49a782941c0996303358cda763
    Author: rowen 
    Date:   Thu Mar 12 00:35:16 2009 +0000
    
        Added unit tests for spatially invariant separable convolution.
        Fix the #! line in ConvolveMaskedImage_1.py
    

    7ae55f93

    commit 7ae55f9399a2076e9fd54bf8ee7c8b2048b8322e
    Author: Paul Price 
    Date:   Thu May 22 14:46:02 2014 -0400
    
        tests: not necessary to re-seed mask planes
        
        Re-seeding the mask planes with the wrong order or number than they are
        originally set in Mask.cc results in the wrong values when convolving.
    

    Commits in /Users/nate/repos_lsst/afw/

    92d6c05e

    commit 92d6c05e41b90a68f651e265defc6b4782f5f7e7
    Author: rowen 
    Date:   Thu Jun 24 23:42:09 2010 +0000
    
        tests/convolve.py now tests that convolve sets xy0.
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/geom/XYTransform.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    #include "lsst/afw/geom/XYTransform.h"
                    #include "boost/make_shared.hpp"
                    
    
    28 dd97c30a - namespace pexEx = lsst::pex::exceptions;
    29 e1996ce6 -
    namespace lsst { namespace afw { namespace geom {
    32 0a8d9c69 + XYTransform::XYTransform()
    33 0a8d9c69 + : daf::base::Citizen(typeid(this))
    34 e1996ce6 -
    35 d1f72a42 - // -------------------------------------------------------------------------------------------------
    36 d1f72a42 - //
    37 d1f72a42 - // XYTransform
    38 d1f72a42 -
    39 d1f72a42 -
    40 a6e8955c - XYTransform::XYTransform(bool inFpCoordinateSystem)
    41 a6e8955c - : daf::base::Citizen(typeid(this)), _inFpCoordinateSystem(inFpCoordinateSystem)
    { } /// default implementation; subclass may override AffineTransform XYTransform::linearizeForwardTransform(Point2D const &p) const { Point2D px = p + Extent2D(1,0); Point2D py = p + Extent2D(0,1); return makeAffineTransformFromTriple(p, px, py, this->forwardTransform(p), this->forwardTransform(px), this->forwardTransform(py)); } /// default implementation; subclass may override AffineTransform XYTransform::linearizeReverseTransform(Point2D const &p) const { Point2D px = p + Extent2D(1,0); Point2D py = p + Extent2D(0,1); return makeAffineTransformFromTriple(p, px, py, this->reverseTransform(p), this->reverseTransform(px), this->reverseTransform(py)); } /// default implementation; subclass may override PTR(XYTransform) XYTransform::invert() const { return boost::make_shared (this->clone()); }
    77 d95640da - ellipses::Quadrupole XYTransform::forwardTransform(Point2D const &pixel, Quadrupole const &q) const
    78 f521567c - {
    79 1e136e29 - // Note: q.transform(L) returns (LQL^T)
    80 f521567c - AffineTransform a = linearizeForwardTransform(pixel);
    81 f521567c - return q.transform(a.getLinear());
    82 f521567c - }
    83 f521567c -
    84 d95640da - ellipses::Quadrupole XYTransform::reverseTransform(Point2D const &pixel, Quadrupole const &q) const
    85 f521567c - {
    86 f521567c - AffineTransform a = linearizeReverseTransform(pixel);
    87 f521567c - return q.transform(a.getLinear());
    88 f521567c - }
    89 f521567c -
    90 f521567c -
    91 48ac4e21 -
    92 e1996ce6 - // -------------------------------------------------------------------------------------------------
    93 48ac4e21 - //
    94 e701b280 - // IdentityXYTransform
    95 e701b280 -
    96 e701b280 -
    97 a6e8955c - IdentityXYTransform::IdentityXYTransform(bool inFpCoordinateSystem)
    98 a6e8955c - : XYTransform(inFpCoordinateSystem)
    99 0a5ba669 - { }
    100 0a5ba669 -
    101 e701b280 - PTR(XYTransform) IdentityXYTransform::clone() const
    102 e701b280 - {
    103 a6e8955c - return boost::make_shared (_inFpCoordinateSystem);
    104 e701b280 - }
    105 e701b280 -
    106 d95640da - Point2D IdentityXYTransform::forwardTransform(Point2D const &pixel) const
    107 e701b280 - {
    108 e701b280 - return pixel;
    109 e701b280 - }
    110 e701b280 -
    111 d95640da - Point2D IdentityXYTransform::reverseTransform(Point2D const &pixel) const
    112 e701b280 - {
    113 e701b280 - return pixel;
    114 e701b280 - }
    115 e701b280 -
    116 d95640da - AffineTransform IdentityXYTransform::linearizeForwardTransform(Point2D const &pixel) const
    117 e701b280 - {
    118 e701b280 - // note: AffineTransform constructor called with no arguments gives the identity transform
    119 d95640da - return AffineTransform();
    120 e701b280 - }
    121 e701b280 -
    122 d95640da - AffineTransform IdentityXYTransform::linearizeReverseTransform(Point2D const &pixel) const
    123 e701b280 - {
    124 e701b280 - // note: AffineTransform constructor called with no arguments gives the identity transform
    125 d95640da - return AffineTransform();
    126 48ac4e21 - }
    127 48ac4e21 -
    128 48ac4e21 -
    129 48ac4e21 - // -------------------------------------------------------------------------------------------------
    130 48ac4e21 - //
    131 48ac4e21 - // InvertedXYTransform
    132 48ac4e21 -
    133 48ac4e21 -
    134 a6e8955c - InvertedXYTransform::InvertedXYTransform(CONST_PTR(XYTransform) base)
    135 a6e8955c - : XYTransform(base->inFpCoordinateSystem()), _base(base)
    136 48ac4e21 - { }
    137 48ac4e21 -
    138 48ac4e21 - PTR(XYTransform) InvertedXYTransform::clone() const
    139 48ac4e21 - {
    140 48ac4e21 - // deep copy
    141 48ac4e21 - return boost::make_shared (_base->clone());
    142 48ac4e21 - }
    143 48ac4e21 -
    144 48ac4e21 - PTR(XYTransform) InvertedXYTransform::invert() const
    145 48ac4e21 - {
    146 a6e8955c - return _base->clone();
    147 48ac4e21 - }
    148 48ac4e21 -
    149 d95640da - Point2D InvertedXYTransform::forwardTransform(Point2D const &pixel) const
    150 48ac4e21 - {
    151 48ac4e21 - return _base->reverseTransform(pixel);
    152 48ac4e21 - }
    153 48ac4e21 -
    154 d95640da - Point2D InvertedXYTransform::reverseTransform(Point2D const &pixel) const
    155 48ac4e21 - {
    156 48ac4e21 - return _base->forwardTransform(pixel);
    157 48ac4e21 - }
    158 48ac4e21 -
    159 d95640da - AffineTransform InvertedXYTransform::linearizeForwardTransform(Point2D const &pixel) const
    160 48ac4e21 - {
    161 48ac4e21 - return _base->linearizeReverseTransform(pixel);
    162 48ac4e21 - }
    163 48ac4e21 -
    164 d95640da - AffineTransform InvertedXYTransform::linearizeReverseTransform(Point2D const &pixel) const
    165 48ac4e21 - {
    166 48ac4e21 - return _base->linearizeForwardTransform(pixel);
    167 d1f72a42 - }
    168 d1f72a42 -
    169 e1996ce6 -
    170 dd97c30a - // -------------------------------------------------------------------------------------------------
    171 dd97c30a - //
    172 dd97c30a - // RadialXYTransform
    173 dd97c30a -
    174 dd97c30a -
    175 dd97c30a - RadialXYTransform::RadialXYTransform(std::vector const &coeffs, bool coefficientsDistort)
    176 0a5ba669 - : XYTransform(true)
    177 dd97c30a - {
    178 dd97c30a - if (coeffs.size() == 0) {
    179 dd97c30a - // constructor called with no arguments = identity transformation
    180 dd97c30a - _coeffs.resize(2);
    181 dd97c30a - _coeffs[0] = 0.0;
    182 dd97c30a - _coeffs[1] = 1.0;
    183 dd97c30a - }
    184 dd97c30a - else if ((coeffs.size() == 1) || (coeffs[0] != 0.0) || (coeffs[1] == 0.0)) {
    185 dd97c30a - // Discontinuous or singular transformation; presumably unintentional so throw exception
    186 76ea3ac3 - throw LSST_EXCEPT(pexEx::InvalidParameterException,
    187 76ea3ac3 - "invalid parameters for radial distortion");
    188 dd97c30a - }
    189 dd97c30a - else {
    190 dd97c30a - _coeffs = coeffs;
    191 dd97c30a - }
    192 dd97c30a -
    193 dd97c30a - _icoeffs = polyInvert(_coeffs);
    194 dd97c30a - _coefficientsDistort = coefficientsDistort;
    195 dd97c30a - }
    196 dd97c30a -
    197 dd97c30a - PTR(XYTransform) RadialXYTransform::clone() const
    198 dd97c30a - {
    199 dd97c30a - return boost::make_shared (_coeffs, _coefficientsDistort);
    200 dd97c30a - }
    201 dd97c30a -
    202 dd97c30a - PTR(XYTransform) RadialXYTransform::invert() const
    203 dd97c30a - {
    204 dd97c30a - return boost::make_shared (_coeffs, !_coefficientsDistort);
    205 dd97c30a - }
    206 dd97c30a -
    207 d95640da - Point2D RadialXYTransform::forwardTransform(Point2D const &p) const
    208 dd97c30a - {
    209 dd97c30a - return _coefficientsDistort ? polyEval(_coeffs,p) : polyEvalInverse(_coeffs,_icoeffs,p);
    210 dd97c30a - }
    211 dd97c30a -
    212 d95640da - Point2D RadialXYTransform::reverseTransform(Point2D const &p) const
    213 dd97c30a - {
    214 dd97c30a - return _coefficientsDistort ? polyEvalInverse(_coeffs,_icoeffs,p) : polyEval(_coeffs,p);
    215 dd97c30a - }
    216 dd97c30a -
    217 d95640da - AffineTransform RadialXYTransform::linearizeForwardTransform(Point2D const &p) const
    218 dd97c30a - {
    219 76ea3ac3 - return _coefficientsDistort ? polyEvalJacobian(_coeffs,p)
    220 76ea3ac3 - : polyEvalInverseJacobian(_coeffs,_icoeffs,p);
    221 dd97c30a - }
    222 dd97c30a -
    223 d95640da - AffineTransform RadialXYTransform::linearizeReverseTransform(Point2D const &p) const
    224 dd97c30a - {
    225 76ea3ac3 - return _coefficientsDistort ? polyEvalInverseJacobian(_coeffs,_icoeffs,p)
    226 76ea3ac3 - : polyEvalJacobian(_coeffs,p);
    227 dd97c30a - }
    228 dd97c30a -
    229 dd97c30a -
    230 dd97c30a - // --- Note: all subsequent RadialXYTransform member functions are static
    231 dd97c30a -
    232 dd97c30a - /*
    233 dd97c30a - * @brief Invert the coefficients for the polynomial.
    234 dd97c30a - *
    235 dd97c30a - * We'll need the coeffs for the inverse of the input polynomial
    236 dd97c30a - * handle up to 6th order
    237 dd97c30a - * terms from Mathematical Handbook of Formula's and Tables, Spiegel & Liu.
    238 dd97c30a - * This is a taylor approx, so not perfect. We'll use it to get close to the inverse
    239 dd97c30a - * and then use Newton-Raphson to get to machine precision. (only needs 1 or 2 iterations)
    240 dd97c30a - */
    241 dd97c30a - std::vector RadialXYTransform::polyInvert(std::vector const &coeffs)
    242 dd97c30a - {
    243 dd97c30a - static const unsigned int maxN = 7; // degree of output polynomial + 1
    244 dd97c30a -
    245 dd97c30a - //
    246 dd97c30a - // Some sanity checks. The formulas for the inversion below assume c0 == 0 and c1 != 0
    247 dd97c30a - //
    248 dd97c30a - if (coeffs.size() <= 1 || coeffs.size() > maxN || coeffs[0] != 0.0 || coeffs[1] == 0.0)
    249 76ea3ac3 - throw LSST_EXCEPT(pexEx::InvalidParameterException,
    250 76ea3ac3 - "invalid parameters in RadialXYTransform::polyInvert");
    251 dd97c30a -
    252 dd97c30a - std::vector c = coeffs;
    253 dd97c30a - c.resize(maxN, 0.0);
    254 dd97c30a -
    255 dd97c30a - std::vector ic(maxN);
    256 dd97c30a -
    257 dd97c30a - ic[0] = 0.0;
    258 dd97c30a -
    259 dd97c30a - ic[1] = 1.0;
    260 dd97c30a - ic[1] /= c[1];
    261 dd97c30a -
    262 dd97c30a - ic[2] = -c[2];
    263 dd97c30a - ic[2] /= std::pow(c[1],3);
    264 dd97c30a -
    265 dd97c30a - ic[3] = 2.0*c[2]*c[2] - c[1]*c[3];
    266 dd97c30a - ic[3] /= std::pow(c[1],5);
    267 dd97c30a -
    268 dd97c30a - ic[4] = 5.0*c[1]*c[2]*c[3] - 5.0*c[2]*c[2]*c[2] - c[1]*c[1]*c[4];
    269 dd97c30a - ic[4] /= std::pow(c[1],7);
    270 dd97c30a -
    271 dd97c30a - ic[5] = 6.0*c[1]*c[1]*c[2]*c[4] + 3.0*c[1]*c[1]*c[3]*c[3] - c[1]*c[1]*c[1]*c[5] +
    272 dd97c30a - 14.0*std::pow(c[2], 4) - 21.0*c[1]*c[2]*c[2]*c[3];
    273 dd97c30a -
    274 dd97c30a - ic[6] = 7.0*c[1]*c[1]*c[1]*c[2]*c[5] + 84.0*c[1]*c[2]*c[2]*c[2]*c[3] +
    275 dd97c30a - 7.0*c[1]*c[1]*c[1]*c[3]*c[4] - 28.0*c[1]*c[1]*c[2]*c[3]*c[3] -
    276 dd97c30a - std::pow(c[1], 4)*c[6] - 28.0*c[1]*c[1]*c[2]*c[2]*c[4] - 42.0*std::pow(c[2], 5);
    277 dd97c30a - ic[6] /= std::pow(c[1],11);
    278 dd97c30a -
    279 dd97c30a - return ic;
    280 dd97c30a - }
    281 dd97c30a -
    282 dd97c30a - double RadialXYTransform::polyEval(std::vector const &coeffs, double x)
    283 dd97c30a - {
    284 dd97c30a - int n = coeffs.size();
    285 dd97c30a -
    286 dd97c30a - double ret = 0.0;
    287 dd97c30a - for (int i = n-1; i >= 0; i--)
    288 dd97c30a - ret = ret*x + coeffs[i];
    289 dd97c30a -
    290 dd97c30a - return ret;
    291 dd97c30a - }
    292 dd97c30a -
    293 d95640da - Point2D RadialXYTransform::polyEval(std::vector const &coeffs, Point2D const &p)
    294 dd97c30a - {
    295 dd97c30a - double x = p.getX();
    296 dd97c30a - double y = p.getY();
    297 dd97c30a - double r = sqrt(x*x+y*y);
    298 dd97c30a -
    299 dd97c30a - if (r > 0.0) {
    300 dd97c30a - double rnew = polyEval(coeffs,r);
    301 dd97c30a - return Point2D(rnew*x/r, rnew*y/r);
    302 dd97c30a - }
    303 dd97c30a -
    304 76ea3ac3 - if (coeffs.size() == 0 || coeffs[0] != 0.0) {
    305 76ea3ac3 - throw LSST_EXCEPT(pexEx::InvalidParameterException,
    306 76ea3ac3 - "invalid parameters for radial distortion");
    307 76ea3ac3 - }
    308 dd97c30a -
    309 dd97c30a - return Point2D(0,0);
    310 dd97c30a - }
    311 dd97c30a -
    312 dd97c30a - double RadialXYTransform::polyEvalDeriv(std::vector const &coeffs, double x)
    313 dd97c30a - {
    314 dd97c30a - int n = coeffs.size();
    315 dd97c30a -
    316 dd97c30a - double ret = 0.0;
    317 dd97c30a - for (int i = n-1; i >= 1; i--)
    318 dd97c30a - ret = ret*x + i*coeffs[i];
    319 dd97c30a -
    320 dd97c30a - return ret;
    321 dd97c30a - }
    322 dd97c30a -
    323 d95640da - AffineTransform RadialXYTransform::polyEvalJacobian(std::vector const &coeffs, Point2D const &p)
    324 dd97c30a - {
    325 dd97c30a - double x = p.getX();
    326 dd97c30a - double y = p.getY();
    327 dd97c30a - double r = sqrt(x*x+y*y);
    328 dd97c30a - double rnew = polyEval(coeffs,r);
    329 dd97c30a - double rderiv = polyEvalDeriv(coeffs,r);
    330 dd97c30a - return makeAffineTransform(x, y, rnew, rderiv);
    331 dd97c30a - }
    332 dd97c30a -
    333 76ea3ac3 - double RadialXYTransform::polyEvalInverse(std::vector const &coeffs,
    334 76ea3ac3 - std::vector const &icoeffs, double x)
    335 dd97c30a - {
    336 dd97c30a - static const int maxIter = 10;
    337 dd97c30a - double tolerance = 1.0e-14 * x;
    338 dd97c30a -
    339 dd97c30a - double r = polyEval(icoeffs, x); // initial guess
    340 dd97c30a - int iter = 0;
    341 dd97c30a -
    342 dd97c30a - for (;;) {
    343 dd97c30a - double dx = x - polyEval(coeffs,r); // residual
    344 dd97c30a - if (fabs(dx) <= tolerance)
    345 dd97c30a - return r;
    346 76ea3ac3 - if (iter++ > maxIter) {
    347 76ea3ac3 - throw LSST_EXCEPT(pexEx::RuntimeErrorException,
    348 76ea3ac3 - "max iteration count exceeded in RadialXYTransform::polyEvalInverse");
    349 76ea3ac3 - }
    350 dd97c30a - r += dx / polyEvalDeriv(coeffs,r); // Newton-Raphson iteration
    351 dd97c30a - }
    352 dd97c30a - }
    353 dd97c30a -
    354 d95640da - Point2D RadialXYTransform::polyEvalInverse(std::vector const &coeffs,
    355 76ea3ac3 - std::vector const &icoeffs,
    356 76ea3ac3 - Point2D const &p)
    357 dd97c30a - {
    358 dd97c30a - double x = p.getX();
    359 dd97c30a - double y = p.getY();
    360 dd97c30a - double r = sqrt(x*x+y*y);
    361 dd97c30a -
    362 dd97c30a - if (r > 0.0) {
    363 dd97c30a - double rnew = polyEvalInverse(coeffs, icoeffs, r);
    364 dd97c30a - return Point2D(rnew*x/r, rnew*y/r);
    365 dd97c30a - }
    366 dd97c30a -
    367 76ea3ac3 - if (coeffs.size() == 0 || coeffs[0] != 0.0) {
    368 76ea3ac3 - throw LSST_EXCEPT(pexEx::InvalidParameterException,
    369 76ea3ac3 - "invalid parameters for radial distortion");
    370 76ea3ac3 - }
    371 dd97c30a -
    372 dd97c30a - return Point2D(0,0);
    373 dd97c30a - }
    374 dd97c30a -
    375 d95640da - AffineTransform RadialXYTransform::polyEvalInverseJacobian(std::vector const &coeffs,
    376 d95640da - std::vector const &icoeffs,
    377 d95640da - Point2D const &p)
    378 dd97c30a - {
    379 dd97c30a - double x = p.getX();
    380 dd97c30a - double y = p.getY();
    381 dd97c30a - double r = sqrt(x*x+y*y);
    382 dd97c30a - double rnew = polyEvalInverse(coeffs,icoeffs,r);
    383 dd97c30a - double rderiv = 1.0 / polyEvalDeriv(coeffs,rnew);
    384 dd97c30a - return makeAffineTransform(x, y, rnew, rderiv);
    385 dd97c30a - }
    386 dd97c30a -
    387 d95640da - AffineTransform RadialXYTransform::makeAffineTransform(double x, double y, double rnew, double rderiv)
    388 dd97c30a - {
    389 dd97c30a - double r = sqrt(x*x + y*y);
    390 dd97c30a -
    391 dd97c30a - if (r <= 0.0) {
    392 dd97c30a - AffineTransform ret;
    393 dd97c30a - ret[0] = ret[3] = rderiv; // ret = rderiv * (identity)
    394 dd97c30a - return ret;
    395 dd97c30a - }
    396 dd97c30a -
    397 dd97c30a - //
    398 dd97c30a - // Note: calculation of "t" is numerically unstable as r->0, since p'(r) and p(r)/r will be
    399 dd97c30a - // nearly equal. However, detailed analysis shows that this is actually OK. The numerical
    400 dd97c30a - // instability means that the roundoff error in t is O(10^{-17}) even though t is formally O(r).
    401 dd97c30a - //
    402 76ea3ac3 - // Propagating through the formulas below, the AffineTransform is
    403 76ea3ac3 - // [rderiv*I + O(r) + O(10^{-17})] which is fine (assuming rderiv is nonzero as r->0).
    404 dd97c30a - //
    405 dd97c30a - double t = rderiv - rnew/r;
    406 dd97c30a -
    407 dd97c30a - AffineTransform ret;
    408 dd97c30a - ret[0] = (rderiv*x*x + rnew/r*y*y) / (r*r); // a00
    409 dd97c30a - ret[1] = ret[2] = t*x*y / (r*r); // a01 == a10 for this transform
    410 dd97c30a - ret[3] = (rderiv*y*y + rnew/r*x*x) / (r*r); // a11
    411 dd97c30a - ret[4] = -t*x; // v0
    412 dd97c30a - ret[5] = -t*y; // v1
    413 dd97c30a - return ret;
    414 dd97c30a - }
    415 dd97c30a -
    416 dd97c30a -
    }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    a6e8955c

    commit a6e8955c7b40f8954863e1dcd0092c1a2701eafb
    Author: Kendrick Smith 
    Date:   Fri Feb 8 13:28:12 2013 -0500
    
        cleanup, add comments
    

    d95640da

    commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
    Author: Kendrick Smith 
    Date:   Tue Feb 19 23:44:14 2013 -0500
    
        move afw::image::XYTransform -> afw::geom::XYTransform
             afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
             afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
        
        wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom
    

    48ac4e21

    commit 48ac4e2159493034950651ab26088f503e79efdf
    Author: Kendrick Smith 
    Date:   Thu Jan 10 12:33:48 2013 -0500
    
        tweak XYTransform::invert() logic
    

    dd97c30a

    commit dd97c30a654e470f55aa39df0b90445b5877c2d5
    Author: Kendrick Smith 
    Date:   Mon Feb 4 15:33:01 2013 -0500
    
        add class RadialXYTransform
    

    f521567c

    commit f521567c57ba5e52e02ccc4b94d76ce4799ff0c8
    Author: Kendrick Smith 
    Date:   Mon Feb 4 16:41:08 2013 -0500
    
        XYTransform member functions to distort Quadrupoles
    

    e701b280

    commit e701b280170e48b6cd0c7dcef21abd351f94c990
    Author: Kendrick Smith 
    Date:   Tue Jan 29 14:58:39 2013 -0500
    
        IdentityXYTransform class
    

    d1f72a42

    commit d1f72a42475c24561e74d74423720abe57e6e38f
    Author: Kendrick Smith 
    Date:   Thu Jan 10 11:51:01 2013 -0500
    
        add XYTransform::invert() member function
    

    0a5ba669

    commit 0a5ba6691461a9ba3a61b11eda9494ab776f6d6a
    Author: Kendrick Smith 
    Date:   Mon Feb 4 16:22:02 2013 -0500
    
        class DetectorXYTransform
    

    e1996ce6

    commit e1996ce6b044a5977a9693420f5f9837947ec5eb
    Author: Kendrick Smith 
    Date:   Wed Dec 19 14:21:49 2012 -0500
    
        add XYTransform.h, XYTransform.cc (compiles but untested)
    

    1e136e29

    commit 1e136e2989a4de7139e93f80555160169b1675d7
    Author: Kendrick Smith 
    Date:   Wed Feb 6 16:31:24 2013 -0500
    
        add comment
    

    76ea3ac3

    commit 76ea3ac37c9afb096b9c3f82e389b9f8525d79b4
    Author: Kendrick Smith 
    Date:   Sat Feb 16 12:50:51 2013 -0500
    
        110-col limit
    

    Commits in /Users/nate/repos_lsst/afw/

    0a8d9c69

    commit 0a8d9c69b9efa9a486595305a950ce02ab1c2ade
    Author: Russell Owen 
    Date:   Tue Feb 18 17:31:35 2014 -0800
    
        Removed inFpCoordinateSystem flag from XYTransform.
    

    Return to list

    tests/maskedImagePersistence1.py

    Diff:

    1 ac6cdb90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import os import os.path
    28 c15438f7 + import unittest
    28 c15438f7 - import unittest
    30 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests
    30 ac6cdb90 -
    import lsst.afw.image as afwImage import lsst.daf.base as dafBase import lsst.daf.persistence as dafPers import lsst.pex.policy as pexPolicy
    35 c15438f7 - import lsst.pex.exceptions as pexExceptions
    36 c15438f7 - import eups
    38 76505c6a - dataDir = os.path.join(eups.productDir("afwdata"), "data")
    ? ^ ^ ^^^^^ ^
    37 7cbb2bb9 + dataDir = os.path.join(lsst.utils.getPackageDir("afwdata"), "data")
    ? ^^^^^ ^^^ ^^^^^ ^^^^ if not dataDir: raise RuntimeError("You must set up afwdata to run these tests") class MaskedImagePersistenceTestCase(unittest.TestCase): """A test case for MaskedImage Persistence""" def checkImages(self, maskedImage, maskedImage2): # Check that two MaskedImages are identical (well, actually check only every 4th pixel) pass def setUp(self): # Create the additionalData PropertySet self.additionalData = dafBase.PropertySet() self.additionalData.addInt("sliceId", 0) self.additionalData.addString("visitId", "fov391") self.additionalData.addInt("universeSize", 100) self.additionalData.addString("itemName", "foo") # Create an empty Policy policy = pexPolicy.Policy() # Get a Persistence object self.persistence = dafPers.Persistence.getPersistence(policy) # Choose a file to manipulate self.infile = os.path.join(dataDir, "small_MI.fits") self.maskedImage = afwImage.MaskedImageF(self.infile) def tearDown(self): del self.additionalData del self.persistence del self.infile del self.maskedImage def testFitsPersistence(self): """Test persisting to FITS""" # Set up the LogicalLocation. logicalLocation = dafPers.LogicalLocation(self.infile) # Create a FitsStorage and put it in a StorageList. storage = self.persistence.getRetrieveStorage("FitsStorage", logicalLocation) storageList = dafPers.StorageList([storage]) # Let's do the retrieval! maskedImage2 = afwImage.MaskedImageF.swigConvert( \ self.persistence.unsafeRetrieve("MaskedImageF", storageList, self.additionalData)) # Check the resulting MaskedImage self.checkImages(self.maskedImage, maskedImage2) def testBoostPersistence(self): """Persist the MaskedImage using boost""" miPath = os.path.join("tests", "data", "Dest") logicalLocation = dafPers.LogicalLocation(miPath) storage = self.persistence.getPersistStorage("BoostStorage", logicalLocation) storageList = dafPers.StorageList([storage])
    98 c15438f7 - try:
    99 c15438f7 - self.persistence.persist(self.maskedImage, storageList, self.additionalData)
    ? ----
    97 6fc1c3d1 + self.persistence.persist(self.maskedImage, storageList, self.additionalData)
    100 3771b5eb - except pexExceptions.LsstCppException, e:
    101 3771b5eb - print e.args[0].what()
    102 c15438f7 - raise
    103 7ca150ed -
    ? --
    98 6fc1c3d1 +
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(MaskedImagePersistenceTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7ca150ed

    commit 7ca150edfd268bbca94fac0337a25941c51ee2a1
    Author: rowen 
    Date:   Wed Mar 11 18:25:19 2009 +0000
    
        Minor test fixes.
    

    76505c6a

    commit 76505c6a9851eb22e1080810712fbd4b07f2ef02
    Author: Paul Price 
    Date:   Fri Nov 18 17:15:21 2011 -0500
    
        Updating image directory.
    

    c15438f7

    commit c15438f75051d5456dca7ca25c3053afe0664d12
    Author: rhl 
    Date:   Tue Apr 8 13:55:05 2008 +0000
    
        Use unittest
    

    ac6cdb90

    commit ac6cdb90be5842198a7de239eaf67b33ee54a74d
    Author: ktlim 
    Date:   Mon Nov 26 23:41:06 2007 +0000
    
        Merged revisions 2718-2729,2731-2804,2806-2900,2902-3023,3025-3144,3146-3389,3391-3414 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DC2/fw/tickets/171
        
        Merged #171 with trunk.
        Also fixed duplicate declaration in kernel.i.
        Removed MaskIO_2.cc test at direction of Tim Axelrod.
        All remaining tests pass.
        
        ........
          r2719 | ktlim | 2007-10-04 17:14:49 -0700 (Thu, 04 Oct 2007) | 1 line
        
          Make Image a Persistable and create its Formatter.  Formatter implementation is not yet complete.
        ........
          r2725 | ktlim | 2007-10-05 00:50:49 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Add code for persisting to FitsStorage using readFits() and writeFits().  Also add (commented out) code for using LSSTFitsResource directly.  Ignore _offsetRows and _offsetCols for now.
        ........
          r2726 | ktlim | 2007-10-05 00:51:37 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Move ImageFormatter.cc from libfw to libfitsio.  Require boost and mwi for libfitsio.
        ........
          r2729 | ktlim | 2007-10-05 02:09:00 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Copy ImageFormatter to MaskedImageFormatter.  *** Will not even compile yet. ***
        ........
          r2742 | ktlim | 2007-10-05 13:10:54 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Make MaskedImage a Persistable and make writeFits() const.
        ........
          r2743 | ktlim | 2007-10-05 13:11:15 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Make writeFits() const.
        ........
          r2744 | ktlim | 2007-10-05 13:12:07 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Implement MaskedImage persistence to FitsStorage.  BoostStorage is still incomplete.
        ........
          r2745 | ktlim | 2007-10-05 13:12:36 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Move all routines into libfw.so; eliminate libfitsio.so.
        ........
          r2746 | ktlim | 2007-10-05 13:17:52 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Import Persistable.h to avoid warnings about unknown base class.
        ........
          r2748 | ktlim | 2007-10-05 13:56:43 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Instantiate proper versions of MaskedImageFormatter.
        ........
          r2749 | ktlim | 2007-10-05 13:58:09 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Use lsst_persistable_shared_ptr macro to enable conversion of Persistables to appropriate types.  Define some typedefs to get around issue of passing multiple template parameters to the macro.
        ........
          r2750 | ktlim | 2007-10-05 14:08:04 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Get registration type name correct.
        ........
          r2751 | ktlim | 2007-10-05 14:33:03 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Remove fitsio dependency.
        ........
          r2753 | ktlim | 2007-10-05 15:14:18 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Use new version of lsst_persistable_shared_ptr that does not require typedefs (which don't work anyway).
        ........
          r2754 | ktlim | 2007-10-05 15:14:38 -0700 (Fri, 05 Oct 2007) | 1 line
        
          Test for retrieval and persistence of MaskedImage through the persistence framework.
        ........
          r2770 | ktlim | 2007-10-07 02:39:14 -0700 (Sun, 07 Oct 2007) | 1 line
        
          Add (untested) ability to persist an Image to a Boost text archive.  Add partial ability to persist a MaskedImage to a Boost text archive.
        ........
          r2771 | ktlim | 2007-10-07 10:30:27 -0700 (Sun, 07 Oct 2007) | 1 line
        
          Rationalize Image pointer type names
        ........
          r2772 | ktlim | 2007-10-07 10:31:18 -0700 (Sun, 07 Oct 2007) | 1 line
        
          Typo fixes: need to use pointer in MaskedImageFormatter; use input archive in ImageFormatter.  Add ImageFormatter instantiation for unsigned short.
        ........
          r2773 | ktlim | 2007-10-07 10:34:52 -0700 (Sun, 07 Oct 2007) | 1 line
        
          Add test for image retrieval from FITS, persistence and retrieval via Boost.
        ........
          r2774 | ktlim | 2007-10-07 11:00:36 -0700 (Sun, 07 Oct 2007) | 1 line
        
          We should test for exact pixel match after retrieving.
        ........
          r2775 | ktlim | 2007-10-07 11:01:59 -0700 (Sun, 07 Oct 2007) | 1 line
        
          Use is_saving/is_loading to merge delegateSerialize back into one template method.  Use make_binary_object() to get more efficient and exact pixel serialization.
        ........
          r2796 | ktlim | 2007-10-08 16:21:25 -0700 (Mon, 08 Oct 2007) | 1 line
        
          Fix comments.
        ........
          r2797 | ktlim | 2007-10-08 16:22:19 -0700 (Mon, 08 Oct 2007) | 1 line
        
          Remove unnecessary includes.
        ........
          r2799 | ktlim | 2007-10-08 16:23:38 -0700 (Mon, 08 Oct 2007) | 1 line
        
          Make Mask into a Persistable, create a MaskFormatter, and use it for Boost serialization in MaskedImageFormatter.
        ........
          r2803 | ktlim | 2007-10-08 17:22:37 -0700 (Mon, 08 Oct 2007) | 1 line
        
          Add formatters for Exposure (to FITS and Boost) and WCS (to Boost only, plus a helper function for Exposure).
        ........
          r2806 | ktlim | 2007-10-08 18:00:36 -0700 (Mon, 08 Oct 2007) | 1 line
        
          Don't kill the whole build if fwData is not present.
        ........
          r2807 | ktlim | 2007-10-08 18:01:58 -0700 (Mon, 08 Oct 2007) | 1 line
        
          Make WCS and Exposure Persistable.
        ........
          r2808 | ktlim | 2007-10-08 18:03:35 -0700 (Mon, 08 Oct 2007) | 1 line
        
          Fix minor compiler-breaking bugs in ExposureFormatter and WcsFormatter.
        ........
          r2810 | ktlim | 2007-10-08 18:14:18 -0700 (Mon, 08 Oct 2007) | 1 line
        
          Fix typo (OArchive instead of IArchive).
        ........
          r2811 | ktlim | 2007-10-09 00:07:43 -0700 (Tue, 09 Oct 2007) | 1 line
        
          Memory for wcsprm, which is a C struct, should be allocated with malloc, not new[].
        ........
          r2828 | ktlim | 2007-10-09 16:53:37 -0700 (Tue, 09 Oct 2007) | 1 line
        
          Initial example implementation of DbStorage for Exposures.  Assumes existence of a Filter table, and assumes that the location of the FITS file will be passed in through additionalData.
        ........
          r2832 | ktlim | 2007-10-09 17:45:43 -0700 (Tue, 09 Oct 2007) | 1 line
        
          Change expected location of previous path.
        ........
          r2861 | ktlim | 2007-10-10 22:22:42 -0700 (Wed, 10 Oct 2007) | 1 line
        
          WCS metadata must be added at top level of image metadata DataProperty for correct persistence.
        ........
          r2868 | ktlim | 2007-10-11 17:55:24 -0700 (Thu, 11 Oct 2007) | 1 line
        
          Persist more header fields into the database.
        ........
          r2869 | ktlim | 2007-10-11 18:06:11 -0700 (Thu, 11 Oct 2007) | 1 line
        
          Some fields are only present in Raw Exposures; some are only present in Science Exposures.  Reorder to match schema.
        ........
          r2872 | ktlim | 2007-10-12 00:02:11 -0700 (Fri, 12 Oct 2007) | 1 line
        
          Minor changes.  All fields in raw and science exposures are now accounted for, although implementation of datetime columns remains to be done.
        ........
          r2889 | ktlim | 2007-10-15 09:29:46 -0700 (Mon, 15 Oct 2007) | 1 line
        
          Add protective defines for non-GCC compilers.
        ........
          r2890 | ktlim | 2007-10-15 09:51:10 -0700 (Mon, 15 Oct 2007) | 1 line
        
          Minor fixes.
        ........
          r2908 | ktlim | 2007-10-17 13:10:25 -0700 (Wed, 17 Oct 2007) | 1 line
        
          Start moving include and source files for formatters into new namespaces and directories.  Change names of persistable classes to match Python names.
        ........
          r2909 | ktlim | 2007-10-17 13:11:22 -0700 (Wed, 17 Oct 2007) | 1 line
        
          Finish move of formatters to new subdirectory.
        ........
          r2910 | ktlim | 2007-10-17 13:17:26 -0700 (Wed, 17 Oct 2007) | 1 line
        
          Fix typo.
        ........
          r2911 | ktlim | 2007-10-17 13:25:11 -0700 (Wed, 17 Oct 2007) | 1 line
        
          More minor fixes.  Builds now!
        ........
          r2930 | ktlim | 2007-10-18 00:09:21 -0700 (Thu, 18 Oct 2007) | 1 line
        
          Complete support for DATETIME and MJD fields.
        ........
          r3022 | ktlim | 2007-10-22 16:06:29 -0700 (Mon, 22 Oct 2007) | 1 line
        
          Change names of types to match Python.
        ........
          r3023 | ktlim | 2007-10-22 16:06:58 -0700 (Mon, 22 Oct 2007) | 1 line
        
          Check for database authenticator availability and copy environment variable if needed.
        ........
          r3025 | ktlim | 2007-10-22 17:38:25 -0700 (Mon, 22 Oct 2007) | 1 line
        
          Fix imports.
        ........
          r3126 | ktlim | 2007-11-01 07:34:12 -0700 (Thu, 01 Nov 2007) | 1 line
        
          Update to new Formatter interface.
        ........
          r3127 | ktlim | 2007-11-01 07:36:02 -0700 (Thu, 01 Nov 2007) | 1 line
        
          Update to new Formatter interface.
        ........
          r3128 | ktlim | 2007-11-01 07:36:31 -0700 (Thu, 01 Nov 2007) | 1 line
        
          Make Exposure persistable in Python.
        ........
          r3129 | ktlim | 2007-11-01 07:37:03 -0700 (Thu, 01 Nov 2007) | 1 line
        
          Include base classes to get Python inheritance.
        ........
          r3130 | ktlim | 2007-11-01 07:41:11 -0700 (Thu, 01 Nov 2007) | 1 line
        
          Fix type of filter id.  Allow DP types to be different from DB types, and allow missing DP values to create NULL DB values.  Add some debugging output.
        ........
          r3221 | ktlim | 2007-11-06 18:29:54 -0800 (Tue, 06 Nov 2007) | 1 line
        
          Since default output parameter handling was removed from mwi p_lsstSwig.i, add it explicitly here.
        ........
          r3222 | ktlim | 2007-11-06 18:46:27 -0800 (Tue, 06 Nov 2007) | 1 line
        
          Move Persistable.h before DataProperty.h to get proper base class declaration.
        ........
          r3223 | ktlim | 2007-11-06 18:49:27 -0800 (Tue, 06 Nov 2007) | 1 line
        
          Change from retrieve to unsafeRetrieve, including use of variable to prevent memory management problems.
        ........
          r3299 | ktlim | 2007-11-09 20:14:11 -0800 (Fri, 09 Nov 2007) | 1 line
        
          Make the test harder by not using an intermediate variable.
        ........
          r3407 | ktlim | 2007-11-20 15:56:22 -0800 (Tue, 20 Nov 2007) | 1 line
        
          Start working on restoring from DbStorage.  Throw LSST exceptions instead of std.
        ........
          r3411 | ktlim | 2007-11-26 13:59:00 -0800 (Mon, 26 Nov 2007) | 1 line
        
          Remove unneeded, duplicative definition of smart pointer macros.
        ........
          r3413 | ktlim | 2007-11-26 14:35:07 -0800 (Mon, 26 Nov 2007) | 1 line
        
          Fix command line parameters for MaskedImageIO_2.cc.
        ........
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    c15438f7

    commit c15438f75051d5456dca7ca25c3053afe0664d12
    Author: rhl 
    Date:   Tue Apr 8 13:55:05 2008 +0000
    
        Use unittest
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/math/Kernel.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include 
                    #include 
                    
                    #include "boost/format.hpp"
                    #if defined(__ICC)
                    #pragma warning (push)
                    #pragma warning (disable: 444)
                    #endif
                    #include "boost/archive/text_oarchive.hpp"
                    #if defined(__ICC)
                    #pragma warning (pop)
                    #endif
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/Kernel.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwMath = lsst::afw::math;
                    
                    afwMath::generic_kernel_tag afwMath::generic_kernel_tag_; ///< Used as default value in argument lists
                    afwMath::deltafunction_kernel_tag afwMath::deltafunction_kernel_tag_;
                        ///< Used as default value in argument lists
                    
                    //
                    // Constructors
                    //
                    afwMath::Kernel::Kernel()
                    :
                        daf::base::Citizen(typeid(this)),
                        _spatialFunctionList(),
                        _width(0),
                        _height(0),
                        _ctrX(0),
                        _ctrY(0),
                        _nKernelParams(0)
                    {}
                    
                    afwMath::Kernel::Kernel(
                        int width,
                        int height,
                        unsigned int nKernelParams,
                        SpatialFunction const &spatialFunction)
                    :
                        daf::base::Citizen(typeid(this)),
                        _spatialFunctionList(),
                        _width(width),
                        _height(height),
                        _ctrX((width-1)/2),
                        _ctrY((height-1)/2),
                        _nKernelParams(nKernelParams)
                    {
                        if ((width < 1) || (height < 1)) {
                            std::ostringstream os;
                            os << "kernel height = " << height << " and/or width = " << width << " < 1";
    
    79 f0a2e370 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    79 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } if (dynamic_cast(&spatialFunction)) { // spatialFunction is not really present } else { if (nKernelParams == 0) {
    85 068759b9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "Kernel function has no parameters");
    ? ^^^^^^ ^
    85 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "Kernel function has no parameters");
    ? ^^ ^ } for (unsigned int ii = 0; ii < nKernelParams; ++ii) { SpatialFunctionPtr spatialFunctionCopy = spatialFunction.clone(); this->_spatialFunctionList.push_back(spatialFunctionCopy); } } } double afwMath::Kernel::computeImage( lsst::afw::image::Image &image, bool doNormalize, double x, double y ) const { if (image.getDimensions() != this->getDimensions()) { std::ostringstream os; os << "image dimensions = ( " << image.getWidth() << ", " << image.getHeight() << ") != (" << this->getWidth() << ", " << this->getHeight() << ") = kernel dimensions";
    104 92570c02 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    104 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } image.setXY0(-_ctrX, -_ctrY); if (this->isSpatiallyVarying()) { this->setKernelParametersFromSpatialModel(x, y); } return doComputeImage(image, doNormalize); } afwMath::Kernel::Kernel( int width, int height, std::vector spatialFunctionList) : daf::base::Citizen(typeid(this)), _width(width), _height(height), _ctrX(width/2), _ctrY(height/2), _nKernelParams(spatialFunctionList.size()) { if ((width < 1) || (height < 1)) { std::ostringstream os; os << "kernel height = " << height << " and/or width = " << width << " < 1";
    128 f0a2e370 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    128 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } for (unsigned int ii = 0; ii < spatialFunctionList.size(); ++ii) { SpatialFunctionPtr spatialFunctionCopy = spatialFunctionList[ii]->clone(); this->_spatialFunctionList.push_back(spatialFunctionCopy); } } // // Public Member Functions // void afwMath::Kernel::setSpatialParameters(const std::vector > params) { // Check params size before changing anything unsigned int nKernelParams = this->getNKernelParameters(); if (params.size() != nKernelParams) {
    143 068759b9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    143 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ (boost::format("params has %d entries instead of %d") % params.size() % nKernelParams).str()); } unsigned int nSpatialParams = this->getNSpatialParameters(); for (unsigned int ii = 0; ii < nKernelParams; ++ii) { if (params[ii].size() != nSpatialParams) {
    149 068759b9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    149 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ (boost::format("params[%d] has %d entries instead of %d") % ii % params[ii].size() % nSpatialParams).str()); } } // Set parameters if (nSpatialParams > 0) { for (unsigned int ii = 0; ii < nKernelParams; ++ii) { this->_spatialFunctionList[ii]->setParameters(params[ii]); } } } void afwMath::Kernel::computeKernelParametersFromSpatialModel( std::vector &kernelParams, double x, double y) const { std::vector::iterator paramIter = kernelParams.begin(); std::vector::const_iterator funcIter = _spatialFunctionList.begin(); for ( ; funcIter != _spatialFunctionList.end(); ++funcIter, ++paramIter) { *paramIter = (*(*funcIter))(x,y); } } afwMath::Kernel::SpatialFunctionPtr afwMath::Kernel::getSpatialFunction( unsigned int index ) const { if (index >= _spatialFunctionList.size()) { if (!this->isSpatiallyVarying()) {
    176 068759b9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "kernel is not spatially varying");
    ? ^^^^^^ ^
    176 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "kernel is not spatially varying");
    ? ^^ ^ } else { std::ostringstream errStream; errStream << "index = " << index << "; must be < , " << _spatialFunctionList.size();
    180 068759b9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, errStream.str());
    ? ^^^^^^ ^
    180 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, errStream.str());
    ? ^^ ^ } } return _spatialFunctionList[index]->clone(); } std::vector afwMath::Kernel::getSpatialFunctionList( ) const { std::vector spFuncCopyList; for (std::vector::const_iterator spFuncIter = _spatialFunctionList.begin(); spFuncIter != _spatialFunctionList.end(); ++spFuncIter) { spFuncCopyList.push_back((**spFuncIter).clone()); } return spFuncCopyList; } std::vector afwMath::Kernel::getKernelParameters() const { return std::vector(); } afwGeom::Box2I afwMath::Kernel::growBBox(afwGeom::Box2I const &bbox) const { return afwGeom::Box2I( afwGeom::Point2I(bbox.getMin() - afwGeom::Extent2I(getCtr())), afwGeom::Extent2I(bbox.getDimensions() + getDimensions() - afwGeom::Extent2I(1,1))); } afwGeom::Box2I afwMath::Kernel::shrinkBBox(afwGeom::Box2I const &bbox) const { if ((bbox.getWidth() < getWidth()) || ((bbox.getHeight() < getHeight()))) { std::ostringstream os; os << "bbox dimensions = " << bbox.getDimensions() << " < (" << getWidth() << ", " << getHeight() << ") in one or both dimensions";
    212 07909a43 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    212 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } return afwGeom::Box2I( afwGeom::Point2I( bbox.getMinX() + getCtrX(), bbox.getMinY() + getCtrY()), afwGeom::Extent2I( bbox.getWidth() + 1 - getWidth(), bbox.getHeight() + 1 - getHeight())); } std::string afwMath::Kernel::toString(std::string const& prefix) const { std::ostringstream os; os << prefix << "Kernel:" << std::endl; os << prefix << "..height, width: " << _height << ", " << _width << std::endl; os << prefix << "..ctr (X, Y): " << _ctrX << ", " << _ctrY << std::endl; os << prefix << "..nKernelParams: " << _nKernelParams << std::endl; os << prefix << "..isSpatiallyVarying: " << (this->isSpatiallyVarying() ? "True" : "False") << std::endl; if (this->isSpatiallyVarying()) { os << prefix << "..spatialFunctions:" << std::endl; for (std::vector::const_iterator spFuncPtr = _spatialFunctionList.begin(); spFuncPtr != _spatialFunctionList.end(); ++spFuncPtr) { os << prefix << "...." << (*spFuncPtr)->toString() << std::endl; } } return os.str(); } #if 0 // This fails to compile with icc void afwMath::Kernel::toFile(std::string fileName) const { std::ofstream os(fileName.c_str()); boost::archive::text_oarchive oa(os); oa << this; } #endif // // Protected Member Functions // void afwMath::Kernel::setKernelParameter(unsigned int, double) const {
    254 068759b9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "Kernel has no kernel parameters");
    ? ^^^^^^ ^
    254 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "Kernel has no kernel parameters");
    ? ^^ ^ } void afwMath::Kernel::setKernelParametersFromSpatialModel(double x, double y) const { std::vector::const_iterator funcIter = _spatialFunctionList.begin(); for (int ii = 0; funcIter != _spatialFunctionList.end(); ++funcIter, ++ii) { this->setKernelParameter(ii, (*(*funcIter))(x,y)); } } std::string afwMath::Kernel::getPythonModule() const { return "lsst.afw.math"; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    068759b9

    commit 068759b9de5ac7caee50d816e7ff6d2c468b4867
    Author: rowen 
    Date:   Mon Sep 28 21:26:58 2009 +0000
    
        Changed Kernel's PixelT to Pixel and PtrT to Ptr
        Added Kernel::ConstPtr
        Renamed KernelList specializations to remove final D (except KernelList itself,
        alas, because I could not make that work).
        Renamed some math .i files to the proper convention.
    

    07909a43

    commit 07909a430dd81a92e25ab17ebcb2665e0c09f681
    Author: rowen 
    Date:   Fri Apr 23 20:57:13 2010 +0000
    
        Attempted to swig new functions. (Unfortunately imageLib.i won't swig, despite no changes on my part. I'm not sure what's going on.)
    

    f0a2e370

    commit f0a2e370f838fd5323a7746c9e8f12da9f58c4d1
    Author: rowen 
    Date:   Thu Jun 24 23:37:24 2010 +0000
    
        Implemented ticket #1345:
        - convolve sets xy0 of the output image (not yet tested; I'll add this)
        - convolve throws an exception if kernel width or height < 1 (tested)
        - the default constructor for DeltaFunctionKernel sets isDeltaFunctionBasis (not unit testable)
        - Kernel and subclasses should not support copy or assignment (not unit testable)
    

    92570c02

    commit 92570c02a059d1547b68e84d8a7326f68938b71b
    Author: Russell Owen 
    Date:   Tue May 7 10:23:10 2013 -0700
    
        Implement ticket #2620: computeImage should set xy0.
        Removed the ability to pass a smaller image to LinearCombinationKernel::computeImage.
        AnalyticKernel::computeImage can still be called with an image of any dimensions,
        but only on that class; if you try to do this on a pointer or reference to Kernel
        then Kernel::computeImage is called,which rejects images whose dimensions do not match that of Kernel
        (Jim Bosch and I consider this a feature).
        Added a unit test to tests/kernel.py that exercises the dimension checking code.
        Moved some boilerplate code for computeImage into a protected member function doComputeImage
        and made Kernel::computeImage nonvirtual.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/table/SchemaMapper.cc

    Diff:

                    #include "boost/preprocessor/seq/for_each.hpp"
                    #include "boost/preprocessor/tuple/to_seq.hpp"
                    
                    #include "lsst/afw/table/SchemaMapper.h"
                    #include "lsst/afw/table/BaseRecord.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    namespace {
                    
                    // Variant visitation functor used in SchemaMapper::invert()
                    struct SwapKeyPair : public boost::static_visitor<> {
                    
                        template 
                        void operator()(std::pair< Key, Key > & pair) const {
                            std::swap(pair.first, pair.second);
                        }
                    
                        void operator()(detail::SchemaMapperImpl::KeyPairVariant & v) const {
                            boost::apply_visitor(*this, v);
                        }
                    
                    };
                    
                    // Variant visitation functor that returns true if the input key in a KeyPairVariant matches a
                    // the Key the functor was initialized with.
                    template 
                    struct KeyPairCompareEqual : public boost::static_visitor {
                    
                        template 
                        bool operator()(std::pair< Key, Key > const & pair) const {
                            return _target == pair.first;
                        }
                        
                        bool operator()(detail::SchemaMapperImpl::KeyPairVariant const & v) const {
                            return boost::apply_visitor(*this, v);
                        }
                    
                        KeyPairCompareEqual(Key const & target) : _target(target) {}
                    
                    private:
                        Key const & _target;
                    };
                    
                    // Functor used to iterate through a minimal schema and map all fields present in the
                    // input schema and add those that are not.
                    struct MapMinimalSchema {
                    
                        template 
                        void operator()(SchemaItem const & item) const {
                            Key outputKey;
                            if (_doMap) {
                                try {
                                    SchemaItem inputItem = _mapper->getInputSchema().find(item.key);
                                    outputKey = _mapper->addMapping(item.key);
    
    56 0315d7db - } catch (pex::exceptions::NotFoundException &) {
    ? ^^^^^^ ^
    56 21597d88 + } catch (pex::exceptions::NotFoundError &) {
    ? ^^ ^ outputKey = _mapper->addOutputField(item.field); } } else { outputKey = _mapper->addOutputField(item.field); } assert(outputKey == item.key); } explicit MapMinimalSchema(SchemaMapper * mapper, bool doMap) : _mapper(mapper), _doMap(doMap) {} private: SchemaMapper * _mapper; bool _doMap; }; // Schema::forEach functor that copies all fields from an schema to a schema mapper and maps them. struct AddMapped { template void operator()(SchemaItem const & item) const { Field field(prefix + item.field.getName(), item.field.getDoc(), item.field.getUnits(), item.field); mapper->addMapping(item.key, field); } explicit AddMapped(SchemaMapper * mapper_) : mapper(mapper_) {} SchemaMapper * mapper; std::string prefix; }; // Schema::forEach functor that copies all fields from an schema to a schema mapper without mapping them. struct AddUnmapped { template void operator()(SchemaItem const & item) const { Field field(prefix + item.field.getName(), item.field.getDoc(), item.field.getUnits(), item.field); mapper->addOutputField(field); } explicit AddUnmapped(SchemaMapper * mapper_) : mapper(mapper_) {} SchemaMapper * mapper; std::string prefix; }; struct RemoveMinimalSchema { template void operator()(SchemaItem const & item) const { if (!minimal.contains(item)) { mapper->addMapping(item.key); } } RemoveMinimalSchema(SchemaMapper * mapper_, Schema const & minimal_) : mapper(mapper_), minimal(minimal_) {} SchemaMapper * mapper; Schema minimal; }; } // anonymous SchemaMapper::SchemaMapper() : _impl(new Impl(Schema(), Schema())) {} SchemaMapper::SchemaMapper(SchemaMapper const & other) : _impl(new Impl(*other._impl)) {} SchemaMapper::SchemaMapper(Schema const & input, Schema const & output) : _impl(new Impl(input, output)) {}
    128 f1760fcb + SchemaMapper::SchemaMapper(Schema const & input, bool shareAliasMap) :
    129 56df42d2 + _impl(new Impl(input, Schema(input.getVersion())))
    130 e1aa105a + {
    131 f1760fcb + if (shareAliasMap) {
    132 f1760fcb + editOutputSchema().setAliasMap(input.getAliasMap());
    133 f1760fcb + }
    134 e1aa105a + }
    135 56df42d2 +
    SchemaMapper & SchemaMapper::operator=(SchemaMapper const & other) { boost::scoped_ptr tmp(new Impl(*other._impl)); _impl.swap(tmp); return *this; } template Key SchemaMapper::addMapping(Key const & inputKey, bool doReplace) { typename Impl::KeyPairMap::iterator i = std::find_if( _impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual(inputKey) ); Field inputField = _impl->_input.find(inputKey).field; if (i != _impl->_map.end()) { Key const & outputKey = boost::get< std::pair< Key, Key > >(*i).second; _impl->_output.replaceField(outputKey, inputField); return outputKey; } else { Key outputKey = _impl->_output.addField(inputField, doReplace); _impl->_map.insert(i, std::make_pair(inputKey, outputKey)); return outputKey; } } template Key SchemaMapper::addMapping(Key const & inputKey, Field const & field, bool doReplace) { typename Impl::KeyPairMap::iterator i = std::find_if( _impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual(inputKey) ); if (i != _impl->_map.end()) { Key const & outputKey = boost::get< std::pair< Key, Key > >(*i).second; _impl->_output.replaceField(outputKey, field); return outputKey; } else { Key outputKey = _impl->_output.addField(field, doReplace); _impl->_map.insert(i, std::make_pair(inputKey, outputKey)); return outputKey; } } template Key SchemaMapper::addMapping(Key const & inputKey, std::string const & outputName, bool doReplace) { typename Impl::KeyPairMap::iterator i = std::find_if( _impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual(inputKey) ); if (i != _impl->_map.end()) { Key const & outputKey = boost::get< std::pair< Key, Key > >(*i).second; Field field = _impl->_output.find(outputKey).field; field = field.copyRenamed(outputName); _impl->_output.replaceField(outputKey, field); return outputKey; } else { Field inputField = _impl->_input.find(inputKey).field; Field outputField = inputField.copyRenamed(outputName); Key outputKey = _impl->_output.addField(outputField, doReplace); _impl->_map.insert(i, std::make_pair(inputKey, outputKey)); return outputKey; } } void SchemaMapper::addMinimalSchema(Schema const & minimal, bool doMap) { if (getOutputSchema().getFieldCount() > 0) { throw LSST_EXCEPT(
    196 6dcc851a - pex::exceptions::LogicErrorException,
    ? ---------
    204 21597d88 + pex::exceptions::LogicError,
    "Must add minimal schema to mapper before adding any other fields" ); } MapMinimalSchema f(this, doMap); minimal.forEach(f); } SchemaMapper SchemaMapper::removeMinimalSchema(Schema const & input, Schema const & minimal) { SchemaMapper mapper(input); RemoveMinimalSchema f(&mapper, minimal); input.forEach(boost::ref(f)); return mapper; } void SchemaMapper::invert() { std::swap(_impl->_input, _impl->_output); std::for_each(_impl->_map.begin(), _impl->_map.end(), SwapKeyPair()); } template bool SchemaMapper::isMapped(Key const & inputKey) const { return std::count_if( _impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual(inputKey) ); } template Key SchemaMapper::getMapping(Key const & inputKey) const { typename Impl::KeyPairMap::iterator i = std::find_if( _impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual(inputKey) ); if (i == _impl->_map.end()) { throw LSST_EXCEPT(
    234 8f7cd2c5 - lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    242 21597d88 + lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ "Input Key is not mapped." ); } return boost::get< std::pair< Key, Key > >(*i).second; } std::vector SchemaMapper::join( std::vector const & inputs, std::vector const & prefixes ) { std::size_t const size = inputs.size(); if (!prefixes.empty() && prefixes.size() != inputs.size()) { throw LSST_EXCEPT(
    248 38ad08ad - pex::exceptions::LengthErrorException,
    ? ---------
    256 21597d88 + pex::exceptions::LengthError,
    (boost::format("prefix vector size (%d) must be the same as input vector size (%d)") % prefixes.size() % inputs.size()).str() ); } std::vector result; for (std::size_t i = 0; i < size; ++i) { result.push_back(SchemaMapper(inputs[i])); } for (std::size_t i = 0; i < size; ++i) { for (std::size_t j = 0; j < size; ++j) { if (i == j) { AddMapped functor(&result[j]); if (!prefixes.empty()) functor.prefix = prefixes[i]; inputs[i].forEach(functor); } else { AddUnmapped functor(&result[j]); if (!prefixes.empty()) functor.prefix = prefixes[i]; inputs[i].forEach(functor); } } } return result; } //----- Explicit instantiation ------------------------------------------------------------------------------ #define INSTANTIATE_LAYOUTMAPPER(r, data, elem) \ template Key< elem > SchemaMapper::addOutputField(Field< elem > const &, bool); \ template Key< elem > SchemaMapper::addMapping(Key< elem > const &, bool); \ template Key< elem > SchemaMapper::addMapping(Key< elem > const &, Field< elem > const &, bool); \ template Key< elem > SchemaMapper::addMapping(Key< elem > const &, std::string const &, bool); \ template bool SchemaMapper::isMapped(Key< elem > const &) const; \ template Key< elem > SchemaMapper::getMapping(Key< elem > const &) const; BOOST_PP_SEQ_FOR_EACH( INSTANTIATE_LAYOUTMAPPER, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_FIELD_TYPE_N, AFW_TABLE_FIELD_TYPE_TUPLE) ) }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0315d7db

    commit 0315d7db48fa755fdd268ecaa357a8e00c908363
    Author: Jim Bosch 
    Date:   Fri Sep 7 17:06:10 2012 -0400
    
        Allow SchemaMapper to add a minimal schema without mapping it (#2308).
    

    38ad08ad

    commit 38ad08ad2101e9cc2f59a107b39c5baad77c1c82
    Author: Jim Bosch 
    Date:   Thu Feb 28 12:52:12 2013 +0900
    
        Minor fixes to reflect code review for #2467.
        
        Removed trailing whitespace.
        Renamed ExposureCatalog::findContains to subsetContaining.
        Miscellaneous doc fixes.
        Added check on input sizes in SchemaMapper::join.
        OutputArchive::put overloads needed to forward permissive flag when delegating.
    

    8f7cd2c5

    commit 8f7cd2c59916e119aea9a5d20be9ae8b8bc7ddc7
    Author: Jim Bosch 
    Date:   Tue Nov 29 18:55:25 2011 -0500
    
        cleaned up Layout and added LayoutMapper
    

    6dcc851a

    commit 6dcc851a5bf7d8db0c36463e4fabd1f9bd097933
    Author: Jim Bosch 
    Date:   Thu Jun 14 13:34:03 2012 -0400
    
        Add method to SchemaMapper to add a "minimal schema" whose keys (and hence order) must be preserved).
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    56df42d2

    commit 56df42d2bb5dd4ebec2e5c67b0d16a137bb1dee2
    Author: Jim Bosch 
    Date:   Wed Aug 20 13:27:23 2014 -0400
    
        Add constructors to Schema and SchemaMapper to set version immediately.
    

    f1760fcb

    commit f1760fcb7952e5dbf1baf526b40e502027f30491
    Author: Jim Bosch 
    Date:   Tue Apr 14 19:09:13 2015 -0400
    
        Make transfer of aliases in SchemaMapper optional.
        
        The previous change to always transfer aliases in SchemaMapper
        broke existing code; this change reverts to the original behavior,
        with an easy option for to transfer aliases if desired (which is now
        used by SourceTable and ExposureTable).
    

    e1aa105a

    commit e1aa105ab8031359ba0a56c11573899780a6834a
    Author: Jim Bosch 
    Date:   Tue Apr 7 19:08:28 2015 -0400
    
        Transfer aliases when initializing SchemaMapper.
    

    Return to list

    src/geom/Box.cc

    Diff:

    1 a6d55f08 - /*
    ? -
    1 778eee48 + /*
    * LSST Data Management System
    3 a6d55f08 - * Copyright 2008, 2009, 2010 LSST Corporation.
    ? ^^^^^^^^ ^
    3 778eee48 + * Copyright 2008-2014 LSST Corporation.
    ? ^ ^
    4 a6d55f08 - *
    ? -
    4 778eee48 + *
    * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
    12 a6d55f08 - *
    ? -
    12 778eee48 + *
    * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
    17 a6d55f08 - *
    ? -
    17 778eee48 + *
    18 a6d55f08 - * You should have received a copy of the LSST License Statement and
    ? -
    18 778eee48 + * You should have received a copy of the LSST License Statement and
    19 a6d55f08 - * the GNU General Public License along with this program. If not,
    ? -
    19 778eee48 + * the GNU General Public License along with this program. If not,
    * see . */
    22 a6d55f08 -
    22 778eee48 +
    #include #include #include "lsst/utils/ieee.h" #include "lsst/afw/geom/Box.h" namespace geom = lsst::afw::geom;
    31 0b7ec4be - /**
    32 b7f6a102 - * @brief Construct a box from its minimum and maximum points.
    33 0b7ec4be - *
    34 a8e2a7e9 - * @param[in] minimum Minimum (lower left) coordinate (inclusive).
    35 a8e2a7e9 - * @param[in] maximum Maximum (upper right) coordinate (inclusive).
    36 a8e2a7e9 - * @param[in] invert If true (default), swap the minimum and maximum coordinates if
    37 0b7ec4be - * minimum > maximum instead of creating an empty box.
    38 0b7ec4be - */
    geom::Box2I::Box2I(Point2I const & minimum, Point2I const & maximum, bool invert) : _minimum(minimum), _dimensions(maximum - minimum) { for (int n=0; n<2; ++n) { if (_dimensions[n] < 0) { if (invert) { _minimum[n] += _dimensions[n]; _dimensions[n] = -_dimensions[n]; } else { *this = Box2I(); return; } } } _dimensions += Extent2I(1); }
    56 0b7ec4be - /**
    57 0b7ec4be - * @brief Construct a box from its minimum point and dimensions.
    58 0b7ec4be - *
    59 a8e2a7e9 - * @param[in] minimum Minimum (lower left) coordinate.
    60 a8e2a7e9 - * @param[in] dimensions Box dimensions. If either dimension coordinate is 0, the box will be empty.
    61 a8e2a7e9 - * @param[in] invert If true (default), invert any negative dimensions instead of creating
    62 0b7ec4be - * an empty box.
    63 0b7ec4be - */
    geom::Box2I::Box2I(Point2I const & minimum, Extent2I const & dimensions, bool invert) : _minimum(minimum), _dimensions(dimensions) { for (int n=0; n<2; ++n) { if (_dimensions[n] == 0) { *this = Box2I(); return; } else if (_dimensions[n] < 0) { if (invert) { _minimum[n] += (_dimensions[n] + 1); _dimensions[n] = -_dimensions[n]; } else { *this = Box2I(); return; } } } if (!isEmpty() && any(getMin().gt(getMax()))) { throw LSST_EXCEPT(
    83 b47297e2 - pex::exceptions::OverflowErrorException,
    ? ---------
    67 21597d88 + pex::exceptions::OverflowError,
    "Box dimensions too large; integer overflow detected." ); } }
    89 0b7ec4be - /**
    90 0b7ec4be - * @brief Construct an integer box from a floating-point box.
    91 0b7ec4be - *
    92 0b7ec4be - * Floating-point to integer box conversion is based on the concept that a pixel
    93 0b7ec4be - * is not an infinitesimal point but rather a square of unit size centered on
    94 0b7ec4be - * integer-valued coordinates. Converting a floating-point box to an integer box
    95 0b7ec4be - * thus requires a choice on how to handle pixels which are only partially contained
    96 0b7ec4be - * by the input floating-point box.
    97 0b7ec4be - *
    98 a8e2a7e9 - * @param[in] other A floating-point box to convert.
    99 a8e2a7e9 - * @param[in] edgeHandling If EXPAND, the integer box will contain any pixels that
    100 0b7ec4be - * overlap the floating-point box. If SHRINK, the integer
    101 0b7ec4be - * box will contain only pixels completely contained by
    102 0b7ec4be - * the floating-point box.
    103 0b7ec4be - */
    geom::Box2I::Box2I(Box2D const & other, EdgeHandlingEnum edgeHandling) : _minimum(), _dimensions() { if (other.isEmpty()) { *this = Box2I(); return; } if (!utils::isfinite(other.getMinX()) || !utils::isfinite(other.getMinY()) || !utils::isfinite(other.getMaxX()) || !utils::isfinite(other.getMaxY())) { throw LSST_EXCEPT(
    112 b47297e2 - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    81 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Cannot convert non-finite Box2D to Box2I" ); } Point2D fpMin(other.getMin() + Extent2D(0.5)); Point2D fpMax(other.getMax() - Extent2D(0.5)); switch (edgeHandling) { case EXPAND: for (int n=0; n<2; ++n) { _minimum[n] = static_cast(std::floor(fpMin[n])); _dimensions[n] = static_cast(std::ceil(fpMax[n])) + 1 - _minimum[n]; } break; case SHRINK: for (int n=0; n<2; ++n) { _minimum[n] = static_cast(std::ceil(fpMin[n])); _dimensions[n] = static_cast(std::floor(fpMax[n])) + 1 - _minimum[n]; } break; } }
    134 ee3397a4 - /// @brief Return slices to extract the box's region from an ndarray::Array.
    ndarray::View< boost::fusion::vector2 > geom::Box2I::getSlices() const { return ndarray::view(getBeginY(), getEndY())(getBeginX(), getEndX()); }
    140 0b7ec4be - /// \brief Return true if the box contains the point.
    bool geom::Box2I::contains(Point2I const & point) const { return all(point.ge(this->getMin())) && all(point.le(this->getMax())); }
    145 0b7ec4be - /**
    146 0b7ec4be - * \brief Return true if all points contained by other are also contained by this.
    147 0b7ec4be - *
    148 0b7ec4be - * An empty box is contained by every other box, including other empty boxes.
    149 0b7ec4be - */
    bool geom::Box2I::contains(Box2I const & other) const {
    151 0b7ec4be - return other.isEmpty() ||
    ? -
    113 778eee48 + return other.isEmpty() ||
    (all(other.getMin().ge(this->getMin())) && all(other.getMax().le(this->getMax()))); }
    155 0b7ec4be - /**
    156 0b7ec4be - * \brief Return true if any points in other are also in this.
    157 0b7ec4be - *
    158 0b7ec4be - * Any overlap operation involving an empty box returns false.
    159 0b7ec4be - */
    bool geom::Box2I::overlaps(Box2I const & other) const { return !(
    162 0b7ec4be - other.isEmpty() || this->isEmpty()
    ? -
    119 778eee48 + other.isEmpty() || this->isEmpty()
    163 c9a1df4f - || any(other.getMax().lt(this->getMin()))
    ? -
    120 778eee48 + || any(other.getMax().lt(this->getMin()))
    || any(other.getMin().gt(this->getMax())) ); }
    168 0b7ec4be - /**
    169 0b7ec4be - * \brief Increase the size of the box by the given buffer amount in all directions.
    170 0b7ec4be - *
    171 0b7ec4be - * If a negative buffer is passed and the final size of the box is less than or
    172 0b7ec4be - * equal to zero, the box will be made empty.
    173 0b7ec4be - */
    void geom::Box2I::grow(Extent2I const & buffer) { if (isEmpty()) return; // should we throw an exception here instead of a no-op? _minimum -= buffer; _dimensions += buffer * 2; if (any(_dimensions.le(0))) *this = Box2I(); }
    181 b7f6a102 - /// \brief Shift the position of the box by the given offset.
    void geom::Box2I::shift(Extent2I const & offset) { if (isEmpty()) return; // should we throw an exception here instead of a no-op? _minimum += offset; }
    187 83689a40 - /// \brief Flip a bounding box about the y-axis given a parent box of extent (pextent).
    void geom::Box2I::flipLR(int xextent) { if (isEmpty()) return; // should we throw an exception here instead of a no-op? // Apply flip about y-axis assumine parent coordinate system _minimum[0] = xextent - (_minimum[0] + _dimensions[0]); // _dimensions should remain unchanged }
    143 778eee48 +
    194 83689a40 - //
    195 83689a40 - /// \brief Flip a bounding box about the x-axis given a parent box of extent (pextent).
    void geom::Box2I::flipTB(int yextent) { if (isEmpty()) return; // should we throw an exception here instead of a no-op? // Apply flip about y-axis assumine parent coordinate system _minimum[1] = yextent - (_minimum[1] + _dimensions[1]); // _dimensions should remain unchanged }
    203 0b7ec4be - /// \brief Expand this to ensure that this->contains(point).
    void geom::Box2I::include(Point2I const & point) { if (isEmpty()) { _minimum = point; _dimensions = Extent2I(1); return; } Point2I maximum(getMax()); for (int n=0; n<2; ++n) { if (point[n] < _minimum[n]) { _minimum[n] = point[n]; } else if (point[n] > maximum[n]) { maximum[n] = point[n]; } } _dimensions = Extent2I(1) + maximum - _minimum; }
    221 0b7ec4be - /// \brief Expand this to ensure that this->contains(other).
    void geom::Box2I::include(Box2I const & other) { if (other.isEmpty()) return; if (this->isEmpty()) { *this = other; return; } Point2I maximum(getMax()); Point2I const & otherMin = other.getMin(); Point2I const otherMax = other.getMax(); for (int n=0; n<2; ++n) { if (otherMin[n] < _minimum[n]) { _minimum[n] = otherMin[n];
    234 95d17565 - }
    ? -
    180 778eee48 + }
    if (otherMax[n] > maximum[n]) { maximum[n] = otherMax[n]; } }
    239 25e61ab4 - _dimensions = Extent2I(1) + maximum - _minimum;
    ? ----
    185 778eee48 + _dimensions = Extent2I(1) + maximum - _minimum;
    }
    242 0b7ec4be - /// \brief Shrink this to ensure that other.contains(*this).
    void geom::Box2I::clip(Box2I const & other) { if (isEmpty()) return; if (other.isEmpty()) { *this = Box2I(); return; } Point2I maximum(getMax()); Point2I const & otherMin = other.getMin(); Point2I const otherMax = other.getMax(); for (int n=0; n<2; ++n) { if (otherMin[n] > _minimum[n]) { _minimum[n] = otherMin[n];
    255 95d17565 - }
    ? -
    200 778eee48 + }
    if (otherMax[n] < maximum[n]) { maximum[n] = otherMax[n]; } } if (any(maximum.lt(_minimum))) { *this = Box2I(); return;
    263 0b7ec4be - }
    208 778eee48 + }
    264 25e61ab4 - _dimensions = Extent2I(1) + maximum - _minimum;
    ? ----
    209 778eee48 + _dimensions = Extent2I(1) + maximum - _minimum;
    }
    267 a8e2a7e9 - /**
    268 a8e2a7e9 - * \brief Compare two boxes for equality.
    269 a8e2a7e9 - *
    270 a8e2a7e9 - * All empty boxes are equal.
    271 a8e2a7e9 - */
    bool geom::Box2I::operator==(Box2I const & other) const { return other._minimum == this->_minimum && other._dimensions == this->_dimensions; }
    276 a8e2a7e9 - /**
    277 a8e2a7e9 - * \brief Compare two boxes for equality.
    278 a8e2a7e9 - *
    279 a8e2a7e9 - * All empty boxes are equal.
    280 a8e2a7e9 - */
    bool geom::Box2I::operator!=(Box2I const & other) const { return other._minimum != this->_minimum || other._dimensions != this->_dimensions; }
    220 7911ee94 + std::vector geom::Box2I::getCorners() const {
    221 7911ee94 + std::vector retVec;
    222 7911ee94 + retVec.push_back(getMin());
    223 7911ee94 + retVec.push_back(geom::Point2I(getMaxX(), getMinY()));
    224 7911ee94 + retVec.push_back(getMax());
    225 7911ee94 + retVec.push_back(geom::Point2I(getMinX(), getMaxY()));
    226 7911ee94 + return retVec;
    227 7911ee94 + }
    228 7911ee94 +
    double const geom::Box2D::EPSILON = std::numeric_limits::epsilon()*2; double const geom::Box2D::INVALID = std::numeric_limits::quiet_NaN();
    289 b7f6a102 - /// \brief Construct an empty box.
    geom::Box2D::Box2D() : _minimum(INVALID), _maximum(INVALID) {}
    292 b7f6a102 - /**
    293 b7f6a102 - * @brief Construct a box from its minimum and maximum points.
    294 b7f6a102 - *
    295 b7f6a102 - * If any(minimum == maximum), the box will always be empty (even if invert==true).
    296 b7f6a102 - *
    297 a8e2a7e9 - * @param[in] minimum Minimum (lower left) coordinate (inclusive).
    298 a8e2a7e9 - * @param[in] maximum Maximum (upper right) coordinate (exclusive).
    299 a8e2a7e9 - * @param[in] invert If true (default), swap the minimum and maximum coordinates if
    300 b7f6a102 - * minimum > maximum instead of creating an empty box.
    301 b7f6a102 - */
    geom::Box2D::Box2D(Point2D const & minimum, Point2D const & maximum, bool invert) : _minimum(minimum), _maximum(maximum) { for (int n=0; n<2; ++n) { if (_minimum[n] == _maximum[n]) { *this = Box2D(); return; } else if (_minimum[n] > _maximum[n]) { if (invert) { std::swap(_minimum[n],_maximum[n]); } else { *this = Box2D(); return; } } } }
    320 b7f6a102 - /**
    321 b7f6a102 - * @brief Construct a box from its minimum point and dimensions.
    322 b7f6a102 - *
    323 a8e2a7e9 - * @param[in] minimum Minimum (lower left) coordinate (inclusive).
    324 a8e2a7e9 - * @param[in] dimensions Box dimensions. If either dimension coordinate is 0, the box will be empty.
    325 a8e2a7e9 - * @param[in] invert If true (default), invert any negative dimensions instead of creating
    326 b7f6a102 - * an empty box.
    327 b7f6a102 - */
    328 25e61ab4 - geom::Box2D::Box2D(Point2D const & minimum, Extent2D const & dimensions, bool invert) :
    ? -
    253 778eee48 + geom::Box2D::Box2D(Point2D const & minimum, Extent2D const & dimensions, bool invert) :
    _minimum(minimum), _maximum(minimum + dimensions) { for (int n=0; n<2; ++n) { if (_minimum[n] == _maximum[n]) { *this = Box2D(); return; } else if (_minimum[n] > _maximum[n]) { if (invert) { std::swap(_minimum[n],_maximum[n]); } else { *this = Box2D(); return; } } } }
    346 b7f6a102 - /**
    347 b7f6a102 - * @brief Construct a floating-point box from an integer box.
    348 b7f6a102 - *
    349 b7f6a102 - * Integer to floating-point box conversion is based on the concept that a pixel
    350 b7f6a102 - * is not an infinitesimal point but rather a square of unit size centered on
    351 b7f6a102 - * integer-valued coordinates. While the output floating-point box thus has
    352 b7f6a102 - * the same dimensions as the input integer box, its minimum/maximum coordinates
    353 b7f6a102 - * are 0.5 smaller/greater.
    354 b7f6a102 - */
    geom::Box2D::Box2D(Box2I const & other) : _minimum(Point2D(other.getMin()) - Extent2D(0.5)), _maximum(Point2D(other.getMax()) + Extent2D(0.5)) { if (other.isEmpty()) *this = Box2D(); }
    362 b7f6a102 - /// \brief Return true if the box contains the point.
    bool geom::Box2D::contains(Point2D const & point) const { return all(point.ge(this->getMin())) && all(point.lt(this->getMax())); }
    367 b7f6a102 - /**
    368 b7f6a102 - * \brief Return true if all points contained by other are also contained by this.
    369 b7f6a102 - *
    370 b7f6a102 - * An empty box is contained by every other box, including other empty boxes.
    371 b7f6a102 - */
    bool geom::Box2D::contains(Box2D const & other) const {
    373 b7f6a102 - return other.isEmpty() ||
    ? -
    283 778eee48 + return other.isEmpty() ||
    (all(other.getMin().ge(this->getMin())) && all(other.getMax().le(this->getMax()))); }
    377 b7f6a102 - /**
    378 b7f6a102 - * \brief Return true if any points in other are also in this.
    379 b7f6a102 - *
    380 b7f6a102 - * Any overlap operation involving an empty box returns false.
    381 b7f6a102 - */
    bool geom::Box2D::overlaps(Box2D const & other) const { return !(
    384 b7f6a102 - other.isEmpty() || this->isEmpty()
    ? -
    289 778eee48 + other.isEmpty() || this->isEmpty()
    385 c9a1df4f - || any(other.getMax().le(this->getMin()))
    ? -
    290 778eee48 + || any(other.getMax().le(this->getMin()))
    || any(other.getMin().ge(this->getMax())) ); }
    390 b7f6a102 - /**
    391 b7f6a102 - * \brief Increase the size of the box by the given buffer amount in all directions.
    392 b7f6a102 - *
    393 b7f6a102 - * If a negative buffer is passed and the final size of the box is less than or
    394 b7f6a102 - * equal to zero, the box will be made empty.
    395 b7f6a102 - */
    void geom::Box2D::grow(Extent2D const & buffer) { if (isEmpty()) return; // should we throw an exception here instead of a no-op? _minimum -= buffer; _maximum += buffer; if (any(_minimum.ge(_maximum))) *this = Box2D(); }
    403 b7f6a102 - /// \brief Shift the position of the box by the given offset.
    void geom::Box2D::shift(Extent2D const & offset) { if (isEmpty()) return; // should we throw an exception here instead of a no-op? _minimum += offset; _maximum += offset; }
    410 83689a40 - /// \brief Flip a bounding box about the y-axis given a parent box of extent (pextent).
    void geom::Box2D::flipLR(float xextent) { if (isEmpty()) return; // should we throw an exception here instead of a no-op? // Swap min and max values for x dimension _minimum[0] += _maximum[0]; _maximum[0] = _minimum[0] - _maximum[0]; _minimum[0] -= _maximum[0]; // Apply flip assuming coordinate system of parent. _minimum[0] = xextent - _minimum[0]; _maximum[0] = xextent - _maximum[0]; // _dimensions should remain unchanged }
    423 83689a40 - /// \brief Flip a bounding box about the x-axis given a parent box of extent (pextent).
    void geom::Box2D::flipTB(float yextent) { if (isEmpty()) return; // should we throw an exception here instead of a no-op? // Swap min and max values for y dimension _minimum[1] += _maximum[1]; _maximum[1] = _minimum[1] - _maximum[1]; _minimum[1] -= _maximum[1]; // Apply flip assuming coordinate system of parent. _minimum[1] = yextent - _minimum[1]; _maximum[1] = yextent - _maximum[1]; // _dimensions should remain unchanged }
    436 b7f6a102 - /**
    437 b7f6a102 - * \brief Expand this to ensure that this->contains(point).
    438 b7f6a102 - *
    439 b7f6a102 - * If the point sets a new maximum value for the box, the maximum coordinate will
    440 efe63046 - * be adjusted to ensure the point is actually contained
    441 b7f6a102 - * by the box instead of sitting on its exclusive upper edge.
    442 b7f6a102 - */
    void geom::Box2D::include(Point2D const & point) { if (isEmpty()) { _minimum = point; _maximum = point; _tweakMax(0); _tweakMax(1); return; } for (int n=0; n<2; ++n) { if (point[n] < _minimum[n]) { _minimum[n] = point[n]; } else if (point[n] >= _maximum[n]) { _maximum[n] = point[n]; _tweakMax(n); } } }
    461 b7f6a102 - /// \brief Expand this to ensure that this->contains(other).
    void geom::Box2D::include(Box2D const & other) { if (other.isEmpty()) return; if (this->isEmpty()) { *this = other; return; } Point2D const & otherMin = other.getMin(); Point2D const & otherMax = other.getMax(); for (int n=0; n<2; ++n) { if (otherMin[n] < _minimum[n]) { _minimum[n] = otherMin[n];
    473 95d17565 - }
    ? -
    361 778eee48 + }
    if (otherMax[n] > _maximum[n]) { _maximum[n] = otherMax[n]; } } }
    480 b7f6a102 - /// \brief Shrink this to ensure that other.contains(*this).
    void geom::Box2D::clip(Box2D const & other) { if (isEmpty()) return; if (other.isEmpty()) { *this = Box2D(); return; } Point2D const & otherMin = other.getMin(); Point2D const & otherMax = other.getMax(); for (int n=0; n<2; ++n) { if (otherMin[n] > _minimum[n]) { _minimum[n] = otherMin[n];
    492 95d17565 - }
    ? -
    379 778eee48 + }
    if (otherMax[n] < _maximum[n]) { _maximum[n] = otherMax[n]; } } if (any(_maximum.le(_minimum))) { *this = Box2D(); return;
    500 b7f6a102 - }
    387 778eee48 + }
    }
    503 a8e2a7e9 - /**
    504 a8e2a7e9 - * \brief Compare two boxes for equality.
    505 a8e2a7e9 - *
    506 a8e2a7e9 - * All empty boxes are equal.
    507 a8e2a7e9 - */
    bool geom::Box2D::operator==(Box2D const & other) const {
    509 a8e2a7e9 - return (other.isEmpty() && this->isEmpty()) ||
    ? -
    391 778eee48 + return (other.isEmpty() && this->isEmpty()) ||
    (other._minimum == this->_minimum && other._maximum == this->_maximum); }
    513 a8e2a7e9 - /**
    514 a8e2a7e9 - * \brief Compare two boxes for equality.
    515 a8e2a7e9 - *
    516 a8e2a7e9 - * All empty boxes are equal.
    517 a8e2a7e9 - */
    bool geom::Box2D::operator!=(Box2D const & other) const { return !(other.isEmpty() && other.isEmpty()) && (other._minimum != this->_minimum || other._maximum != this->_maximum); }
    400 7911ee94 + std::vector geom::Box2D::getCorners() const {
    401 7911ee94 + std::vector retVec;
    402 7911ee94 + retVec.push_back(getMin());
    403 7911ee94 + retVec.push_back(geom::Point2D(getMaxX(), getMinY()));
    404 7911ee94 + retVec.push_back(getMax());
    405 7911ee94 + retVec.push_back(geom::Point2D(getMinX(), getMaxY()));
    406 7911ee94 + return retVec;
    407 7911ee94 + }
    408 7911ee94 +
    std::ostream & geom::operator<<(std::ostream & os, geom::Box2I const & box) { if (box.isEmpty()) return os << "Box2I()"; return os << "Box2I(Point2I" << box.getMin() << ", Extent2I" << box.getDimensions() << ")"; } std::ostream & geom::operator<<(std::ostream & os, geom::Box2D const & box) { if (box.isEmpty()) return os << "Box2D()"; return os << "Box2D(Point2D" << box.getMin() << ", Extent2D" << box.getDimensions() << ")"; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b47297e2

    commit b47297e251e0a6c5a299e75c23da267d2e4f3406
    Author: Jim Bosch 
    Date:   Sat Mar 30 17:26:05 2013 -0400
    
        Add overflow and finiteness detection to Box2I constructors (#2769).
    

    a8e2a7e9

    commit a8e2a7e9666f30c2384ae6bb3557181f65684db7
    Author: jbosch 
    Date:   Mon Dec 21 23:37:41 2009 +0000
    
        afw/#1095 - swig wrappers, some tests for BoxI and BoxD.
    

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    ee3397a4

    commit ee3397a48c333ed8b03db3b7f20df16601de938a
    Author: jbosch 
    Date:   Fri Feb 11 03:15:03 2011 +0000
    
        afw #1556 - added Box2I::getSlices() to support ndarray/numpy indexing with boxes
    

    0b7ec4be

    commit 0b7ec4be44da7c523ad2dc4b39e3e3908c154805
    Author: jbosch 
    Date:   Fri Dec 18 09:41:20 2009 +0000
    
        afw/#1095 - added header for new boxes, implementation for BoxI.
    

    c9a1df4f

    commit c9a1df4f56c690e10eab1bc57499b806b454b7b4
    Author: jbosch 
    Date:   Thu Jan 7 00:06:50 2010 +0000
    
        afw/1095 - changes to coordinate API: renamed comparison operators to functions with Fortran-like names, added free-function constructors.
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    83689a40

    commit 83689a402f5eb3e42eb8eb17b18dd8ea5dd6ae53
    Author: krughoff 
    Date:   Thu Sep 29 20:52:34 2011 +0000
    
        changes for ticket #1767
    

    95d17565

    commit 95d1756551e9b95838e816f351f3f425a06cfc47
    Author: dubcovsky 
    Date:   Wed Mar 17 22:02:57 2010 +0000
    
        #1169 merged to trunk
    

    b7f6a102

    commit b7f6a1025c4a8de7ab1f9f9333cec2dd5f2d884e
    Author: jbosch 
    Date:   Sat Dec 19 01:15:49 2009 +0000
    
        afw/#1095 - nominally finished c++ implementation for BoxD.
    

    efe63046

    commit efe63046abc195ae94aa09a94c0d10d26a895229
    Author: jbosch 
    Date:   Mon Dec 28 21:09:52 2009 +0000
    
        afw/#1095 - tests for Box done
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    778eee48

    commit 778eee48a3b8c63179e448972e5d78c64406589f
    Author: Jim Bosch 
    Date:   Wed Aug 20 13:42:54 2014 -0400
    
        Move Box2I and Box2D Doxygen comments to header.
        
        Also removed trailing whitespace and updated copyright dates.
    

    7911ee94

    commit 7911ee946edad9f1f95b38049679799efe317cd6
    Author: Russell Owen 
    Date:   Thu Feb 20 13:47:43 2014 -0800
    
        Added getCorners method to Box2D and Box2I C++ (and removed Python-only version).
        Updated Detector.cc to use it.
    

    Return to list

    tests/scaledPlus.py

    Diff:

    1 af8983bc - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . #
    25 af8983bc - import math
    import unittest
    28 af8983bc - import numpy
    29 af8983bc -
    import lsst.utils.tests as utilsTests
    31 af8983bc - import lsst.pex.exceptions as pexExcept
    import lsst.pex.logging as pexLog import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.image.testUtils as imTestUtils VERBOSITY = 0 # increase to see trace pexLog.Debug("lsst.afw", VERBOSITY) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ScaledPlus(unittest.TestCase): def setUp(self): self.random = afwMath.Random() self.imWidth = 200 self.imHeight = 200 self.maskedImage0 = afwImage.MaskedImageF(afwGeom.Extent2I(self.imWidth, self.imHeight)) afwMath.randomUniformImage(self.maskedImage0.getImage(), self.random) afwMath.randomUniformImage(self.maskedImage0.getVariance(), self.random) # afwMath.randomUniformImage(self.maskedImage0.getMask(), self.random) self.maskedImage1 = afwImage.MaskedImageF(afwGeom.Extent2I(self.imWidth, self.imHeight)) afwMath.randomUniformImage(self.maskedImage1.getImage(), self.random) afwMath.randomUniformImage(self.maskedImage1.getVariance(), self.random) # afwMath.randomUniformImage(self.maskedImage1.getMask(), self.random) def tearDown(self): self.random = None self.maskedImage0 = None self.maskedImage1 = None def runScaledAddTest(self, coeff0, coeff1): """Run one test of scaledPlus Inputs: - coeff0: coefficient of image 0 - coeff1: coefficient of image 1 """ im0ArrSet = self.maskedImage0.getArrays() im1ArrSet = self.maskedImage1.getArrays() desMaskedImage = afwImage.MaskedImageF(self.maskedImage0.getDimensions()) desMaskedImage <<= self.maskedImage0 desMaskedImage *= coeff0 desMaskedImage.scaledPlus(coeff1, self.maskedImage1) desImArrSet = desMaskedImage.getArrays() actMaskedImage = afwImage.MaskedImageF(afwGeom.Extent2I(self.imWidth, self.imHeight)) afwMath.randomUniformImage(actMaskedImage.getImage(), self.random) afwMath.randomUniformImage(actMaskedImage.getVariance(), self.random) afwMath.scaledPlus(actMaskedImage, coeff0, self.maskedImage0, coeff1, self.maskedImage1) actImArrSet = actMaskedImage.getArrays() actImage = afwImage.ImageF(afwGeom.Extent2I(self.imWidth, self.imHeight)) afwMath.randomUniformImage(actImage, self.random) afwMath.scaledPlus(actImage, coeff0, self.maskedImage0.getImage(), coeff1, self.maskedImage1.getImage()) actImArr = actImage.getArray() errStr = imTestUtils.imagesDiffer(actImArr, desImArrSet[0]) if errStr: self.fail("scaledPlus failed in images; coeff0=%s, coeff1=%s:\n%s" % (coeff0, coeff1, errStr,)) errStr = imTestUtils.maskedImagesDiffer(actImArrSet, desImArrSet) if errStr: self.fail("scaledPlus failed on masked images; coeff0=%s, coeff1=%s:\n%s" % (coeff0, coeff1, errStr,)) def testScaledPlus(self): for coeff0 in (0.0, -0.1e-5, 0.1e-5, 1.0e3): for coeff1 in (0.0, 0.1e-5, -0.1e-5, 1.0e3): self.runScaledAddTest(coeff0, coeff1) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ScaledPlus) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(doExit=False): """Run the tests""" utilsTests.run(suite(), doExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    af8983bc

    commit af8983bcfdfc2c50cda426f396cce6977d5ca8e8
    Author: rowen 
    Date:   Wed May 12 22:37:53 2010 +0000
    
        swig afwMath.scaledPlus and add a unit test for it.
        Finish unit tests for interpolated convolution.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    python/lsst/afw/display/utils.py

    Diff:

                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    
                    ## \file
                    ## \brief Utilities to use with displaying images
                    
    
    26 533d26ca - from __future__ import with_statement
    26 bde0ab27 + from __future__ import absolute_import, division, print_function
    28 f065975e - import math
    import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom
    31 76134b7e - import lsst.afw.display.ds9 as ds9
    30 bde0ab27 +
    31 bde0ab27 + __all__ = (
    32 bde0ab27 + "Mosaic",
    33 bde0ab27 + "drawBBox", "drawFootprint", "drawCoaddInputs",
    34 bde0ab27 + )
    35 bde0ab27 +
    36 bde0ab27 + def _getDisplayFromDisplayOrFrame(display, frame=None):
    37 bde0ab27 + """!Return an afwDisplay.Display given either a display or a frame ID.
    38 bde0ab27 +
    39 bde0ab27 + If the two arguments are consistent, return the desired display; if they are not,
    40 bde0ab27 + raise a RuntimeError exception.
    41 bde0ab27 +
    42 bde0ab27 + If the desired display is None, return None rather than the default display"""
    43 bde0ab27 +
    44 bde0ab27 + import lsst.afw.display as afwDisplay # import locally to allow this file to be imported by __init__
    45 bde0ab27 +
    46 bde0ab27 + if display is None and frame is None:
    47 bde0ab27 + return None
    48 bde0ab27 +
    49 bde0ab27 + if frame:
    50 bde0ab27 + if display and display.frame != frame:
    51 bde0ab27 + raise RuntimeError("Please specify display *or* frame")
    52 bde0ab27 + display = afwDisplay.getDisplay(frame, create=True)
    53 bde0ab27 +
    54 bde0ab27 + return display
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class Mosaic(object): """A class to handle mosaics of one or more identically-sized images (or Masks or MaskedImages) E.g. m = Mosaic() m.setGutter(5) m.setBackground(10) m.setMode("square") # the default; other options are "x" or "y" mosaic = m.makeMosaic(im1, im2, im3) # build the mosaic
    67 bde0ab27 + display = afwDisplay.getDisplay()
    44 2eb9dac3 - ds9.mtv(mosaic) # display it
    ? ^
    68 bde0ab27 + display.mtv(mosaic) # display it
    ? + ^^^^
    45 5555e238 - m.drawLabels(["Label 1", "Label 2", "Label 3"]) # label the panels
    69 bde0ab27 + m.drawLabels(["Label 1", "Label 2", "Label 3"], display) # label the panels
    ? +++++++++ # alternative way to build a mosaic images = [im1, im2, im3] labels = ["Label 1", "Label 2", "Label 3"] mosaic = m.makeMosaic(images)
    52 5555e238 - ds9.mtv(mosaic)
    ? ^
    76 bde0ab27 + display.mtv(mosaic)
    ? + ^^^^
    53 5555e238 - m.drawLabels(labels)
    77 bde0ab27 + m.drawLabels(labels, display)
    ? +++++++++ # Yet another way to build a mosaic (no need to build the images/labels lists) for i in range(len(images)): m.append(images[i], labels[i])
    58 3530e042 - # You may optionally include a colour, e.g. ds9.YELLOW, as a third argument
    ? ^ ^
    82 bde0ab27 + # You may optionally include a colour, e.g. afwDisplay.YELLOW, as a third argument
    ? ^^^^^ ^^^^ mosaic = m.makeMosaic()
    61 5555e238 - ds9.mtv(mosaic)
    ? ^
    85 bde0ab27 + display.mtv(mosaic)
    ? + ^^^^
    62 5555e238 - m.drawLabels()
    86 bde0ab27 + m.drawLabels(display=display)
    87 bde0ab27 +
    88 bde0ab27 + Or simply:
    89 bde0ab27 + mosaic = m.makeMosaic(display=display)
    You can return the (ix, iy)th (or nth) bounding box (in pixels) with getBBox() """ def __init__(self, gutter=3, background=0, mode="square"): self.gutter = gutter # number of pixels between panels in a mosaic self.background = background # value in gutters self.setMode(mode) # mosaicing mode self.xsize = 0 # column size of panels self.ysize = 0 # row size of panels self.reset() def reset(self): """Reset the list of images to be mosaiced""" self.images = [] # images to mosaic together self.labels = [] # labels for images def append(self, image, label=None, ctype=None): """Add an image to the list of images to be mosaiced Set may be cleared with Mosaic.reset() Returns the index of this image (may be passed to getBBox()) """ if not self.xsize: self.xsize = image.getWidth() self.ysize = image.getHeight() self.images.append(image) self.labels.append((label, ctype)) return len(self.images)
    95 82bff8fb - def makeMosaic(self, images=None, frame=None, mode=None, background=None, title=""):
    ? ^^ ^^
    122 bde0ab27 + def makeMosaic(self, images=None, display=None, mode=None, background=None, title="", frame=None):
    ? ^^^^^ ^ ++++++++++++ """Return a mosaic of all the images provided; if none are specified, use the list accumulated with Mosaic.append(). Note that this mosaic is a patchwork of the input images; if you want to make a mosaic of a set images of the sky, you probably want to use the coadd code
    102 3c57f5d1 - If frame is specified, display it
    129 bde0ab27 + If display or frame (deprecated) is specified, display the mosaic
    """ if not images: images = self.images
    135 76134b7e + self.nImage = len(images)
    if self.nImage == 0: raise RuntimeError, "You must provide at least one image" self.xsize, self.ysize = 0, 0 for im in images: w, h = im.getWidth(), im.getHeight() if w > self.xsize: self.xsize = w if h > self.ysize: self.ysize = h if background is None: background = self.background if mode is None: mode = self.mode if mode == "square": nx, ny = 1, self.nImage while nx*im.getWidth() < ny*im.getHeight(): nx += 1
    128 148d4ecb - ny = int(self.nImage/nx)
    ? ---- -
    156 bde0ab27 + ny = self.nImage//nx
    ? + if nx*ny < self.nImage: ny += 1 if nx*ny < self.nImage: nx += 1 if nx > self.nImage: nx = self.nImage assert(nx*ny >= self.nImage) elif mode == "x": nx, ny = self.nImage, 1 elif mode == "y": nx, ny = 1, self.nImage elif isinstance(mode, int): nx = mode ny = self.nImage//nx if nx*ny < self.nImage: ny += 1 else: raise RuntimeError, ("Unknown mosaicing mode: %s" % mode) self.nx, self.ny = nx, ny mosaic = images[0].Factory( afwGeom.Extent2I(nx*self.xsize + (nx - 1)*self.gutter, ny*self.ysize + (ny - 1)*self.gutter) ) try: mosaic.set(self.background) except AttributeError: raise RuntimeError("Attempt to mosaic images of type %s which don't support set" % type(mosaic)) for i in range(len(images)): smosaic = mosaic.Factory(mosaic, self.getBBox(i%nx, i//nx), afwImage.LOCAL) im = images[i] if smosaic.getDimensions() != im.getDimensions(): # im is smaller than smosaic
    167 c9c89e06 - llc = afwGeom.Point2I((smosaic.getWidth() - im.getWidth())//2,
    ? -
    195 bde0ab27 + llc = afwGeom.PointI((smosaic.getWidth() - im.getWidth())//2,
    168 8ac39af5 - (smosaic.getHeight() - im.getHeight())//2)
    ? -
    196 bde0ab27 + (smosaic.getHeight() - im.getHeight())//2)
    smosaic = smosaic.Factory(smosaic, afwGeom.Box2I(llc, im.getDimensions()), afwImage.LOCAL) smosaic <<= im
    173 76134b7e - if frame is not None:
    201 bde0ab27 + display = _getDisplayFromDisplayOrFrame(display, frame)
    202 bde0ab27 + if display:
    174 c41be7b6 - ds9.mtv(mosaic, frame=frame, title=title)
    ? ^ -------------
    203 bde0ab27 + display.mtv(mosaic, title=title)
    ? + ^^^^ if images == self.images:
    177 3c57f5d1 - self.drawLabels(frame=frame)
    ? ^^ ^^ ^^ ^^
    206 bde0ab27 + self.drawLabels(display=display)
    ? ^^^^^ ^ ^^^^^ ^ return mosaic def setGutter(self, gutter): """Set the number of pixels between panels in a mosaic""" self.gutter = gutter def setBackground(self, background): """Set the value in the gutters""" self.background = background def setMode(self, mode): """Set mosaicing mode. Valid options: square Make mosaic as square as possible x Make mosaic one image high y Make mosaic one image wide """ if mode not in ("square", "x", "y"): raise RuntimeError, ("Unknown mosaicing mode: %s" % mode) self.mode = mode def getBBox(self, ix, iy=None): """Get the BBox for the nth or (ix, iy)the panel""" if iy is None:
    205 a7aa0c91 - ix, iy = ix % self.nx, ix/self.nx
    234 bde0ab27 + ix, iy = ix % self.nx, ix//self.nx
    ? +
    207 c9c89e06 - return afwGeom.Box2I(afwGeom.Point2I(ix*(self.xsize + self.gutter), iy*(self.ysize + self.gutter)),
    ? -
    236 bde0ab27 + return afwGeom.Box2I(afwGeom.PointI(ix*(self.xsize + self.gutter), iy*(self.ysize + self.gutter)),
    208 c9c89e06 - afwGeom.Extent2I(self.xsize, self.ysize))
    ? -
    237 bde0ab27 + afwGeom.ExtentI(self.xsize, self.ysize))
    ? +
    210 6c16535b - def drawLabels(self, labels=None, frame=None):
    239 bde0ab27 + def drawLabels(self, labels=None, display=None, frame=None):
    ? ++++++++++++++ """Draw the list labels at the corners of each panel. If labels is None, use the ones specified by Mosaic.append()""" if not labels: labels = self.labels if not labels: return if len(labels) != self.nImage: raise RuntimeError, ("You provided %d labels for %d panels" % (len(labels), self.nImage))
    252 bde0ab27 + display = _getDisplayFromDisplayOrFrame(display, frame)
    253 bde0ab27 + if not display:
    254 bde0ab27 + return
    255 bde0ab27 +
    223 4402095d - with ds9.Buffering():
    ? ^
    256 bde0ab27 + with display.Buffering():
    ? + ^^^^ for i in range(len(labels)): if labels[i]: label, ctype = labels[i], None try: label, ctype = label except: pass if not label: continue
    235 4402095d - ds9.dot(str(label), self.getBBox(i).getMinX(), self.getBBox(i).getMinY(),
    ? ^
    268 bde0ab27 + display.dot(str(label), self.getBBox(i).getMinX(), self.getBBox(i).getMinY(), ctype=ctype)
    ? + ^^^^ +++++++++++++
    236 4402095d - frame=frame, ctype=ctype)
    237 c369a8ad - @property
    238 c369a8ad - def nImage(self):
    239 c369a8ad - """Number of images"""
    240 c369a8ad - return len(self.images)
    242 1f2c9901 - def drawBBox(bbox, borderWidth=0.0, origin=None, frame=None, ctype=None, bin=1):
    ? ^^ ^^
    270 bde0ab27 + def drawBBox(bbox, borderWidth=0.0, origin=None, display=None, ctype=None, bin=1, frame=None):
    ? ^^^^^ ^ ++++++++++++
    243 3530e042 - """Draw an afwImage::BBox on a ds9 frame with the specified ctype. Include an extra borderWidth pixels
    ? ^
    271 bde0ab27 + """Draw an afwImage::BBox on a display frame with the specified ctype. Include an extra borderWidth pixels
    ? + ^^^^ If origin is present, it's Added to the BBox All BBox coordinates are divided by bin, as is right and proper for overlaying on a binned image """ x0, y0 = bbox.getMinX(), bbox.getMinY() x1, y1 = bbox.getMaxX(), bbox.getMaxY() if origin: x0 += origin[0]; x1 += origin[0] y0 += origin[1]; y1 += origin[1] x0 /= bin; y0 /= bin x1 /= bin; y1 /= bin borderWidth /= bin
    287 bde0ab27 + display = _getDisplayFromDisplayOrFrame(display, frame)
    259 b03e574b - ds9.line([(x0 - borderWidth, y0 - borderWidth),
    ? ^
    288 bde0ab27 + display.line([(x0 - borderWidth, y0 - borderWidth),
    ? + ^^^^ (x0 - borderWidth, y1 + borderWidth), (x1 + borderWidth, y1 + borderWidth), (x1 + borderWidth, y0 - borderWidth), (x0 - borderWidth, y0 - borderWidth), ], frame=frame, ctype=ctype) def drawFootprint(foot, borderWidth=0.5, origin=None, XY0=None, frame=None, ctype=None, bin=1,
    267 8a2e2a73 - peaks=False, symb="+", size=0.4, ctypePeak=None):
    296 bde0ab27 + peaks=False, symb="+", size=0.4, ctypePeak=None, display=None):
    ? ++++++++++++++
    268 21069702 - """Draw an afwDetection::Footprint on a ds9 frame with the specified ctype. Include an extra borderWidth
    ? ^
    297 bde0ab27 + """Draw an afwDetection::Footprint on a display frame with the specified ctype. Include an extra borderWidth
    ? + ^^^^ pixels If origin is present, it's Added to the Footprint; if XY0 is present is Subtracted from the Footprint If peaks is True, also show the object's Peaks using the specified symbol and size and ctypePeak All Footprint coordinates are divided by bin, as is right and proper for overlaying on a binned image """ if XY0: if origin: raise RuntimeError("You may not specify both origin and XY0") origin = (-XY0[0], -XY0[1])
    310 bde0ab27 + display = _getDisplayFromDisplayOrFrame(display, frame)
    281 4402095d - with ds9.Buffering():
    ? ^
    311 bde0ab27 + with display.Buffering():
    ? + ^^^^ borderWidth /= bin for s in foot.getSpans(): y, x0, x1 = s.getY(), s.getX0(), s.getX1() if origin: x0 += origin[0]; x1 += origin[0] y += origin[1] x0 /= bin; x1 /= bin; y /= bin
    292 4402095d - ds9.line([(x0 - borderWidth, y - borderWidth),
    ? ^
    322 bde0ab27 + display.line([(x0 - borderWidth, y - borderWidth),
    ? + ^^^^ (x0 - borderWidth, y + borderWidth), (x1 + borderWidth, y + borderWidth), (x1 + borderWidth, y - borderWidth), (x0 - borderWidth, y - borderWidth), ], frame=frame, ctype=ctype) if peaks: for p in foot.getPeaks(): x, y = p.getIx(), p.getIy() if origin: x += origin[0]; y += origin[1] x /= bin; y /= bin
    308 4402095d - ds9.dot(symb, x, y, size=size, ctype=ctypePeak, frame=frame)
    ? ^
    338 bde0ab27 + display.dot(symb, x, y, size=size, ctype=ctypePeak, frame=frame)
    ? + ^^^^
    310 0a2647a4 - def drawCoaddInputs(exposure, frame=None, ctype=None, bin=1):
    340 bde0ab27 + def drawCoaddInputs(exposure, frame=None, ctype=None, bin=1, display=None):
    ? ++++++++++++++
    311 0a2647a4 - """Draw the bounding boxes of input exposures to a coadd on a ds9 frame with the specified ctype,
    ? ^
    341 bde0ab27 + """Draw the bounding boxes of input exposures to a coadd on a display frame with the specified ctype,
    ? + ^^^^
    312 0a2647a4 - assuming ds9.mtv() has already been called on the given exposure on this frame.
    ? ^
    342 bde0ab27 + assuming display.mtv() has already been called on the given exposure on this frame.
    ? + ^^^^ All coordinates are divided by bin, as is right and proper for overlaying on a binned image """ coaddWcs = exposure.getWcs() catalog = exposure.getInfo().getCoaddInputs().ccds
    320 0a2647a4 - offset = afwGeom.Point2D() - afwGeom.Point2D(exposure.getXY0())
    ? - -
    350 bde0ab27 + offset = afwGeom.PointD() - afwGeom.PointD(exposure.getXY0())
    351 bde0ab27 +
    352 bde0ab27 + display = _getDisplayFromDisplayOrFrame(display, frame)
    353 bde0ab27 +
    321 0a2647a4 - with ds9.Buffering():
    ? ^
    354 bde0ab27 + with display.Buffering():
    ? + ^^^^ for record in catalog: ccdBox = afwGeom.Box2D(record.getBBox()) ccdCorners = ccdBox.getCorners() coaddCorners = [coaddWcs.skyToPixel(record.getWcs().pixelToSky(point)) + offset for point in ccdCorners]
    327 0a2647a4 - ds9.line([(coaddCorners[i].getX() / bin, coaddCorners[i].getY() / bin)
    ? ^ - - - -
    360 bde0ab27 + display.line([(coaddCorners[i].getX()/bin, coaddCorners[i].getY()/bin)
    ? + ^^^^ for i in range(-1, 4)], frame=frame, ctype=ctype)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    82bff8fb

    commit 82bff8fbe3f351bf45bf263aa8fce9e9c6049dd6
    Author: Robert Lupton the Good 
    Date:   Sun Jul 29 15:45:52 2012 +0900
    
        Minor changes to mosaic code.  If height>width 1x1 mosaic ended up as 1x2...
    

    c41be7b6

    commit c41be7b64fd82363ddbb5b11a1180e4c61e16e5e
    Author: rhl 
    Date:   Sat Sep 26 06:24:20 2009 +0000
    
        Support makeMosaic(..., title=XXX)
    

    21069702

    commit 21069702f3ca3ac87d30135e620cb853330c6f0e
    Author: rhl 
    Date:   Thu Mar 24 13:48:11 2011 +0000
    
        Added drawFootprint
    

    3c57f5d1

    commit 3c57f5d19fbc242bcb231f42b1b3cda429905ebc
    Author: rhl 
    Date:   Mon Jul 6 17:08:39 2009 +0000
    
        (I thought that I'd checked this in long ago).  Support Mosaic.append()
    

    0a2647a4

    commit 0a2647a4f57addc3b3adb347da995fa0d36b43cb
    Author: Jim Bosch 
    Date:   Wed Feb 6 13:23:20 2013 -0500
    
        Add display.utils function to plot the bboxes of inputs to a coadd in ds9.
    

    76134b7e

    commit 76134b7e3d3078a5dd294a8e43c9eb2d7d2aa3a8
    Author: rhl 
    Date:   Sun Mar 8 06:18:53 2009 +0000
    
        Misc minor improvements
    

    4402095d

    commit 4402095d4b48c21dc2c039fdd808f1455eb30aa2
    Author: rhl 
    Date:   Fri Sep 16 18:49:46 2011 +0000
    
        Allow users to use "with" when buffering dot/line
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    b03e574b

    commit b03e574bcadf3641e7e235baa72038ddb717ca0f
    Author: rhl 
    Date:   Thu Jan 7 04:18:16 2010 +0000
    
        Worked on Raft (including ds9 display)
    

    533d26ca

    commit 533d26ca3139d81f641875d769426c1db600c8e6
    Merge: 42901f2 4162d34
    Author: rhl 
    Date:   Tue Sep 20 22:26:09 2011 +0000
    
        Merged from #1763
    

    2eb9dac3

    commit 2eb9dac33eec6f13a73c03cc2827aa9884ff06cc
    Author: rowen 
    Date:   Mon Sep 28 22:55:55 2009 +0000
    
        Removed all tabs.
    

    3530e042

    commit 3530e042cea526dce3552a1ac85b074c18f4b1b1
    Author: rhl 
    Date:   Thu Apr 15 15:29:10 2010 +0000
    
        Add ability to have different coloured labels in a mosaic; misc
    

    c369a8ad

    commit c369a8ad53962aba950f7710210be4b23f45a523
    Author: Paul Price 
    Date:   Wed Jul 2 07:29:40 2014 +0900
    
        utils: make Mosaic.nImage a property
        
        This fixes the problem in setting nImage (wasn't being
        done until makeMosaic was called), while not hurting the
        API.
    

    f065975e

    commit f065975eb810f47343b1b291660a55c0ae04b720
    Author: rhl 
    Date:   Mon Mar 2 19:22:13 2009 +0000
    
        Add a class Mosaic to make mosaics
    

    148d4ecb

    commit 148d4ecbe61b2f192219bc187050582ec13e173f
    Author: rhl 
    Date:   Sat Apr 17 23:56:30 2010 +0000
    
        Improve packing login for Mosaic
    

    5555e238

    commit 5555e23886ab0af249d1cb48d28b0c2045277e2e
    Author: rhl 
    Date:   Fri Jul 10 16:19:41 2009 +0000
    
        Improved docstring
    

    6c16535b

    commit 6c16535b756702211756bc7507e2702503eaf8d6
    Author: rhl 
    Date:   Thu Dec 17 19:05:19 2009 +0000
    
        make Mosaic.drawLabels understand frame==None
    

    8ac39af5

    commit 8ac39af5a7f73410e3ba82d2465d1deaa4a28683
    Author: rhl 
    Date:   Fri Mar 20 18:23:09 2009 +0000
    
        Allow mosaic code to accept stamps of different sizes (it'll pad out to the largest; packing properly is, I think, NP hard)
    

    8a2e2a73

    commit 8a2e2a73e5d4639c62f73bc54a00aab70420f9d1
    Author: rhl 
    Date:   Thu Sep 15 22:08:24 2011 +0000
    
        Added FootprintSet::merge to merge FootprintSets; #762
    

    1f2c9901

    commit 1f2c99018a903fc4302243f8ce0e152b5595c05b
    Author: rhl 
    Date:   Tue May 25 13:59:43 2010 +0000
    
        Added option to bin BBoxes
    

    Commits in /Users/nate/repos_lsst/afw/

    bde0ab27

    commit bde0ab27a9add858f810563213c1424f9e63ddde
    Author: Robert Lupton the Good 
    Date:   Sun Apr 12 16:00:47 2015 -0300
    
        Implement RFC-42
        
        N.b. that you need display_ds9 to use the ds9 backend
        N.b. support frame only in cameraGeom.utils top-level routine, showCamera
    

    76134b7e

    commit 76134b7e3d3078a5dd294a8e43c9eb2d7d2aa3a8
    Author: rhl 
    Date:   Sun Mar 8 06:18:53 2009 +0000
    
        Misc minor improvements
    

    Return to list

    src/math/detail/SConscript

    Diff:

                    # -*- python -*-
                    from lsst.sconsUtils import scripts, targets, env
                    
    
    4 13d41289 - import eups
    5 13d41289 - if eups.productDir("cuda_toolkit"):
    4 ed95653a + import lsst.utils
    5 ed95653a + try:
    6 ed95653a + lsst.utils.getPackageDir('cuda_toolkit')
    7 ed95653a + except Exception:
    8 ed95653a + pass
    9 ed95653a + else:
    envCudaCommon = env.Clone() envCudaCommon.Append(NVCCFLAGS = ' -gencode=arch=compute_13,code=\\"sm_13,compute_13\\" ') envCudaCommon.Append(NVCCFLAGS = ' -gencode=arch=compute_20,code=\\"sm_20,compute_20\\" ') envConv = envCudaCommon.Clone() envConv.Append(NVCCFLAGS = ' -maxrregcount=60 ') envConv.Append(NVCCFLAGS = ' --ptxas-options=-v ') gpuObjConvolution = envConv.SharedObject("#/src/math/detail/convGPU", ["#src/math/detail/convGPU.cu"]) envWarp = envCudaCommon.Clone() envWarp.Append(NVCCFLAGS = ' -maxrregcount=60 ') envWarp.Append(NVCCFLAGS = ' --ptxas-options=-v ') gpuObjConvolution = envWarp.SharedObject('#src/math/detail/cudaLanczos', ['#src/math/detail/cudaLanczos.cu'])
    17 13d41289 -
    18 13d41289 -
    19 13d41289 -

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    13d41289

    commit 13d41289af5b2053141f9014195f68e20032551a
    Author: Kresimir Cosic 
    Date:   Fri Mar 23 04:58:07 2012 +0100
    
        nvcc options are now set per-file in SConscript. Cleaned up some comments.
    

    Commits in /Users/nate/repos_lsst/afw/

    ed95653a

    commit ed95653aae0db5c64fec82321af822db861c9e9c
    Author: Joshua Hoblitt 
    Date:   Thu May 21 14:38:34 2015 -0700
    
        replace eups.productDir() calls with lsst.utils.getPackageDir()
    

    Return to list

    tests/pickles.py

    Diff:

    1 314dc66e - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for pickles of some afw types """
    29 314dc66e - import math
    30 314dc66e - import os
    31 314dc66e - import sys
    import unittest
    33 314dc66e - import eups
    import pickle import lsst.daf.base as dafBase import lsst.utils.tests as utilsTests import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.afw.geom.ellipses as geomEllip import lsst.afw.coord as afwCoord class PickleTestCase(unittest.TestCase): """A test case for pickles""" def setUp(self): raise NotImplementedError("Need to inherit and create the 'data' element.") def tearDown(self): del self.data def assertPickled(self, new): """Assert that the pickled data is the same as the original Subclasses should override this method if the particular data doesn't support the == operator. """ self.assertTrue(new == self.data) def testPickle(self): """Test round-trip pickle""" pickled = pickle.dumps(self.data) newData = pickle.loads(pickled) self.assertPickled(newData) class AngleTestCase(PickleTestCase): def setUp(self): self.data = 1.0*afwGeom.degrees class CoordTestCase(PickleTestCase): def setUp(self): ra = 10.0*afwGeom.degrees dec = 1.0*afwGeom.degrees epoch = 2000.0 self.data = [afwCoord.Coord(ra, dec, epoch), afwCoord.Fk5Coord(ra, dec, epoch), afwCoord.IcrsCoord(ra, dec), afwCoord.GalacticCoord(ra, dec), afwCoord.EclipticCoord(ra, dec), # TopocentricCoord is not currently picklable ] class QuadrupoleTestCase(PickleTestCase): def setUp(self): ixx, iyy, ixy = 1.0, 1.0, 0.0 self.data = geomEllip.Quadrupole(ixx, iyy, ixy) class AxesTestCase(PickleTestCase): def setUp(self): a, b, theta = 1.0, 1.0, 0.0 self.data = geomEllip.Axes(a, b, theta) class Point2DTestCase(PickleTestCase): def setUp(self): x, y = 1.0, 1.0 self.data = afwGeom.Point2D(x, y) class Point2ITestCase(PickleTestCase): def setUp(self): x, y = 1, 1 self.data = afwGeom.Point2I(x, y) class Point3DTestCase(PickleTestCase): def setUp(self): x, y, z = 1.0, 1.0, 1.0 self.data = afwGeom.Point3D(x, y, z) class Point3ITestCase(PickleTestCase): def setUp(self): x, y, z = 1,1,1 self.data = afwGeom.Point3I(x, y, z) class Extent2DTestCase(PickleTestCase): def setUp(self): x, y = 1.0, 1.0 self.data = afwGeom.Extent2D(x, y) class Extent3DTestCase(PickleTestCase): def setUp(self): x, y, z = 1,1,1 self.data = afwGeom.Extent3D(x, y, z) class Extent2ITestCase(PickleTestCase): def setUp(self): x, y = 1, 1 self.data = afwGeom.Extent2I(x, y) class Extent3ITestCase(PickleTestCase): def setUp(self): x, y, z = 1,1,1 self.data = afwGeom.Extent3I(x, y, z) class Box2DTestCase(PickleTestCase): def setUp(self): p, e = afwGeom.Point2D(1.0, 1.0), afwGeom.Extent2D(0.5, 0.5) self.data = afwGeom.Box2D(p, e) class Box2ITestCase(PickleTestCase): def setUp(self): p, e = afwGeom.Point2I(1, 2), afwGeom.Extent2I(1, 1) self.data = afwGeom.Box2I(p, e) class AffineTransformTestCase(PickleTestCase): def setUp(self): scale = 2.2 linear = afwGeom.LinearTransform().makeScaling(scale) dx, dy = 1.1, 3.3 trans = afwGeom.Extent2D(dx, dy) self.data = afwGeom.AffineTransform(linear, trans) def assertPickled(self, new): self.assertTrue((new.getMatrix() == self.data.getMatrix()).all()) class LinearTransformTestCase(PickleTestCase): def setUp(self): scale = 2.0 self.data = afwGeom.LinearTransform().makeScaling(scale) def assertPickled(self, new): self.assertTrue((new.getMatrix() == self.data.getMatrix()).all()) class WcsPickleTestCase(PickleTestCase): def setUp(self): hdr = dafBase.PropertyList() hdr.add("NAXIS", 2) hdr.add("EQUINOX", 2000.0000000000) hdr.add("RADESYS", "FK5") hdr.add("CRPIX1", 947.04531175212) hdr.add("CRPIX2", -305.70042176782) hdr.add("CD1_1", -5.6081060666063e-05) hdr.add("CD1_2", 1.1941349711530e-10) hdr.add("CD2_1", 1.1938226362497e-10) hdr.add("CD2_2", 5.6066392248206e-05) hdr.add("CRVAL1", 5.5350859380564) hdr.add("CRVAL2", -0.57805534748292) hdr.add("CUNIT1", "deg") hdr.add("CUNIT2", "deg") hdr.add("CTYPE1", "RA---TAN") hdr.add("CTYPE2", "DEC--TAN") self.data = afwImage.makeWcs(hdr) class TanWcsPickleTestCase(PickleTestCase): def setUp(self): hdr = dafBase.PropertyList() hdr.add("NAXIS", 2) hdr.add("EQUINOX", 2000.0000000000) hdr.add("RADESYS", "FK5") hdr.add("CRPIX1", 947.04531175212) hdr.add("CRPIX2", -305.70042176782) hdr.add("CD1_1", -5.6081060666063e-05) hdr.add("CD1_2", 1.1941349711530e-10) hdr.add("CD2_1", 1.1938226362497e-10) hdr.add("CD2_2", 5.6066392248206e-05) hdr.add("CRVAL1", 5.5350859380564) hdr.add("CRVAL2", -0.57805534748292) hdr.add("CUNIT1", "deg") hdr.add("CUNIT2", "deg") hdr.add("A_ORDER", 3) hdr.add("A_0_0", -3.4299726900155e-05) hdr.add("A_0_2", 2.9999243742039e-08) hdr.add("A_0_3", 5.3160367322875e-12) hdr.add("A_1_0", -1.1102230246252e-16) hdr.add("A_1_1", 1.7804837804549e-07) hdr.add("A_1_2", -3.9117665277930e-10) hdr.add("A_2_0", 1.2614116305773e-07) hdr.add("A_2_1", 2.4753748298399e-12) hdr.add("A_3_0", -4.0559790823371e-10) hdr.add("B_ORDER", 3) hdr.add("B_0_0", -0.00040333633853922) hdr.add("B_0_2", 2.7329405108287e-07) hdr.add("B_0_3", -4.1945333823804e-10) hdr.add("B_1_1", 1.0211300606274e-07) hdr.add("B_1_2", -1.1907781112538e-12) hdr.add("B_2_0", 7.1256679698479e-08) hdr.add("B_2_1", -4.0026664120969e-10) hdr.add("B_3_0", 7.2509034631981e-14) hdr.add("AP_ORDER", 5) hdr.add("AP_0_0", 0.065169424373537) hdr.add("AP_0_1", 3.5323035231808e-05) hdr.add("AP_0_2", -2.4878457741060e-08) hdr.add("AP_0_3", -1.4288745247360e-11) hdr.add("AP_0_4", -2.0000000098183) hdr.add("AP_0_5", 4.3337569354109e-19) hdr.add("AP_1_0", 1.9993638555698) hdr.add("AP_1_1", -2.0722860000493e-07) hdr.add("AP_1_2", 4.7562056847339e-10) hdr.add("AP_1_3", -8.5172068319818e-06) hdr.add("AP_1_4", -1.3242986537057e-18) hdr.add("AP_2_0", -1.4594781790233e-07) hdr.add("AP_2_1", -2.9254828606617e-12) hdr.add("AP_2_2", -2.7203380713516e-11) hdr.add("AP_2_3", 1.5030517486646e-19) hdr.add("AP_3_0", 4.7856034999197e-10) hdr.add("AP_3_1", 1.5571061278960e-15) hdr.add("AP_3_2", -3.2422164667295e-18) hdr.add("AP_4_0", 5.8904402441647e-16) hdr.add("AP_4_1", -4.5488928339401e-20) hdr.add("AP_5_0", -1.3198044795585e-18) hdr.add("BP_ORDER", 5) hdr.add("BP_0_0", 0.00025729974056661) hdr.add("BP_0_1", -0.00060857907313083) hdr.add("BP_0_2", -3.1283728005742e-07) hdr.add("BP_0_3", 5.0413932972962e-10) hdr.add("BP_0_4", -0.0046142128142681) hdr.add("BP_0_5", -2.2359607268985e-18) hdr.add("BP_1_0", 0.0046783112625990) hdr.add("BP_1_1", -1.2304042740813e-07) hdr.add("BP_1_2", -2.3756827881344e-12) hdr.add("BP_1_3", -3.9300202582816e-08) hdr.add("BP_1_4", -9.7385290942256e-21) hdr.add("BP_2_0", -6.5238116398890e-08) hdr.add("BP_2_1", 4.7855579009100e-10) hdr.add("BP_2_2", -1.2297758131839e-13) hdr.add("BP_2_3", -3.0849793267035e-18) hdr.add("BP_3_0", -9.3923321275113e-12) hdr.add("BP_3_1", -1.3193479628568e-17) hdr.add("BP_3_2", 2.1762350028059e-19) hdr.add("BP_4_0", -5.9687252632035e-16) hdr.add("BP_4_1", -1.4096893423344e-18) hdr.add("BP_5_0", 2.8085458107813e-19) hdr.add("CTYPE1", "RA---TAN-SIP") hdr.add("CTYPE2", "DEC--TAN-SIP") self.data = afwImage.makeWcs(hdr) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(AngleTestCase) suites += unittest.makeSuite(CoordTestCase) suites += unittest.makeSuite(QuadrupoleTestCase) suites += unittest.makeSuite(AxesTestCase) suites += unittest.makeSuite(Point2DTestCase) suites += unittest.makeSuite(Point3DTestCase) suites += unittest.makeSuite(Point2ITestCase) suites += unittest.makeSuite(Point3ITestCase) suites += unittest.makeSuite(Extent2DTestCase) suites += unittest.makeSuite(Extent3DTestCase) suites += unittest.makeSuite(Box2DTestCase) suites += unittest.makeSuite(Box2ITestCase) suites += unittest.makeSuite(AffineTransformTestCase) suites += unittest.makeSuite(LinearTransformTestCase) suites += unittest.makeSuite(WcsPickleTestCase) suites += unittest.makeSuite(TanWcsPickleTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(exit=False): """Run the tests""" utilsTests.run(suite(), exit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    314dc66e

    commit 314dc66e177c22d47c91ec14ac754df7d0617fab
    Author: price 
    Date:   Tue May 3 13:36:25 2011 +0000
    
        Wcs wasn't round-tripping through pickles because of missing elements in the archive.  Added a test to demonstrate this.  Added a operator== in Wcs, TanWcs and Coord so as to compare round-tripped Wcs.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    include/lsst/afw/geom/Extent.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief A coordinate class intended to represent offsets and dimensions.
                     */
                    #ifndef LSST_AFW_GEOM_EXTENT_H
                    #define LSST_AFW_GEOM_EXTENT_H
                    
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/geom/CoordinateExpr.h"
                    
                    namespace lsst { namespace afw { namespace geom {
                    
                    // These are present to avoid a static assertion for instantiating computeNorm() on integer types.
                    namespace detail {
                    
                    template 
                    double computeExtentNorm(Extent const & s) {
                        return s.asEigen().norm();
                    }
                    
                    template 
                    int computeExtentNorm(Extent const & s) {
                        throw LSST_EXCEPT(
    
    52 d01f3a63 - pex::exceptions::LogicErrorException,
    ? ---------
    52 21597d88 + pex::exceptions::LogicError,
    "Cannot compute norm of integer extent" ); #if 1 // make compilers happy in non-void function return -1; #endif } } // namespace detail template class ExtentBase : public CoordinateBase,T,N> { typedef CoordinateBase,T,N> Super; public: /// \brief Return the squared L2 norm of the Extent (x^2 + y^2 + ...). T computeSquaredNorm() const { return this->asEigen().squaredNorm(); } /// \brief Return the L2 norm of the Extent (sqrt(x^2 + y^2 + ...)). T computeNorm() const { return detail::computeExtentNorm(static_cast const &>(*this)); } /** * @brief Standard equality comparison. * * Returns true iff all(this->eq(other)); */ bool operator==(Extent const & other) const { return all(this->eq(other)); } /** * @brief Standard inequality comparison. * * Returns true iff any(this->ne(other)); */ bool operator!=(Extent const & other) const { return any(this->ne(other)); } /** * @name Named comparison functions * * Note that these return CoordinateExpr, not bool. * * Unlike most arithmetic and assignment operators, scalar interoperability is provided * for comparisons; expressions like * \code * if (all(extent.gt(0))) ... * \endcode * are both ubiquitous and easy to interpret. */ //@{ CoordinateExpr eq(Extent const & other) const; CoordinateExpr ne(Extent const & other) const; CoordinateExpr lt(Extent const & other) const; CoordinateExpr le(Extent const & other) const; CoordinateExpr gt(Extent const & other) const; CoordinateExpr ge(Extent const & other) const; CoordinateExpr eq(T scalar) const { return this->eq(Extent(scalar)); } CoordinateExpr ne(T scalar) const { return this->ne(Extent(scalar)); } CoordinateExpr lt(T scalar) const { return this->lt(Extent(scalar)); } CoordinateExpr le(T scalar) const { return this->le(Extent(scalar)); } CoordinateExpr gt(T scalar) const { return this->gt(Extent(scalar)); } CoordinateExpr ge(T scalar) const { return this->ge(Extent(scalar)); } //@} /** * @name Additive arithmetic operators * * No scalar interoperability is provided for Extent additive arithmetic operations. */ //@{ Point operator+(Point const & other) const; Extent operator+(Extent const & other) const { return Extent(this->_vector + other._vector); } Extent operator-(Extent const & other) const { return Extent(this->_vector - other._vector); } Extent & operator+=(Extent const & other) { this->_vector += other._vector; return static_cast&>(*this); } Extent & operator-=(Extent const & other) { this->_vector -= other._vector; return static_cast&>(*this); } Extent operator+() const { return static_cast const &>(*this); } Extent operator-() const { return Extent(-this->_vector); } //@} /** * @name Multiplicative arithmetic operators * * As usual with matrices and vectors, Extent can be multiplied or divided by a scalar. */ //@{ Extent operator*(T scalar) const { return Extent(this->_vector * scalar); } Extent & operator*=(T scalar) { this->_vector *= scalar; return static_cast&>(*this); } Extent operator/(T scalar) const { return Extent(this->_vector / scalar); } Extent & operator/=(T scalar) { this->_vector /= scalar; return static_cast&>(*this); } //@}
    152 b449d4b3 + /// Cast this object to an Extent of the same numeric type and dimensionality.
    153 b449d4b3 + Point asPoint() const;
    154 b449d4b3 +
    std::string toString() const { std::stringstream out; out << "Extent("; for (size_t i = 0; i < N; ++i) { if (i != 0) { out << ","; } out << (*this)[i]; } out << ")"; return out.str(); } protected: /// \brief Construct an Extent with all elements set to the same scalar value. explicit ExtentBase(T val=static_cast(0)) : Super(val) {} /// \brief Construct an Extent from an Eigen vector. template explicit ExtentBase(Eigen::MatrixBase const & vector) : Super(vector) {} }; /** * \brief A coordinate class intended to represent offsets and dimensions. *
    179 25e61ab4 - * Much of the functionality of Extent is provided by its CRTP base class, CoordinateBase.
    ? ^^^^^^^^
    182 8196a1ba + * Much of the functionality of Extent is provided by its CRTP base class, ExtentBase.
    ? ^^ ++ *
    184 8196a1ba + * See @ref afwGeomOps for mathematical operators on Extent.
    181 25e61ab4 - * Unlike Point, Extent does not have a type-converting constructor, because the rounding semantics
    182 25e61ab4 - * are not as clear. In most cases, conversions between integer and floating point dimensions are
    183 25e61ab4 - * best handled by Box objects, where the rounding semantics make more sense.
    */ template class Extent : public ExtentBase { typedef ExtentBase Super; public: typedef typename Super::EigenVector EigenVector; /// \brief Construct an Extent with all elements set to the same scalar value. explicit Extent(T val=static_cast(0)) : Super(val) {} /// \brief Construct an Extent from an Eigen vector. explicit Extent(EigenVector const & vector) : Super(vector) {} /// \brief Explicit constructor from Point. explicit Extent(Point const & other); /// \brief Explicit constructor from Extent of different type (if allowed) template explicit Extent(Extent const & other); template explicit Extent(Point const & other); /// \brief Return the squared L2 norm of the Extent (x^2 + y^2 + ...). T computeSquaredNorm() const { return this->asEigen().squaredNorm(); } /// \brief Return the L2 norm of the Extent (sqrt(x^2 + y^2 + ...)). T computeNorm() const { return this->asEigen().norm(); } void swap(Extent & other) { this->_swap(other); } }; /** * \brief A coordinate class intended to represent offsets and dimensions (2-d specialization).
    218 8196a1ba + *
    219 8196a1ba + * See @ref afwGeomOps for mathematical operators on Extent.
    */ template class Extent : public ExtentBase { typedef ExtentBase Super; public: typedef typename Super::EigenVector EigenVector; /// \brief Construct an Extent with all elements set to the same scalar value. explicit Extent(T val=static_cast(0)) : Super(val) {} /// \brief Construct an Extent from an Eigen vector. explicit Extent(EigenVector const & vector) : Super(vector) {} /// \brief Explicit constructor from Point. explicit Extent(Point const & other); /// \brief Explicit constructor from Extent of different type (if allowed) template explicit Extent(Extent const & other); template explicit Extent(Point const & other); /// @brief Construct from two scalars. explicit Extent(T x, T y) : Super(EigenVector(x, y)) {} /// @brief Construct from a two-element array. explicit Extent(T const xy[2]) : Super(EigenVector(xy[0], xy[1])) {} /// @brief Construct from a std::pair. explicit Extent(std::pair const & xy) : Super(EigenVector(xy.first, xy.second)) {} /// @brief Construct from boost::tuple. explicit Extent(boost::tuple const & xy) : Super(EigenVector(xy.template get<0>(), xy.template get<1>())) {} #ifdef SWIG T getX() const; T getY() const; void setX(T x); void setY(T y); #endif void swap(Extent & other) { this->_swap(other); } }; /** * \brief A coordinate class intended to represent offsets and dimensions (3-d specialization).
    267 8196a1ba + *
    268 8196a1ba + * See @ref afwGeomOps for mathematical operators on Extent.
    */ template class Extent : public ExtentBase { typedef ExtentBase Super; public: typedef typename Super::EigenVector EigenVector; /// \brief Construct an Extent with all elements set to the same scalar value. explicit Extent(T val=static_cast(0)) : Super(val) {} /// \brief Construct an Extent from an Eigen vector. explicit Extent(EigenVector const & vector) : Super(vector) {} /// \brief Explicit constructor from Point. explicit Extent(Point const & other); /// \brief Explicit constructor from Extent of different type (if allowed) template explicit Extent(Extent const & other); template explicit Extent(Point const & other); /// @brief Construct from three scalars. explicit Extent(T x, T y, T z) : Super(EigenVector(x, y, z)) {} /// @brief Construct from a two-element array. explicit Extent(T const xyz[3]) : Super(EigenVector(xyz[0], xyz[1], xyz[2])) {} /// @brief Construct from boost::tuple. explicit Extent(boost::tuple const & xyz) : Super(EigenVector(xyz.template get<0>(), xyz.template get<1>(), xyz.template get<2>())) {} #ifdef SWIG T getX() const; T getY() const; T getZ() const; void setX(T x); void setY(T y); void setZ(T z); #endif void swap(Extent & other) { this->_swap(other); } }; // Constructor for any 2D type from 2I type template template Extent::Extent(Extent const & other) { BOOST_STATIC_ASSERT( (!boost::is_same::value && boost::is_integral::value) ); this->setX(static_cast(other.getX())); this->setY(static_cast(other.getY())); }; template template Extent::Extent(Point const & other) { BOOST_STATIC_ASSERT( (!boost::is_same::value && boost::is_integral::value) ); this->setX(static_cast(other.getX())); this->setY(static_cast(other.getY())); }; // Constructor for any 3D type from 3I type template template Extent::Extent(Extent const & other) { BOOST_STATIC_ASSERT( (!boost::is_same::value && boost::is_integral::value) ); this->setX(static_cast(other.getX())); this->setY(static_cast(other.getY())); this->setZ(static_cast(other.getZ())); }; // Constructor for any 3D type from 3I type template template Extent::Extent(Point const & other) { BOOST_STATIC_ASSERT( (!boost::is_same::value && boost::is_integral::value) ); this->setX(static_cast(other.getX())); this->setY(static_cast(other.getY())); this->setZ(static_cast(other.getZ())); }; typedef Extent ExtentI; typedef Extent Extent2I; typedef Extent Extent3I; typedef Extent ExtentD; typedef Extent Extent2D; typedef Extent Extent3D;
    361 4567a4cd + /**
    362 4567a4cd + * Return the component-wise truncation (round towards zero).
    363 4567a4cd + *
    364 4567a4cd + * In Python, this is available as both a free function and a method on ExtentD.
    365 4567a4cd + */
    366 4567a4cd + template
    367 4567a4cd + Extent truncate(Extent const & input);
    368 4567a4cd +
    369 4567a4cd + /**
    370 4567a4cd + * Return the component-wise floor (round towards more negative).
    371 4567a4cd + *
    372 4567a4cd + * In Python, this is available as both a free function and a method on ExtentD.
    373 4567a4cd + */
    374 4567a4cd + template
    375 4567a4cd + Extent floor(Extent const & input);
    376 4567a4cd +
    377 4567a4cd + /**
    378 4567a4cd + * Return the component-wise ceil (round towards more positive).
    379 4567a4cd + *
    380 4567a4cd + * In Python, this is available as both a free function and a method on ExtentD.
    381 4567a4cd + */
    382 4567a4cd + template
    383 4567a4cd + Extent ceil(Extent const & input);
    384 4567a4cd +
    385 4567a4cd + #ifndef SWIG
    386 4567a4cd +
    387 4567a4cd + // Some operators below need to take ExtentBase arguments rather than Extent to
    388 4567a4cd + // avoid ambiguous overloads (since some competing operators are defined as member
    389 4567a4cd + // functions on ExtentBase).
    390 4567a4cd +
    391 4567a4cd + template
    392 4567a4cd + Extent operator*(T scalar, ExtentBase const & rhs) {
    393 4567a4cd + return rhs * scalar;
    394 4567a4cd + }
    395 4567a4cd +
    396 4567a4cd + template
    397 4567a4cd + Extent operator*(ExtentBase const & lhs, double rhs) {
    398 4567a4cd + return Extent(static_cast const &>(lhs)) * rhs;
    399 4567a4cd + }
    400 4567a4cd +
    401 4567a4cd + template
    402 4567a4cd + void operator*=(ExtentBase & lhs, double rhs) {
    403 4567a4cd + // use "N < 0" so assertion is dependent on template instantiation, instead of triggering all the time
    404 4567a4cd + static_assert(N < 0, "In-place multiplication of Extent by double would truncate.");
    405 4567a4cd + }
    406 4567a4cd +
    407 4567a4cd + template
    408 4567a4cd + Extent operator/(ExtentBase const & lhs, double rhs) {
    409 4567a4cd + return Extent(static_cast const &>(lhs)) / rhs;
    410 4567a4cd + }
    411 4567a4cd +
    412 4567a4cd + template
    413 4567a4cd + void operator/=(ExtentBase & lhs, double rhs) {
    414 4567a4cd + // use "N < 0" so assertion is dependent on template instantiation, instead of triggering all the time
    415 4567a4cd + static_assert(N < 0, "In-place division of Extent by double would truncate.");
    416 4567a4cd + }
    417 4567a4cd +
    418 4567a4cd + template
    419 4567a4cd + Extent operator*(double lhs, ExtentBase const & rhs) {
    420 4567a4cd + return lhs * Extent(static_cast const &>(rhs));
    421 4567a4cd + }
    422 4567a4cd +
    423 4567a4cd + template
    424 4567a4cd + Extent operator+(Extent const & lhs, Extent const & rhs) {
    425 4567a4cd + return lhs + Extent(rhs);
    426 4567a4cd + }
    427 4567a4cd +
    428 4567a4cd + template
    429 4567a4cd + Extent & operator+=(Extent & lhs, Extent const & rhs) {
    430 4567a4cd + return lhs += Extent(rhs);
    431 4567a4cd + }
    432 4567a4cd +
    433 4567a4cd + template
    434 4567a4cd + Extent operator-(Extent const & lhs, Extent const & rhs) {
    435 4567a4cd + return lhs - Extent(rhs);
    436 4567a4cd + }
    437 4567a4cd +
    438 4567a4cd + template
    439 4567a4cd + Extent & operator-=(Extent & lhs, Extent const & rhs) {
    440 4567a4cd + return lhs -= Extent(rhs);
    441 4567a4cd + }
    442 4567a4cd +
    443 4567a4cd + template
    444 4567a4cd + Extent operator+(Extent const & lhs, Extent const & rhs) {
    445 4567a4cd + return Extent(lhs) + rhs;
    446 4567a4cd + }
    447 4567a4cd +
    448 4567a4cd + template
    449 4567a4cd + Extent operator-(Extent const & lhs, Extent const & rhs) {
    450 4567a4cd + return Extent(lhs) - rhs;
    451 4567a4cd + }
    452 4567a4cd +
    453 4567a4cd + #endif // !SWIG
    454 4567a4cd +
    }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d01f3a63

    commit d01f3a63feaa9523c38ace7eefa66026e7b08d6b
    Author: Jim Bosch 
    Date:   Wed Jun 13 17:13:25 2012 -0400
    
        Throw exceptions instead of asserting in Python-accessible code.
    

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    8196a1ba

    commit 8196a1baa9b18a3cf752b2784d0c895d54a3ab36
    Author: Jim Bosch 
    Date:   Tue Apr 14 15:25:10 2015 -0400
    
        Add table of Point/Extent operations to Doxygen.
    

    b449d4b3

    commit b449d4b3dd5e2b050d522b7c3990f50277096ef0
    Author: Jim Bosch 
    Date:   Fri Apr 3 18:17:10 2015 -0400
    
        Add conversion between Point and Extent as methods.
        
        Methods are much less verbose than the existing conversion constructors
        in Python.
    

    Return to list

    src/coord/Coord.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file Coord.cc
                     * @brief Provide functions to handle coordinates
                     * @ingroup afw
                     * @author Steve Bickerton
                     *
                     * Most (nearly all) algorithms adapted from Astronomical Algorithms, 2nd ed. (J. Meeus)
                     *
                     */
                    #include 
                    #include 
                    #include 
    
    37 4d62652f + #include
    #include "Eigen/Core" #include "Eigen/Geometry" #include "lsst/pex/exceptions.h" #include "boost/algorithm/string.hpp" #include "boost/tuple/tuple.hpp" #include "boost/format.hpp" #include "lsst/afw/coord/Coord.h" #include "lsst/daf/base/DateTime.h" namespace afwCoord = lsst::afw::coord; namespace ex = lsst::pex::exceptions; namespace afwGeom = lsst::afw::geom; namespace dafBase = lsst::daf::base; namespace { typedef std::map CoordSystemMap; CoordSystemMap const getCoordSystemMap() { CoordSystemMap idMap; idMap["FK5"] = afwCoord::FK5; idMap["ICRS"] = afwCoord::ICRS; idMap["ECLIPTIC"] = afwCoord::ECLIPTIC; idMap["GALACTIC"] = afwCoord::GALACTIC; idMap["ELON"] = afwCoord::ECLIPTIC; idMap["GLON"] = afwCoord::GALACTIC; idMap["TOPOCENTRIC"] = afwCoord::TOPOCENTRIC; return idMap; } /// Calculate angular distance between two points using the Haversine formula /// /// Besides the differences between the two coordinates, we also input the /// cosine of the two declinations, so as to be thrifty with the use of trig functions. afwGeom::Angle haversine(afwGeom::Angle const dAlpha, /// Difference between RAs (or longitudes), alpha1-alpha2 afwGeom::Angle const dDelta, /// Difference between Decs (or latitudes), delta1-delta2 double const cosDelta1, /// Cosine of the first Dec, cos(delta1) double const cosDelta2 /// Cosine of the second Dec, cos(delta2) ) { double const havDDelta = std::sin(dDelta/2.0) * std::sin(dDelta/2.0); double const havDAlpha = std::sin(dAlpha/2.0) * std::sin(dAlpha/2.0); double const havD = havDDelta + cosDelta1 * cosDelta2 * havDAlpha; double const sinDHalf = std::sqrt(havD); afwGeom::Angle dist = (2.0 * std::asin(sinDHalf)) * afwGeom::radians; return dist; } double const epochTolerance = 1.0e-12; ///< Precession to new epoch performed if two epochs differ by this. // Put a pair of coordinates in a common FK5 system std::pair commonFk5(afwCoord::Coord const& c1, afwCoord::Coord const& c2 ) { // make sure they're fk5 afwCoord::Fk5Coord fk51 = c1.toFk5(); afwCoord::Fk5Coord fk5tmp = c2.toFk5(); // make sure they have the same epoch afwCoord::Fk5Coord fk52; if (fabs(fk51.getEpoch() - fk5tmp.getEpoch()) > epochTolerance) { fk52 = fk5tmp.precess(fk51.getEpoch()); } else { fk52 = fk5tmp; } return std::make_pair(fk51, fk52); } } // end anonymous namespace /** * @brief A utility function to get the enum value of a coordinate system from a string name. */ afwCoord::CoordSystem afwCoord::makeCoordEnum(std::string const system) { static CoordSystemMap idmap = getCoordSystemMap(); if (idmap.find(system) != idmap.end()) { return idmap[system]; } else {
    121 29df7008 - throw LSST_EXCEPT(ex::InvalidParameterException, "System " + system + " not defined.");
    ? ^^^^^^ ^
    122 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError, "System " + system + " not defined.");
    ? ^^ ^ } } namespace { double const NaN = std::numeric_limits::quiet_NaN(); double const JD2000 = 2451544.50; /* * A local class to handle dd:mm:ss coordinates * * This class allows a decimal or dd:mm:ss coordinate to be * disassembed into d, m, and s components. * It's in an anonymous namespace, but there are public functions * which perform the transformations directly: * * --> std::string dmsStr = degreesToDmsString(double deg); * --> double deg = dmsStringToDegrees(std::string dms); */ class Dms { public: Dms() {}; // note that isSouth is needed to specify coords between dec = 0, and dec = -1 // otherwise, d = -0 gets carried as d = 0 ... need a way to specify it explicitly Dms(int const d, int const m, double const s, bool const isSouth=false) { sign = (d < 0 || isSouth) ? -1 : 1; deg = std::abs(d); min = m; sec = s; }; // unit could be "degrees" or "hours" Dms(afwGeom::Angle const deg00, afwGeom::AngleUnit const unit = afwGeom::degrees) { double deg0 = deg00.asAngularUnits(unit); double const absVal = std::fabs(deg0); sign = (deg0 >= 0) ? 1 : -1; deg = static_cast(std::floor(absVal)); min = static_cast(std::floor((absVal - deg)*60.0)); sec = ((absVal - deg)*60.0 - min)*60.0; } int deg; int min; double sec; int sign; }; /** * Store the Fk5 coordinates of the Galactic pole (and vice-versa) for coordinate transforms. * */ afwCoord::Coord const& GalacticPoleInFk5() { static afwCoord::Coord pole(192.85950*afwGeom::degrees, 27.12825*afwGeom::degrees, 2000.0); // C&O return pole; } afwCoord::Coord const& Fk5PoleInGalactic() { static afwCoord::Coord pole(122.93200 * afwGeom::degrees, 27.12825 * afwGeom::degrees, 2000.0); // C&O return pole; } /** * @brief Compute the mean Sidereal Time at Greenwich * */ afwGeom::Angle meanSiderealTimeGreenwich( double const jd ///< Julian Day ) { double const T = (jd - 2451545.0)/36525.0; return (280.46061837 + 360.98564736629*(jd - 2451545.0) + 0.000387933*T*T - (T*T*T/38710000.0)) * afwGeom::degrees; } /* * A pair of utility functions to go from cartesian to spherical */ double const atPoleEpsilon = 0.0; //std::numeric_limits::epsilon(); afwGeom::Angle pointToLongitude(lsst::afw::geom::Point3D const &p3d, double const defaultLongitude=0.0) { afwGeom::Angle lon; if (fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) { lon = afwGeom::Angle(0.0); } else { lon = std::atan2(p3d.getY(), p3d.getX()) * afwGeom::radians; lon.wrap(); } return lon; } afwGeom::Angle pointToLatitude(lsst::afw::geom::Point3D const &p3d) { afwGeom::Angle lat; if ( fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) { lat = (p3d.getZ() >= 0) ? afwGeom::Angle(afwGeom::HALFPI) : afwGeom::Angle(-afwGeom::HALFPI); } else { lat = std::asin(p3d.getZ()) * afwGeom::radians; } return lat; } std::pair pointToLonLat(lsst::afw::geom::Point3D const &p3d, double const defaultLongitude=0.0, bool normalize=true) { std::pair lonLat; if (normalize) { double const inorm = 1.0/p3d.asEigen().norm(); double const x = inorm*p3d.getX(); double const y = inorm*p3d.getY(); double const z = inorm*p3d.getZ(); if (fabs(x) <= atPoleEpsilon && fabs(y) <= atPoleEpsilon) { lonLat.first = 0.0 * afwGeom::radians; lonLat.second = ((z >= 0) ? 1.0 : -1.0) * afwGeom::HALFPI * afwGeom::radians; } else { lonLat.first = atan2(y, x) * afwGeom::radians; lonLat.first.wrap(); lonLat.second = asin(z) * afwGeom::radians; } } else { if (fabs(p3d.getX()) <= atPoleEpsilon && fabs(p3d.getY()) <= atPoleEpsilon) { lonLat.first = 0.0 * afwGeom::radians; lonLat.second = ((p3d.getZ() >= 0) ? 1.0 : -1.0) * afwGeom::HALFPI * afwGeom::radians; } else { lonLat.first = atan2(p3d.getY(), p3d.getX()) * afwGeom::radians; lonLat.first.wrap(); lonLat.second = asin(p3d.getZ()) * afwGeom::radians; } } return lonLat; } } // end anonymous namespace /******************* Public functions ********************/ static std::string angleToXmsString(afwGeom::Angle const a, afwGeom::AngleUnit const unit) { Dms dms(a, unit); // make sure rounding won't give 60.00 for sec or min if ( (60.00 - dms.sec) < 0.005 ) { dms.sec = 0.0; dms.min += 1; if (dms.min == 60) { dms.min = 0; dms.deg += 1; if (dms.deg == 360) { dms.deg = 0; } } } std::string fmt("%02d:%02d:%05.2f"); std::string s = (boost::format(fmt) % dms.deg % dms.min % dms.sec).str(); if (dms.sign < 0) { s = "-" + s; } return s; } /** * @brief a Function to convert a coordinate in decimal degrees to a string with form dd:mm:ss * * @todo allow a user specified format */ std::string afwCoord::angleToDmsString(afwGeom::Angle const a) { return angleToXmsString(a, afwGeom::degrees); } /** * @brief a function to convert decimal degrees to a string with form hh:mm:ss.s */ std::string afwCoord::angleToHmsString(afwGeom::Angle const a) { return angleToXmsString(a, afwGeom::hours); } /** * @brief Convert a XX:mm:ss string to Angle */ static afwGeom::Angle xmsStringToAngle( std::string const dms, ///< Coord as a string in dd:mm:ss format afwGeom::AngleUnit unit ) { if (dms.find(":") == std::string::npos) {
    311 721f7910 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    312 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ (boost::format("String is not in xx:mm:ss format: %s") % dms).str()); } std::vector elements; boost::split(elements, dms, boost::is_any_of(":")); if (elements.size() != 3) {
    317 721f7910 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    318 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ (boost::format("Could not parse string as xx:mm:ss format: %s") % dms).str()); } int const deg = abs(atoi(elements[0].c_str())); int const min = atoi(elements[1].c_str()); double const sec = atof(elements[2].c_str()); afwGeom::Angle ang = (deg + min/60.0 + sec/3600.0) * unit; if ( (elements[0].c_str())[0] == '-' ) { ang *= -1.0; } return ang; } /** * @brief Convert a hh:mm:ss string to Angle */ afwGeom::Angle afwCoord::hmsStringToAngle( std::string const hms ){ return xmsStringToAngle(hms, afwGeom::hours); } /** * @brief Convert a dd:mm:ss string to Angle */ afwGeom::Angle afwCoord::dmsStringToAngle( std::string const dms ///< Coord as a string in dd:mm:ss format ) { return xmsStringToAngle(dms, afwGeom::degrees); } /** * @brief get the inclination of the ecliptic pole (obliquity) at epoch * */ afwGeom::Angle afwCoord::eclipticPoleInclination( double const epoch ///< desired epoch for inclination ) { double const T = (epoch - 2000.0)/100.0; return (23.0 + 26.0/60.0 + (21.448 - 46.82*T - 0.0006*T*T - 0.0018*T*T*T)/3600.0) * afwGeom::degrees; } /* ============================================================ * * class Coord * * ============================================================*/ /** * @brief Constructor for the Coord base class * */ afwCoord::Coord::Coord( lsst::afw::geom::Point2D const &p2d, ///< Point2D afwGeom::AngleUnit unit, ///< Rads, Degs, or Hrs double const epoch ///< epoch of coordinate ) : _longitude(NaN), _latitude(NaN), _epoch(epoch) { _longitude = afwGeom::Angle(p2d.getX(), unit); _longitude.wrap(); _latitude = afwGeom::Angle(p2d.getY(), unit); _verifyValues(); } /** * @brief Constructor for the Coord base class */ afwCoord::Coord::Coord( afwGeom::Point3D const &p3d, ///< Point3D double const epoch, ///< epoch of coordinate bool normalize, ///< normalize the p3d provided afwGeom::Angle const defaultLongitude ///< longitude to use if x=y=0 ) : _longitude(0. * afwGeom::radians), _latitude(0. * afwGeom::radians), _epoch(epoch) { std::pair lonLat = pointToLonLat(p3d, defaultLongitude, normalize); _longitude = lonLat.first; _latitude = lonLat.second; _epoch = epoch; } /** * @brief Constructor for the Coord base class * */ afwCoord::Coord::Coord( afwGeom::Angle const ra, ///< Right ascension, decimal degrees afwGeom::Angle const dec, ///< Declination, decimal degrees double const epoch ///< epoch of coordinate ) : _longitude(ra), _latitude(dec), _epoch(epoch) { _longitude.wrap(); _verifyValues(); } /** * @brief Constructor for the Coord base class * */ afwCoord::Coord::Coord( std::string const ra, ///< Right ascension, hh:mm:ss.s format std::string const dec, ///< Declination, dd:mm:ss.s format double const epoch ///< epoch of coordinate ) : _longitude(hmsStringToAngle(ra)), _latitude(dmsStringToAngle(dec)), _epoch(epoch) { _longitude.wrap(); _verifyValues(); } /** * @brief Default constructor for the Coord base class * * Set all values to NaN * Don't call _veriftyValues() method ... it'll fail. * */ afwCoord::Coord::Coord() : _longitude(afwGeom::Angle(NaN)), _latitude(afwGeom::Angle(NaN)), _epoch(NaN) {} /** * @brief Make sure the values we've got are in the range 0 <= x < 2PI */ void afwCoord::Coord::_verifyValues() const { if (_latitude.asRadians() < -afwGeom::HALFPI || _latitude.asRadians() > afwGeom::HALFPI) {
    448 737686e9 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    449 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ (boost::format("Latitude coord must be: -PI/2 <= lat <= PI/2 (%f).") % _latitude).str()); } } /** * @brief Reset our coordinates wholesale. * * This allows the user to instantiate Coords without values, and fill them later. */ void afwCoord::Coord::reset( afwGeom::Angle const longitude, ///< Longitude coord (eg. R.A. for Fk5) afwGeom::Angle const latitude, ///< Latitude coord (eg. Declination for Fk5) double const epoch ///< epoch of coordinate ) { _longitude = longitude; _latitude = latitude; _longitude.wrap(); _epoch = epoch; _verifyValues(); } /** * @brief Return our contents in a Point2D object * */ afwGeom::Point2D afwCoord::Coord::getPosition(afwGeom::AngleUnit unit) const { // treat HOURS specially, they must mean hours for RA, degrees for Dec if (unit == afwGeom::hours) { return afwGeom::Point2D(getLongitude().asHours(), getLatitude().asDegrees()); } else { return afwGeom::Point2D(getLongitude().asAngularUnits(unit), getLatitude().asAngularUnits(unit)); } } /** * @brief Return our contents in a position vector. * */ afwGeom::Point3D afwCoord::Coord::getVector() const { double lng = getLongitude(); double lat = getLatitude(); double const x = std::cos(lng) * std::cos(lat); double const y = std::sin(lng) * std::cos(lat); double const z = std::sin(lat); return afwGeom::Point3D(x, y, z); } /** * @brief Tranform our current coords to another spherical polar system * * Variable names assume an equaltorial/galactic tranform, but it works * for any spherical polar system when the appropriate poles are supplied. */ afwCoord::Coord afwCoord::Coord::transform( Coord const &poleTo, ///< Pole of the destination system in the current coords Coord const &poleFrom ///< Pole of the current system in the destination coords ) const { double const alphaGP = poleFrom[0]; double const deltaGP = poleFrom[1]; double const lCP = poleTo[0]; double const alpha = getLongitude(); double const delta = getLatitude(); afwGeom::Angle const l = (lCP - std::atan2(std::sin(alpha - alphaGP), std::tan(delta)*std::cos(deltaGP) - std::cos(alpha - alphaGP)*std::sin(deltaGP))) * afwGeom::radians; afwGeom::Angle const b = std::asin( (std::sin(deltaGP)*std::sin(delta) + std::cos(deltaGP)*std::cos(delta)*std::cos(alpha - alphaGP))) * afwGeom::radians; return Coord(l, b); } /** * @brief Rotate our current coords about a pole * */ void afwCoord::Coord::rotate( Coord const &axis, ///< axis of rotation (right handed) afwGeom::Angle const theta ///< angle to offset in radians ) { double const c = std::cos(theta); double const mc = 1.0 - c; double const s = std::sin(theta); // convert to cartesian afwGeom::Point3D const x = getVector(); afwGeom::Point3D const u = axis.getVector(); double const ux = u[0]; double const uy = u[1]; double const uz = u[2]; // rotate afwGeom::Point3D xprime; xprime[0] = (ux*ux + (1.0 - ux*ux)*c)*x[0] + (ux*uy*mc - uz*s)*x[1] + (ux*uz*mc + uy*s)*x[2]; xprime[1] = (uy*uy + (1.0 - uy*uy)*c)*x[1] + (uy*uz*mc - ux*s)*x[2] + (ux*uy*mc + uz*s)*x[0]; xprime[2] = (uz*uz + (1.0 - uz*uz)*c)*x[2] + (uz*ux*mc - uy*s)*x[0] + (uy*uz*mc + ux*s)*x[1]; // in-situ std::pair lonLat = pointToLonLat(xprime); _longitude = lonLat.first; _latitude = lonLat.second; } /** * @brief offset our current coords along a great circle defined by an angle wrt a declination parallel * * @note At/near the pole, longitude becomes degenerate with angle-wrt-declination. So * at the pole the offset will trace a meridian with longitude = 90 + longitude0 + phi * * @return the angle wrt a declination parallel at new position */ afwGeom::Angle afwCoord::Coord::offset( afwGeom::Angle const phi, ///< angle wrt parallel to offset afwGeom::Angle const arcLen ///< angle to offset ) { // let v = vector in the direction arcLen points (tangent to surface of sphere) // thus: |v| = arcLen // angle phi = orientation of v in a tangent plane, measured wrt to a parallel of declination // To do the rotation, use rotate() method. // - must provide an axis of rotation: take the cross product r x v to get that axis (pole) // get the vector r Eigen::Vector3d r = getVector().asEigen(); // Get the vector v: // let u = unit vector lying on a parallel of declination // let w = unit vector along line of longitude = r x u // the vector v must satisfy the following: // |v| = arcLen // r . v = 0 // u . v = |v| cos(phi) = arcLen*cos(phi) // w . v = |v| sin(phi) = arcLen*sin(phi) // v is a linear combination of u and w // v = arcLen*cos(phi)*u + arcLen*sin(phi)*w // Thus, we must: // - create u vector // - solve w vector (r cross u) // - compute v Eigen::Vector3d u; u << -std::sin(getLongitude()), std::cos(getLongitude()), 0.0; Eigen::Vector3d w = r.cross(u); Eigen::Vector3d v = arcLen * std::cos(phi)*u + arcLen * std::sin(phi)*w; // take r x v to get the axis Eigen::Vector3d axisVector = r.cross(v); axisVector.normalize(); Coord axisCoord = Coord(afwGeom::Point3D(axisVector), getEpoch()); rotate(axisCoord, arcLen); // now get the position angle at our destination // u2 . v2 = arcLen*cos(phi2) // w2 . v2 = arcLen*sin(phi2) // if we normalize v2: // phi2 = atan2(w2.v2, u2.v2) // // we need to compute u2, and then rotate v (exactly as we rotated r) to get v2 Eigen::Vector3d r2 = getVector().asEigen(); Eigen::Vector3d u2; u2 << -std::sin(getLongitude()), std::cos(getLongitude()), 0.0; Eigen::Vector3d w2 = r2.cross(u2); // make v a unit vector and rotate v exactly as we rotated r v.normalize(); Coord v2Coord = Coord(afwGeom::Point3D(v), getEpoch()); v2Coord.rotate(axisCoord, arcLen); Eigen::Vector3d v2 = v2Coord.getVector().asEigen(); afwGeom::Angle phi2 = std::atan2(w2.dot(v2), u2.dot(v2)) * afwGeom::radians; return phi2; } /** * @brief Convert to a specified Coord type. */ afwCoord::Coord::Ptr afwCoord::Coord::convert(CoordSystem system) const { switch (system) { case FK5: { Fk5Coord c1 = this->toFk5(); return boost::shared_ptr(new Fk5Coord(c1.getLongitude(), c1.getLatitude(), c1.getEpoch())); } break; case ICRS: { IcrsCoord c2 = this->toIcrs(); return boost::shared_ptr(new IcrsCoord(c2.getLongitude(), c2.getLatitude())); } break; case GALACTIC: { GalacticCoord c4 = this->toGalactic(); return boost::shared_ptr(new GalacticCoord(c4.getLongitude(), c4.getLatitude())); } break; case ECLIPTIC: { EclipticCoord c5 = this->toEcliptic(); return boost::shared_ptr(new EclipticCoord(c5.getLongitude(), c5.getLatitude(), c5.getEpoch())); } break; case TOPOCENTRIC:
    670 5b7a0990 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    671 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Cannot make Topocentric with convert() (must also specify Observatory).\n" "Instantiate TopocentricCoord() directly."); break; default:
    675 5b7a0990 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    676 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC allowed."); break; } } /** * @brief compute the angular separation between two Coords * */ afwGeom::Angle afwCoord::Coord::angularSeparation( Coord const &c ///< coordinate to compute our separation from ) const { // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic) // we'll put them in the same system. std::pair const& fk5 = commonFk5(*this, c); afwGeom::Angle const alpha1 = fk5.first.getRa(); afwGeom::Angle const delta1 = fk5.first.getDec(); afwGeom::Angle const alpha2 = fk5.second.getRa(); afwGeom::Angle const delta2 = fk5.second.getDec(); return haversine(alpha1 - alpha2, delta1 - delta2, std::cos(delta1), std::cos(delta2)); } /** * @brief Compute the offset from a coordinate * * The resulting angles are suitable for input to Coord::offset * * @return pair of Angles: bearing (angle wrt a declination parallel) and distance */ std::pair afwCoord::Coord::getOffsetFrom(afwCoord::Coord const &c ///< Coordinate from which to compute offset ) const { // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic) // we'll put them in the same system. std::pair const& fk5 = commonFk5(*this, c); afwGeom::Angle const alpha1 = fk5.first.getRa(); afwGeom::Angle const delta1 = fk5.first.getDec(); afwGeom::Angle const alpha2 = fk5.second.getRa(); afwGeom::Angle const delta2 = fk5.second.getDec(); afwGeom::Angle const dAlpha = alpha1-alpha2; afwGeom::Angle const dDelta = delta1-delta2; double const cosDelta1 = std::cos(delta1); double const cosDelta2 = std::cos(delta2); afwGeom::Angle separation = haversine(dAlpha, dDelta, cosDelta1, cosDelta2); // Formula from http://www.movable-type.co.uk/scripts/latlong.html double const y = std::sin(dAlpha)*cosDelta2; double const x = cosDelta1*std::sin(delta2) - std::sin(delta1)*cosDelta2*std::cos(dAlpha); afwGeom::Angle bearing = std::atan2(y, x)*afwGeom::radians - 90.0*afwGeom::degrees; return std::make_pair(bearing, separation); } /** * @brief Get the offset on the tangent plane * * This is suitable only for small angles. * * @return pair of Angles: Longitude and Latitude offsets */ std::pair afwCoord::Coord::getTangentPlaneOffset(afwCoord::Coord const &c ///< Coordinate from which to compute offset ) const { // work in Fk5, no matter what two derived classes we're given (eg Fk5 and Galactic) // we'll put them in the same system. std::pair const& fk5 = commonFk5(*this, c); afwGeom::Angle const alpha1 = fk5.first.getRa(); afwGeom::Angle const delta1 = fk5.first.getDec(); afwGeom::Angle const alpha2 = fk5.second.getRa(); afwGeom::Angle const delta2 = fk5.second.getDec(); // This is a projection of coord2 to the tangent plane at coord1 double const sinDelta1 = std::sin(delta1); double const cosDelta1 = std::cos(delta1); double const sinDelta2 = std::sin(delta2); double const cosDelta2 = std::cos(delta2); double const cosAlphaDiff = std::cos(alpha2 - alpha1); double const sinAlphaDiff = std::sin(alpha2 - alpha1); double const div = cosDelta1 * cosAlphaDiff * cosDelta2 + sinDelta1 * sinDelta2; double const xi = cosDelta1 * sinAlphaDiff / div; double const eta = (cosDelta1 * cosAlphaDiff * sinDelta2 - sinDelta1 * cosDelta2) / div; return std::make_pair(xi*afwGeom::radians, eta*afwGeom::radians); } /** * @brief Convert ourself to Fk5: RA, Dec (precess to new epoch) */ afwCoord::Fk5Coord afwCoord::Coord::toFk5(double const epoch) const { return Fk5Coord(getLongitude(), getLatitude(), getEpoch()).precess(epoch); } /** * @brief Convert ourself to Fk5: RA, Dec (use current epoch) */ afwCoord::Fk5Coord afwCoord::Coord::toFk5() const { return Fk5Coord(getLongitude(), getLatitude(), getEpoch()); } /** * @brief Convert ourself to ICRS: RA, Dec (basically J2000) * */ afwCoord::IcrsCoord afwCoord::Coord::toIcrs() const { return this->toFk5().toIcrs(); } /** * @brief Convert ourself to Galactic: l, b */ afwCoord::GalacticCoord afwCoord::Coord::toGalactic() const { return this->toFk5().toGalactic(); } /** * @brief Convert ourself to Ecliptic: lambda, beta (precess to new epoch) */ afwCoord::EclipticCoord afwCoord::Coord::toEcliptic(double const epoch) const { return this->toFk5(epoch).toEcliptic(); } /** * @brief Convert ourself to Ecliptic: lambda, beta (use existing epoch) */ afwCoord::EclipticCoord afwCoord::Coord::toEcliptic() const { return this->toFk5().toEcliptic(); } /** * @brief Convert ourself to Altitude/Azimuth: alt, az */ afwCoord::TopocentricCoord afwCoord::Coord::toTopocentric( Observatory const &obs, ///< observatory of observation lsst::daf::base::DateTime const &obsDate ///< date of observation ) const { return this->toFk5().toTopocentric(obs, obsDate); } /* ============================================================ * * class Fk5Coord * * ============================================================*/ /** * @brief Convert ourself to Fk5 (ie. a no-op): RA, Dec (precess to new epoch) */ afwCoord::Fk5Coord afwCoord::Fk5Coord::toFk5(double const epoch) const { return Fk5Coord(getLongitude(), getLatitude(), getEpoch()).precess(epoch); } /** * @brief Convert ourself to Fk5 (ie. a no-op): RA, Dec (keep current epoch) */ afwCoord::Fk5Coord afwCoord::Fk5Coord::toFk5() const { return Fk5Coord(getLongitude(), getLatitude(), getEpoch()); } /** * @brief Convert ourself to ICRS: RA, Dec (basically J2000) * */ afwCoord::IcrsCoord afwCoord::Fk5Coord::toIcrs() const { // only do the precession to 2000 if we're not already there. if ( fabs(getEpoch() - 2000.0) > epochTolerance ) { afwCoord::Fk5Coord c = precess(2000.0); return IcrsCoord(c.getLongitude(), c.getLatitude()); } else { return IcrsCoord(getLongitude(), getLatitude()); } } /** * @brief Convert ourself to Galactic: l, b */ afwCoord::GalacticCoord afwCoord::Fk5Coord::toGalactic() const { // if we're epoch==2000, we can transform, otherwise we need to precess first Fk5Coord c; if ( fabs(getEpoch() - 2000.0) > epochTolerance ) { c = precess(2000.0); } else { c = *this; } Coord ct = c.transform(Fk5PoleInGalactic(), GalacticPoleInFk5()); return GalacticCoord(ct.getLongitude(), ct.getLatitude()); } /** * @brief Convert ourself to Ecliptic: lambda, beta (precess to new epoch) */ afwCoord::EclipticCoord afwCoord::Fk5Coord::toEcliptic(double const epoch) const { afwGeom::Angle const eclPoleIncl = eclipticPoleInclination(epoch); Coord const eclPoleInEquatorial(270.0 * afwGeom::degrees, (90.0 * afwGeom::degrees) - eclPoleIncl, epoch); Coord const equPoleInEcliptic(90.0 * afwGeom::degrees, (90.0 * afwGeom::degrees) - eclPoleIncl, epoch); Coord c = transform(equPoleInEcliptic, eclPoleInEquatorial); return EclipticCoord(c.getLongitude(), c.getLatitude(), epoch); } /** * @brief Convert ourself to Ecliptic: lambda, beta (use current epoch) */ afwCoord::EclipticCoord afwCoord::Fk5Coord::toEcliptic() const { return this->toEcliptic(getEpoch()); } /** * @brief Convert ourself to Altitude/Azimuth: alt, az */ afwCoord::TopocentricCoord afwCoord::Fk5Coord::toTopocentric( Observatory const &obs, ///< observatory lsst::daf::base::DateTime const &obsDate ///< date of obs. ) const { // make sure we precess to the epoch Fk5Coord fk5 = precess(obsDate.get(dafBase::DateTime::EPOCH)); // greenwich sidereal time afwGeom::Angle theta0 = meanSiderealTimeGreenwich(obsDate.get(dafBase::DateTime::JD)); theta0.wrap(); // lat/long of the observatory afwGeom::Angle const phi = obs.getLatitude(); afwGeom::Angle const L = obs.getLongitude(); // ra/dec of the target afwGeom::Angle const alpha = fk5.getRa(); afwGeom::Angle const delta = fk5.getDec(); afwGeom::Angle const H = theta0 + L - alpha; // compute the altitude, h double const sinh = std::sin(phi)* std::sin(delta) + std::cos(phi) * std::cos(delta) * std::cos(H); afwGeom::Angle const h = std::asin(sinh) * afwGeom::radians; // compute the azimuth, A double const tanAnumerator = std::sin(H); double const tanAdenominator = (std::cos(H) * std::sin(phi) - std::tan(delta) * std::cos(phi)); // Equations used here assume azimuth is with respect to South // but we use the North as our origin ... must add 180 deg afwGeom::Angle A = (180.0*afwGeom::degrees) + atan2(tanAnumerator, tanAdenominator)* afwGeom::radians; A.wrap(); return TopocentricCoord(A, h, obsDate.get(dafBase::DateTime::EPOCH), obs); } /** * @brief Precess ourselves from whence we are to a new epoch * */ afwCoord::Fk5Coord afwCoord::Fk5Coord::precess( double const epochTo ///< epoch to precess to ) const { // return a copy if the epochs are the same if ( fabs(getEpoch() - epochTo) < epochTolerance) { return Fk5Coord(getLongitude(), getLatitude(), getEpoch()); } dafBase::DateTime const dateFrom(getEpoch(), dafBase::DateTime::EPOCH, dafBase::DateTime::TAI); dafBase::DateTime const dateTo(epochTo, dafBase::DateTime::EPOCH, dafBase::DateTime::TAI); double const jd0 = dateFrom.get(dafBase::DateTime::JD); double const jd = dateTo.get(dafBase::DateTime::JD); double const T = (jd0 - JD2000)/36525.0; double const t = (jd - jd0)/36525.0; double const tt = t*t; double const ttt = tt*t; afwGeom::Angle const xi = ((2306.2181 + 1.39656*T - 0.000139*T*T)*t + (0.30188 - 0.000344*T)*tt + 0.017998*ttt) * afwGeom::arcseconds; afwGeom::Angle const z = ((2306.2181 + 1.39656*T - 0.000139*T*T)*t + (1.09468 + 0.000066*T)*tt + 0.018203*ttt) * afwGeom::arcseconds; afwGeom::Angle const theta = ((2004.3109 - 0.85330*T - 0.000217*T*T)*t - (0.42665 + 0.000217*T)*tt - 0.041833*ttt) * afwGeom::arcseconds; Fk5Coord fk5 = this->toFk5(); afwGeom::Angle const alpha0 = fk5.getRa(); afwGeom::Angle const delta0 = fk5.getDec(); double const a = std::cos(delta0) * std::sin((alpha0 + xi)); double const b = std::cos(theta) * std::cos(delta0) * std::cos((alpha0 + xi)) - std::sin(theta) * std::sin(delta0); double const c = std::sin(theta) * std::cos(delta0) * std::cos((alpha0 + xi)) + std::cos(theta) * std::sin(delta0); afwGeom::Angle const alpha = (std::atan2(a,b) + z) * afwGeom::radians; afwGeom::Angle const delta = std::asin(c) * afwGeom::radians; return Fk5Coord(alpha, delta, epochTo); } /* ============================================================ * * class IcrsCoord * * ============================================================*/ /** * @brief special reset() overload to make sure no epoch can be set */ void afwCoord::IcrsCoord::reset(afwGeom::Angle const longitude, afwGeom::Angle const latitude) { Coord::reset(longitude, latitude, 2000.0); } /** * @brief Fk5 converter for IcrsCoord. (specify epoch) */ afwCoord::Fk5Coord afwCoord::IcrsCoord::toFk5(double const epoch) const { return Fk5Coord(getLongitude(), getLatitude(), 2000.0).precess(epoch); } /** * @brief Fk5 converter for IcrsCoord. (no epoch specified) */ afwCoord::Fk5Coord afwCoord::IcrsCoord::toFk5() const { return Fk5Coord(getLongitude(), getLatitude(), 2000.0); } /** * @brief Icrs converter for IcrsCoord. (ie. a no-op) */ afwCoord::IcrsCoord afwCoord::IcrsCoord::toIcrs() const { return IcrsCoord(getLongitude(), getLatitude()); } /* ============================================================ * * class GalacticCoord * * ============================================================*/ /** * @brief special reset() overload to make sure no epoch can be set */ void afwCoord::GalacticCoord::reset(afwGeom::Angle const longitudeDeg, afwGeom::Angle const latitudeDeg) { Coord::reset(longitudeDeg, latitudeDeg, 2000.0); } /** * @brief Convert ourself from galactic to Fk5 (specify epoch) */ afwCoord::Fk5Coord afwCoord::GalacticCoord::toFk5(double const epoch) const { // transform to fk5 // galactic coords are ~constant, and the poles used are for epoch=2000, so we get J2000 Coord c = transform(GalacticPoleInFk5(), Fk5PoleInGalactic()); return Fk5Coord(c.getLongitude(), c.getLatitude(), 2000.0).precess(epoch); } /** * @brief Convert ourself from galactic to Fk5 (no epoch specified) */ afwCoord::Fk5Coord afwCoord::GalacticCoord::toFk5() const { return this->toFk5(2000.0); } /** * @brief Convert ourself from Galactic to Galactic ... a no-op */ afwCoord::GalacticCoord afwCoord::GalacticCoord::toGalactic() const { return GalacticCoord(getLongitude(), getLatitude()); } /* ============================================================ * * class EclipticCoord * * ============================================================*/ /** * @brief Convert ourself from Ecliptic to Ecliptic ... a no-op (but precess to new epoch) */ afwCoord::EclipticCoord afwCoord::EclipticCoord::toEcliptic(double const epoch) const { return EclipticCoord(getLongitude(), getLatitude(), getEpoch()).precess(epoch); } /** * @brief Convert ourself from Ecliptic to Ecliptic ... a no-op (use the current epoch) */ afwCoord::EclipticCoord afwCoord::EclipticCoord::toEcliptic() const { return EclipticCoord(getLongitude(), getLatitude(), getEpoch()); } /** * @brief Convert ourself from Ecliptic to Fk5 (precess to new epoch) */ afwCoord::Fk5Coord afwCoord::EclipticCoord::toFk5(double const epoch) const { afwGeom::Angle const eclPoleIncl = eclipticPoleInclination(epoch); afwGeom::Angle ninety = 90. * afwGeom::degrees; Coord const eclipticPoleInFk5(270.0 * afwGeom::degrees, ninety - eclPoleIncl, epoch); Coord const fk5PoleInEcliptic(ninety, ninety - eclPoleIncl, epoch); Coord c = transform(eclipticPoleInFk5, fk5PoleInEcliptic); return Fk5Coord(c.getLongitude(), c.getLatitude(), epoch); } /** * @brief Convert ourself from Ecliptic to Fk5 (use current epoch) */ afwCoord::Fk5Coord afwCoord::EclipticCoord::toFk5() const { return this->toFk5(getEpoch()); } /** * @brief precess to new epoch * * Do this by going through fk5 */ afwCoord::EclipticCoord afwCoord::EclipticCoord::precess( double const epochTo ///< epoch to precess to. ) const { return this->toFk5().precess(epochTo).toEcliptic(); } /* ============================================================ * * class TopocentricCoord * * ============================================================*/ /** * @brief Convert ourself from Topocentric to Fk5 */ afwCoord::Fk5Coord afwCoord::TopocentricCoord::toFk5(double const epoch) const { afwGeom::Angle const phi = _obs.getLatitude(); afwGeom::Angle const L = _obs.getLongitude(); // Equations used here assume azimuth is with respect to South // but we use the North as our origin. afwGeom::Angle A = getAzimuth() + 180.0*afwGeom::degrees; A.wrap(); afwGeom::Angle const h = getAltitude(); double const jd = dafBase::DateTime(epoch, dafBase::DateTime::EPOCH, dafBase::DateTime::TAI).get(dafBase::DateTime::JD); afwGeom::Angle theta0 = meanSiderealTimeGreenwich(jd); theta0.wrap(); double const tanHnum = std::sin(A); double const tanHdenom = std::cos(A)*std::sin(phi) + std::tan(h)*std::cos(phi); afwGeom::Angle H = std::atan2(tanHnum, tanHdenom) * afwGeom::radians; afwGeom::Angle const alpha = theta0 + L - H; double const sinDelta = std::sin(phi)*std::sin(h) - std::cos(phi)*std::cos(h)*std::cos(A); afwGeom::Angle const delta = (std::asin(sinDelta)) * afwGeom::radians; return Fk5Coord(alpha, delta, epoch); } /** * @brief Convert outself from Topocentric to Fk5 (use current epoch) */ afwCoord::Fk5Coord afwCoord::TopocentricCoord::toFk5() const { return this->toFk5(getEpoch()); } /** * @brief Convert ourself from Topocentric to Topocentric ... a no-op */ afwCoord::TopocentricCoord afwCoord::TopocentricCoord::toTopocentric( lsst::afw::coord::Observatory const &obs, ///< observatory of observation lsst::daf::base::DateTime const &date ///< date of observation ) const { if (obs != _obs) {
    1168 cf7af3d5 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1169 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ (boost::format("Expected observatory %s, saw %s") % _obs % obs).str()); } if (fabs(date.get() - getEpoch()) > std::numeric_limits::epsilon()) {
    1172 cf7af3d5 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1173 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ (boost::format("Expected date %g, saw %g") % getEpoch() % date.get()).str()); } return TopocentricCoord(getLongitude(), getLatitude(), getEpoch(), _obs); } /** * @brief Convert ourself from Topocentric to Topocentric with no observatory or date arguments * * As this is essentially a copy-constructor, the extra info can be obtained internally. */ afwCoord::TopocentricCoord afwCoord::TopocentricCoord::toTopocentric() const { return TopocentricCoord(getLongitude(), getLatitude(), getEpoch(), _obs); } /* =============================================================================== * * Factory function definitions: * * Each makeCoord() function has overloaded variants with and without epoch specified. * It was tempting to specify default values, but some coordinate systems have * no epoch, and this would be confusing to the user. In its current form, * any epochless coordinate system requested with an epoch specified will throw an exception. * The epochless factories will always work, but assume default epoch = 2000. * * =============================================================================== */ /** * @brief Factory function to create a Coord of arbitrary type with decimal RA,Dec * * @note This factory allows the epoch to be specified but will throw if used with ICRS or Galactic * @note Most of the other factories (which accept epochs) just call this one indirectly. * */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system, ///< the system (equ, fk5, galactic ..) afwGeom::Angle const ra, ///< right ascension afwGeom::Angle const dec, ///< declination double const epoch ///< epoch of coordinate ) { switch (system) { case FK5: return boost::shared_ptr(new Fk5Coord(ra, dec, epoch)); break; case ICRS:
    1222 b5487454 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1223 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "ICRS has no epoch, use overloaded makeCoord with args (system, ra, dec)."); break; case GALACTIC:
    1226 b5487454 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1227 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Galactic has no epoch, use overloaded makeCoord with (system, ra, dec)."); break; case ECLIPTIC: return boost::shared_ptr(new EclipticCoord(ra, dec, epoch)); break; case TOPOCENTRIC:
    1233 b5487454 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1234 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n" "Instantiate TopocentricCoord() directly."); break; default:
    1238 b5487454 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1239 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, and TOPOCENTRIC allowed."); break; } } /** * @brief Factory function to create a Coord of arbitrary type with decimal RA,Dec in degrees * * @note This factory assumes a default epoch * @note Most of the other factories (which don't accept epoch) call this one. */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system, ///< the system (equ, fk5, galactic ..) afwGeom::Angle const ra, ///< right ascension afwGeom::Angle const dec ///< declination ) { switch (system) { case FK5: return boost::shared_ptr(new Fk5Coord(ra, dec, 2000.0)); break; case ICRS: return boost::shared_ptr(new IcrsCoord(ra, dec)); break; case GALACTIC: return boost::shared_ptr(new GalacticCoord(ra, dec)); break; case ECLIPTIC: return boost::shared_ptr(new EclipticCoord(ra, dec, 2000.0)); break; case TOPOCENTRIC:
    1274 ad9e652d - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1275 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n" "Instantiate TopocentricCoord() directly."); break; default:
    1279 ad9e652d - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1280 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, and TOPOCENTRIC allowed."); break; } } /** * @brief Factory function to create a Coord of arbitrary type with a Point3D * * @note This factory accepts epoch. There is an overloaded version which uses a default. * */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system, ///< the system (equ, fk5, galactic ..) lsst::afw::geom::Point3D const &p3d, ///< the coord in Point3D format double const epoch, ///< epoch of coordinate bool normalize, ///< normalize the p3d provided afwGeom::Angle const defaultLongitude ///< longitude to use if x=y=0 ) { Coord c(p3d, 2000.0, normalize, defaultLongitude); return makeCoord(system, c.getLongitude(), c.getLatitude(), epoch); } /** * @brief Factory function to create a Coord of arbitrary type with a Point3D * * @note This factory uses a default epoch. There is an overloaded version which accepts an epoch. * */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system, ///< the system (equ, fk5, galactic ..) lsst::afw::geom::Point3D const &p3d, ///< the coord in Point3D format bool normalize, ///< normalize the p3d provided afwGeom::Angle const defaultLongitude ///< longitude to use if x=y=0 ) { Coord c(p3d, 2000.0, normalize, defaultLongitude); return makeCoord(system, c.getLongitude(), c.getLatitude()); } /** * @brief Factory function to create a Coord of arbitrary type with Point2D * * @note This factory accepts epoch. There is an overloaded version which uses a default. */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system, ///< the system (equ, fk5, galactic ..) lsst::afw::geom::Point2D const &p2d, ///< the (eg) ra,dec in a Point2D afwGeom::AngleUnit unit, ///< the units (eg. degrees, radians) double const epoch ///< epoch of coordinate ) { if (unit == afwGeom::hours) { return makeCoord(system, afwGeom::Angle(p2d.getX(), afwGeom::hours), afwGeom::Angle(p2d.getY(), afwGeom::degrees), epoch); } else { return makeCoord(system, afwGeom::Angle(p2d.getX(), unit), afwGeom::Angle(p2d.getY(), unit), epoch); } } /** * @brief Factory function to create a Coord of arbitrary type with Point2D * * @note This factory uses a default epoch. There is an overloaded version which accepts an epoch. * */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system, ///< the system (equ, fk5, galactic ..) lsst::afw::geom::Point2D const &p2d, ///< the (eg) ra,dec in a Point2D afwGeom::AngleUnit unit ///< the units (eg. degrees, radians) ) { if (unit == afwGeom::hours) { return makeCoord(system, afwGeom::Angle(p2d.getX(), afwGeom::hours), afwGeom::Angle(p2d.getY(), afwGeom::degrees)); } else { return makeCoord(system, afwGeom::Angle(p2d.getX(), unit), afwGeom::Angle(p2d.getY(), unit)); } } /** * @brief Factory function to create a Coord of arbitrary type with string RA [in degrees, not hours!], Dec * * @note This factory accepts epoch. There is an overloaded version which uses a default. */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system, ///< the system (equ, fk5, galactic ..) std::string const ra, ///< right ascension std::string const dec, ///< declination double const epoch ///< epoch of coordinate ) { return makeCoord(system, dmsStringToAngle(ra), dmsStringToAngle(dec), epoch); } /** * @brief Factory function to create a Coord of arbitrary type with string RA [in degrees, not hours!], Dec * * @note This factory uses a default epoch. There is an overloaded version which accepts an epoch. */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system, ///< the system (equ, fk5, galactic ..) std::string const ra, ///< right ascension std::string const dec ///< declination ) { return makeCoord(system, dmsStringToAngle(ra), dmsStringToAngle(dec)); } /** * @brief Lightweight factory to make an empty coord. */ afwCoord::Coord::Ptr afwCoord::makeCoord( CoordSystem const system ///< the system (FK5, ICRS, etc) ) { switch (system) { case FK5: return boost::shared_ptr(new Fk5Coord()); break; case ICRS: return boost::shared_ptr(new IcrsCoord()); break; case GALACTIC: return boost::shared_ptr(new GalacticCoord()); break; case ECLIPTIC: return boost::shared_ptr(new EclipticCoord()); break; case TOPOCENTRIC:
    1405 7d972731 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1406 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Cannot make Topocentric with makeCoord() (must also specify Observatory).\n" "Instantiate TopocentricCoord() directly."); break; default:
    1410 7d972731 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    1411 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "Undefined CoordSystem: only FK5, ICRS, GALACTIC, ECLIPTIC, allowed."); break; } } std::ostream & afwCoord::operator<<(std::ostream & os, afwCoord::Coord const & coord) {
    1418 14a984bc - return os << coord.getPosition() << "@" << coord.getEpoch();
    1419 4d62652f + auto const className = coord.getClassName();
    1420 4d62652f + os << (boost::format("%s(%.7f, %.7f")
    1421 4d62652f + % className
    1422 4d62652f + % coord[0].asDegrees()
    1423 4d62652f + % coord[1].asDegrees()).str();
    1424 4d62652f + if (className == "TopocentricCoord") {
    1425 4d62652f + os << (boost::format(", %.12f, (%s)")
    1426 4d62652f + % coord.getEpoch()
    1427 4d62652f + % dynamic_cast(coord).getObservatory()).str();
    1428 4d62652f + } else if (className != "IcrsCoord" && className != "GalacticCoord") {
    1429 4d62652f + os << (boost::format(", %.2f") % coord.getEpoch()).str();
    1430 4d62652f + }
    1431 4d62652f + os << ")";
    1432 4d62652f + return os;
    }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ad9e652d

    commit ad9e652d37eb8a8caf2feae975152f1a9c80d473
    Author: bick 
    Date:   Thu Mar 11 18:32:40 2010 +0000
    
        Added factory functions.
    

    cf7af3d5

    commit cf7af3d516d5901501013fc2c26e6afbd475098c
    Author: rhl 
    Date:   Thu Jun 3 00:23:50 2010 +0000
    
        Use boost::format not sprintf;  check that arguments afwCoord::TopocentricCoord::toTopocentric are correct instead of just ignoring them;  add methods to Observatory to support this; #1254
    

    7d972731

    commit 7d9727319e47f4d2407991b04e1dec2de3a690d2
    Author: bick 
    Date:   Sat Mar 20 23:06:15 2010 +0000
    
        Added Equatorial (identical to Icrs). Got factories working right.
    

    721f7910

    commit 721f7910168d6650f5f6c3892a329bd775dc38a6
    Author: Paul Price 
    Date:   Sun Jun 2 21:22:40 2013 -0400
    
        Coord: check inputs to xmsStringToAngle (#2915)
        
        In particular, the array size wasn't being checked, which
        caused SEGVs.  Also added check that the input is in
        xx:mm::ss format.
    

    29df7008

    commit 29df7008c846afeffa2dea8c96e9923903ed8c86
    Author: bick 
    Date:   Thu Mar 25 22:48:33 2010 +0000
    
        #1188 Inlined some accessors.  Added exception for makeCoordEnum.
    

    5b7a0990

    commit 5b7a0990e31d2075db774907d8b5ca7670fae77e
    Author: bick 
    Date:   Sun Mar 21 20:52:09 2010 +0000
    
        Added generic convert() method.  More tests.
    

    14a984bc

    commit 14a984bcec6252a9f72e4398d3df5af84f0c9814
    Author: price 
    Date:   Tue Apr 26 19:08:01 2011 +0000
    
        Adding stream output for Coord.
    

    737686e9

    commit 737686e982a00f0b9d9d8e021d45b4e90f3cc4ea
    Author: bick 
    Date:   Sat Mar 6 01:53:37 2010 +0000
    
        check-in for basic coord tools.  Much editing yet to do.
    

    b5487454

    commit b54874549a26c43dd8d462562e35c20c98a7428d
    Author: bick 
    Date:   Wed Mar 24 18:38:03 2010 +0000
    
        #1188 removed Equatorial class, added epochless factory functions.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    4d62652f

    commit 4d62652fa86a1c53d99c71ca845d3ea3af63565f
    Author: Russell Owen 
    Date:   Wed Apr 22 16:57:18 2015 -0700
    
        Improved string representations of Coords
        
        Improved os << Coord (in C++) and Coord.__str__ and __repr__ in Python
        for Coord and all subclasses, as follows:
        - The coordinate system is shown, even for clones (without the need to cast)
        - Positions are in degrees, instead of radians
        - IcrsCoord and GalacticCoord do not show the epoch
        - TopocentricCoord now has string representations, and the data includes Observatory
        - Coord.__str__ now uses C++ os << Coord, for simplicity and uniformity
        - Coord.__repr__ shows numbers (except observatory to full precision
          (except for observatory data for TopocentricCoord, since it didn't seem worth the extra clutter).
        - Coord.__repr__ omits the leading "afwCoord."
        
        Note: I would prefer to make Coord.__repr__ the same as __str__
        but it was more detailed so I left that feature.
        
        Make Coord.__str__ use << and add observatory information for topo
    

    Return to list

    lib/libafw.so-gdb.py

    Diff:

                    import os, os.path, sys
    
    2 ed95653a + import lsst.utils
    import gdb # # Adjust the load path to include lsst.gdb, bypassing the regular lsstimport mechanism as # the version of python running within gdb may not be the same as we are using for lsst processing #
    8 ed95653a + try:
    9 ed95653a + afwDir = lsst.utils.getPackageDir('afw')
    10 ed95653a + except Exception:
    11 ed95653a + pass
    12 ed95653a + else:
    7 9d75da31 - printerDir = os.path.join(os.environ["AFW_DIR"], "python", "lsst", "gdb")
    ? ^^^^^^ -------------
    13 ed95653a + printerDir = os.path.join(afwDir, "python", "lsst", "gdb")
    ? ++++ ^^^^
    8 9d75da31 - if printerDir not in sys.path:
    14 ed95653a + if printerDir not in sys.path:
    ? ++++
    9 9d75da31 - sys.path.append(printerDir)
    15 ed95653a + sys.path.append(printerDir)
    ? ++++ import afw.printers afw.printers.register(gdb.current_objfile())

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9d75da31

    commit 9d75da31a13fb65f7130388d428819a7df7bef0d
    Author: rhl 
    Date:   Sun May 22 21:25:50 2011 +0000
    
        Redid the gdb+python plumbing in a way that should permit the system/gdb and lsst pythons to be different
    

    Commits in /Users/nate/repos_lsst/afw/

    ed95653a

    commit ed95653aae0db5c64fec82321af822db861c9e9c
    Author: Joshua Hoblitt 
    Date:   Thu May 21 14:38:34 2015 -0700
    
        replace eups.productDir() calls with lsst.utils.getPackageDir()
    

    Return to list

    tests/maskedImage.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for MaskedImages Run with: python MaskedImage.py or python >>> import MaskedImage; MaskedImage.run() """ import os
    36 a3819593 -
    import unittest
    39 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests import lsst.pex.exceptions import lsst.daf.base import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.afw.math as afwMath
    45 f8edfe90 - import eups
    import lsst.afw.display.ds9 as ds9 try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class MaskedImageTestCase(unittest.TestCase): """A test case for MaskedImage""" def setUp(self): self.imgVal1, self.varVal1 = 100.0, 10.0 self.imgVal2, self.varVal2 = 200.0, 15.0 self.mimage = afwImage.MaskedImageF(100, 200) self.mimage.getImage().set(self.imgVal1) # # Set center of mask to 0, with 2 pixel border set to EDGE # self.BAD = afwImage.MaskU_getPlaneBitMask("BAD") self.EDGE = afwImage.MaskU_getPlaneBitMask("EDGE") self.mimage.getMask().set(self.EDGE) centre = afwImage.MaskU( self.mimage.getMask(), afwGeom.Box2I(afwGeom.Point2I(2, 2), self.mimage.getDimensions() - afwGeom.Extent2I(4)), afwImage.LOCAL) centre.set(0x0) # self.mimage.getVariance().set(self.varVal1) # # Second MaskedImage # self.mimage2 = afwImage.MaskedImageF(self.mimage.getDimensions()) self.mimage2.getImage().set(self.imgVal2) self.mimage2.getVariance().set(self.varVal2) # # a Function2 # self.function = afwMath.PolynomialFunction2D(2) self.function.setParameters(range(self.function.getNParameters())) def tearDown(self): del self.mimage del self.mimage2 del self.function def testArrays(self): image, mask, variance = self.mimage.getArrays() self.assert_((self.mimage.getImage().getArray() == image).all()) self.assert_((self.mimage.getMask().getArray() == mask).all()) self.assert_((self.mimage.getVariance().getArray() == variance).all()) mimage2 = afwImage.makeMaskedImageFromArrays(image, mask, variance) self.assertEqual(type(mimage2), type(self.mimage)) def testSetGetValues(self): self.assertEqual(self.mimage.get(0, 0), (self.imgVal1, self.EDGE, self.varVal1)) self.assertEqual(self.mimage.getMask().get(1, 1), self.EDGE) self.assertEqual(self.mimage.getMask().get(2, 2), 0x0) def testMaskedImageFromImage(self): w, h = 10, 20 dims = afwGeom.Extent2I(w, h) im, mask, var = afwImage.ImageF(dims), afwImage.MaskU(dims), afwImage.ImageF(dims) im.set(666) maskedImage = afwImage.MaskedImageF(im, mask, var) maskedImage = afwImage.makeMaskedImage(im, mask, var) maskedImage = afwImage.MaskedImageF(im) self.assertEqual(im.getDimensions(), maskedImage.getImage().getDimensions()) self.assertEqual(im.getDimensions(), maskedImage.getMask().getDimensions()) self.assertEqual(im.getDimensions(), maskedImage.getVariance().getDimensions()) self.assertEqual(maskedImage.get(0, 0), (im.get(0, 0), 0x0, 0.0)) def testMakeMaskedImageXY0(self): """Test that makeMaskedImage sets XY0 correctly""" im = afwImage.ImageF(200, 300) xy0 = afwGeom.PointI(10, 20) im.setXY0(*xy0) mi = afwImage.makeMaskedImage(im) self.assertEqual(mi.getImage().getXY0(), xy0) self.assertEqual(mi.getMask().getXY0(), xy0) self.assertEqual(mi.getVariance().getXY0(), xy0) def testCopyMaskedImage(self): """Test copy constructor""" # # shallow copy # mi = self.mimage.Factory(self.mimage, False) val00 = self.mimage.get(0, 0) nval00 = (100, 0xff, -1) # the new value we'll set self.assertNotEqual(val00, nval00) self.assertEqual(mi.get(0, 0), val00) mi.set(0, 0, nval00) self.assertEqual(self.mimage.get(0, 0), nval00) self.assertEqual(mi.get(0, 0), nval00) mi.set(0, 0, val00) # reinstate initial value # # deep copy # mi = self.mimage.Factory(self.mimage, True) self.assertEqual(mi.get(0, 0), val00) mi.set(0, 0, nval00) self.assertEqual(self.mimage.get(0, 0), val00) self.assertEqual(mi.get(0, 0), nval00) # # Copy with change of Image type # mi = self.mimage.convertD() self.assertEqual(mi.get(0, 0), val00) mi.set(0, 0, nval00) self.assertEqual(self.mimage.get(0, 0), val00) self.assertEqual(mi.get(0, 0), nval00) # # Convert from U to F # mi = afwImage.MaskedImageU(afwGeom.Extent2I(10, 20)) val00 = (10, 0x10, 1) mi.set(val00) self.assertEqual(mi.get(0, 0), val00) fmi = mi.convertF() self.assertEqual(fmi.get(0, 0), val00) def testAddImages(self): "Test addition" # add an image self.mimage2 += self.mimage self.assertEqual(self.mimage2.get(0, 0), (self.imgVal1 + self.imgVal2, self.EDGE, self.varVal1 + self.varVal2)) # Add an Image to a MaskedImage mimage_i = afwImage.MaskedImageI(self.mimage2.getDimensions()) mimage_i.set(900, 0x0, 1000.0) image_i = afwImage.ImageI(mimage_i.getDimensions(), 2) mimage_i += image_i self.assertEqual(mimage_i.get(0, 0), (902, 0x0, 1000.0)) # add a scalar self.mimage += self.imgVal1 self.assertEqual(self.mimage.get(0, 0), (2*self.imgVal1, self.EDGE, self.varVal1)) self.assertEqual(self.mimage.getMask().get(1, 1), self.EDGE) self.assertEqual(self.mimage.getMask().get(2, 2), 0x0) # add a function self.mimage.set(self.imgVal1, 0x0, 0.0) self.mimage += self.function for i, j in [(2, 3)]: self.assertEqual(self.mimage.getImage().get(i, j), self.imgVal1 + self.function(i, j)) def testAddScaledImages(self): "Test addition by a scaled MaskedImage" # add an image c = 10.0 mimage2_copy = self.mimage2.Factory(self.mimage2, True) # make a copy self.mimage2.scaledPlus(c, self.mimage) # # Now repeat calculation using a temporary # tmp = self.mimage.Factory(self.mimage, True) tmp *= c mimage2_copy += tmp self.assertEqual(self.mimage2.get(0, 0), mimage2_copy.get(0, 0)) def testSubtractImages(self): "Test subtraction" # subtract an image self.mimage2 -= self.mimage self.assertEqual(self.mimage2.get(0, 0), (self.imgVal2 - self.imgVal1, self.EDGE, self.varVal2 + self.varVal1)) # Subtract an Image from a MaskedImage mimage_i = afwImage.MaskedImageI(self.mimage2.getDimensions()) mimage_i.set(900, 0x0, 1000.0) image_i = afwImage.ImageI(mimage_i.getDimensions(), 2) mimage_i -= image_i self.assertEqual(mimage_i.get(0, 0), (898, 0x0, 1000.0)) # subtract a scalar self.mimage -= self.imgVal1 self.assertEqual(self.mimage.get(0, 0), (0.0, self.EDGE, self.varVal1)) def testSubtractScaledImages(self): "Test subtraction by a scaled MaskedImage" # subtract a scaled image c = 10.0 mimage2_copy = self.mimage2.Factory(self.mimage2, True) # make a copy self.mimage2.scaledMinus(c, self.mimage) # # Now repeat calculation using a temporary # tmp = self.mimage.Factory(self.mimage, True) tmp *= c mimage2_copy -= tmp self.assertEqual(self.mimage2.get(0, 0), mimage2_copy.get(0, 0)) def testArithmeticImagesMismatch(self): "Test arithmetic operations on MaskedImages of different sizes" i1 = afwImage.MaskedImageF(afwGeom.Extent2I(100, 100)) i1.set(100) i2 = afwImage.MaskedImageF(afwGeom.Extent2I(10, 10)) i2.set(10) def tst1(i1, i2): i1 -= i2 def tst2(i1, i2): i1.scaledMinus(1.0, i2) def tst3(i1, i2): i1 += i2 def tst4(i1, i2): i1.scaledPlus(1.0, i2) def tst5(i1, i2): i1 *= i2 def tst6(i1, i2): i1.scaledMultiplies(1.0, i2) def tst7(i1, i2): i1 /= i2 def tst8(i1, i2): i1.scaledDivides(1.0, i2) tsts12 = [tst1, tst3, tst5, tst7] for tst in tsts12:
    292 a7aa0c91 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst, i1, i2)
    ? ^^^ ^^^^^^ ------- ------ ---------
    292 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst, i1, i2)
    ? ^^ ^ tsts21 = [tst2, tst4, tst6, tst8] for tst in tsts21:
    296 a7aa0c91 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst, i2, i1)
    ? ^^^ ^^^^^^ ------- ------ ---------
    296 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst, i2, i1)
    ? ^^ ^ def testMultiplyImages(self): """Test multiplication""" # Multiply by a MaskedImage self.mimage2 *= self.mimage self.assertEqual(self.mimage2.get(0, 0), (self.imgVal2*self.imgVal1, self.EDGE, self.varVal2*pow(self.imgVal1,2) + self.varVal1*pow(self.imgVal2, 2))) # Divide a MaskedImage by an Image; this divides the variance Image # by an Image in C++ mimage_i = afwImage.MaskedImageI(self.mimage2.getDimensions()) mimage_i.set(900, 0x0, 1000.0) image_i = afwImage.ImageI(mimage_i.getDimensions(), 2) mimage_i *= image_i self.assertEqual(mimage_i.get(0, 0), (1800, 0x0, 4000.0)) # multiply by a scalar self.mimage *= self.imgVal1 self.assertEqual(self.mimage.get(0, 0), (self.imgVal1*self.imgVal1, self.EDGE, self.varVal1*pow(self.imgVal1, 2))) self.assertEqual(self.mimage.getMask().get(1, 1), self.EDGE) self.assertEqual(self.mimage.getMask().get(2, 2), 0x0) def testScaledMultiplyImages(self): """Test multiplication by a scaled image""" # Multiply by an image c = 10.0 mimage2_copy = self.mimage2.Factory(self.mimage2, True) # make a copy self.mimage2.scaledMultiplies(c, self.mimage) # # Now repeat calculation using a temporary # tmp = self.mimage.Factory(self.mimage, True) tmp *= c mimage2_copy *= tmp self.assertEqual(self.mimage2.get(0, 0), mimage2_copy.get(0, 0)) def testDivideImages(self): """Test division""" # Divide by a MaskedImage mimage2_copy = self.mimage2.Factory(self.mimage2, True) # make a copy mimage2_copy /= self.mimage self.assertEqual(mimage2_copy.getImage().get(0, 0), self.imgVal2/self.imgVal1) self.assertEqual(mimage2_copy.getMask().get(0, 0), self.EDGE) self.assertAlmostEqual(mimage2_copy.getVariance().get(0, 0), (self.varVal2*pow(self.imgVal1,2) + self.varVal1*pow(self.imgVal2, 2))/pow(self.imgVal1, 4), 10) # Divide by an Image (of the same type as MaskedImage.getImage()) mimage = self.mimage2.Factory(self.mimage2, True) mimage /= mimage.getImage() self.assertEqual(mimage.get(0, 0), (self.imgVal2/self.imgVal2, 0x0, self.varVal2)) # Divide by an Image (of a different type from MaskedImage.getImage()) if False: # this isn't supported from python (it's OK in C++) mimage = self.mimage2.Factory(self.mimage2, True) image = afwImage.ImageI(mimage.getDimensions(), 1) mimage /= image self.assertEqual(mimage.get(0, 0), (self.imgVal2, 0x0, self.varVal2)) # Divide a MaskedImage by an Image; this divides the variance Image # by an Image in C++ mimage_i = afwImage.MaskedImageI(self.mimage2.getDimensions()) mimage_i.set(900, 0x0, 1000.0) image_i = afwImage.ImageI(mimage_i.getDimensions(), 2) mimage_i /= image_i self.assertEqual(mimage_i.get(0, 0), (450, 0x0, 250.0)) # divide by a scalar self.mimage /= self.imgVal1 self.assertEqual(self.mimage.getImage().get(0, 0), self.imgVal1/self.imgVal1) self.assertEqual(self.mimage.getMask().get(0, 0), self.EDGE) self.assertAlmostEqual(self.mimage.getVariance().get(0, 0), self.varVal1/pow(self.imgVal1, 2), 9) self.assertEqual(self.mimage.getMask().get(1, 1), self.EDGE) self.assertEqual(self.mimage.getMask().get(2, 2), 0x0) def testScaledDivideImages(self): """Test division by a scaled image""" # Divide by an image c = 10.0 mimage2_copy = self.mimage2.Factory(self.mimage2, True) # make a copy self.mimage2.scaledDivides(c, self.mimage) # # Now repeat calculation using a temporary # tmp = self.mimage.Factory(self.mimage, True) tmp *= c mimage2_copy /= tmp self.assertEqual(self.mimage2.get(0, 0), mimage2_copy.get(0, 0)) def testCopyConstructors(self): dimage = afwImage.MaskedImageF(self.mimage, True) # deep copy simage = afwImage.MaskedImageF(self.mimage) # shallow copy self.mimage += 2 # should only change dimage self.assertEqual(dimage.getImage().get(0, 0), self.imgVal1) self.assertEqual(simage.getImage().get(0, 0), self.imgVal1 + 2) def checkImgPatch12(self, img, x0, y0): """Check that a patch of an image is correct; origin of patch is at (x0, y0) in full image N.b. This isn't a general routine! Works only for testSubimages[12]""" self.assertEqual(img.get(x0 - 1, y0 - 1), (self.imgVal1, self.EDGE, self.varVal1)) self.assertEqual(img.get(x0, y0), (666, self.BAD, 0)) self.assertEqual(img.get(x0 + 3, y0), (self.imgVal1, 0x0, self.varVal1)) self.assertEqual(img.get(x0, y0 + 1), (666, self.BAD, 0)) self.assertEqual(img.get(x0 + 3, y0 + 1), (self.imgVal1, 0x0, self.varVal1)) self.assertEqual(img.get(x0, y0 + 2), (self.imgVal1, 0x0, self.varVal1)) def testOrigin(self): """Check that we can set and read the origin""" im = afwImage.MaskedImageF(afwGeom.ExtentI(10, 20)) x0 = y0 = 0 self.assertEqual(im.getX0(), x0) self.assertEqual(im.getY0(), y0) self.assertEqual(im.getXY0(), afwGeom.PointI(x0, y0)) x0, y0 = 3, 5 im.setXY0(x0, y0) self.assertEqual(im.getX0(), x0) self.assertEqual(im.getY0(), y0) self.assertEqual(im.getXY0(), afwGeom.PointI(x0, y0)) x0, y0 = 30, 50 im.setXY0(afwGeom.Point2I(x0, y0)) self.assertEqual(im.getX0(), x0) self.assertEqual(im.getY0(), y0) self.assertEqual(im.getXY0(), afwGeom.Point2I(x0, y0)) def testSubimages1(self): smimage = afwImage.MaskedImageF( self.mimage, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(10, 5)), afwImage.LOCAL ) simage = afwImage.MaskedImageF( smimage, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(3, 2)), afwImage.LOCAL ) self.assertEqual(simage.getX0(), 2) self.assertEqual(simage.getY0(), 2) # i.e. wrt self.mimage mimage2 = afwImage.MaskedImageF(simage.getDimensions()) mimage2.getImage().set(666) mimage2.getMask().set(self.BAD) simage <<= mimage2 del simage del mimage2 self.checkImgPatch12(self.mimage, 2, 2) self.checkImgPatch12(smimage, 1, 1) def testSubimages2(self): """Test subimages when we've played with the (x0, y0) value""" self.mimage.set(9, 4, (888, 0x0, 0)) #printImg(afwImage.ImageF(self.mimage, afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(10, 5)))); print smimage = afwImage.MaskedImageF( self.mimage, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(10, 5)), afwImage.LOCAL ) smimage.setXY0(afwGeom.Point2I(0, 0)) # reset origin; doesn't affect pixel coordinate systems simage = afwImage.MaskedImageF( smimage, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(3, 2)), afwImage.LOCAL ) self.assertEqual(simage.getX0(), 1) self.assertEqual(simage.getY0(), 1) mimage2 = afwImage.MaskedImageF(simage.getDimensions()) mimage2.set(666, self.BAD, 0.0) simage <<= mimage2 del simage del mimage2 self.checkImgPatch12(self.mimage, 2, 2) self.checkImgPatch12(smimage, 1, 1) def checkImgPatch3(self, img, deep): """Check that a patch of an image is correct; origin of patch is at (x0, y0) in full image N.b. This isn't a general routine! Works only for testSubimages3""" # Include deep in comparison so we can see which test fails self.assertEqual(img.get(0, 0) + (deep, ), (100, 0x0, self.varVal1, deep)) self.assertEqual(img.get(10, 10) + (deep, ), (200, 0xf, self.varVal1, deep)) def testSubimages3(self): """Test subimages when we've played with the (x0, y0) value""" self.mimage.getImage().set(20, 20, 200) self.mimage.getMask().set(20, 20, 0xf) for deep in (True, False): mimage = self.mimage.Factory( self.mimage, afwGeom.Box2I(afwGeom.Point2I(10, 10), afwGeom.Extent2I(64, 64)), afwImage.LOCAL, deep) mimage.setXY0(afwGeom.Point2I(0, 0)) mimage2 = mimage.Factory(mimage) if display: ds9.mtv(mimage2) self.checkImgPatch3(mimage2, deep) def testSetCopiedMask(self): """Check that we can set the Mask with a copied Mask""" crMask = self.mimage.getMask().Factory(self.mimage.getMask(), True) msk = self.mimage.getMask() msk |= crMask del msk def testVariance(self): """Check that we can set the variance from the gain""" gain = 2 var = self.mimage.getVariance() var <<= self.mimage.getImage() var /= gain def testTicket653(self): """How-to-repeat for #653""" # The original ticket read this file, but it doesn't reproduce for me, # As I don't see how reading an exposure from disk could make a difference # it's easier to just build an Image if False:
    548 801abc84 - im = afwImage.ImageF(os.path.join(eups.productDir("afwdata"), "med_img.fits"))
    ? ^ ^ ^^^^^ ^
    548 7cbb2bb9 + im = afwImage.ImageF(os.path.join(lsst.utils.getPackageDir("afwdata"), "med_img.fits"))
    ? ^^^^^ ^^^ ^^^^^ ^^^^ else: im = afwImage.ImageF(afwGeom.Extent2I(10, 10)) mi = afwImage.MaskedImageF(im) exp = afwImage.ExposureF(mi) def testMaskedImageInitialisation(self): dims = self.mimage.getDimensions() factory = self.mimage.Factory self.mimage.set(666) del self.mimage # tempt C++ to reuse the memory self.mimage = factory(dims) self.assertEqual(self.mimage.get(10, 10), (0, 0x0, 0)) del self.mimage self.mimage = factory(afwGeom.Extent2I(20, 20)) self.assertEqual(self.mimage.get(10, 10), (0, 0x0, 0)) def testImageSlices(self): """Test image slicing, which generate sub-images using Box2I under the covers""" im = afwImage.MaskedImageF(10, 20) im[4,10] = (10, 0x2, 100) im[-3:, -2:] = 100 sim = im[1:4, 6:10] nan = -666 # a real NaN != NaN so tests fail sim[:] = (-1, 0x8, nan) im[0:4, 0:4] = im[2:6, 8:12] if display: ds9.mtv(im) self.assertEqual(im.get(0, 6), ( 0, 0x0, 0)) self.assertEqual(im.get(6, 17), ( 0, 0x0, 0)) self.assertEqual(im.get(7, 18), (100,0x0, 0)) self.assertEqual(im.get(9, 19), (100,0x0, 0)) self.assertEqual(im.get(1, 6), (-1, 0x8, nan)) self.assertEqual(im.get(3, 9), (-1, 0x8, nan)) self.assertEqual(im.get(4, 10), (10, 0x2, 100)) self.assertEqual(im.get(4, 9), ( 0, 0x0, 0)) self.assertEqual(im.get(2, 2), (10, 0x2, 100)) self.assertEqual(im.get(0, 0), (-1, 0x8, nan)) def testConversionToScalar(self): """Test that even 1-pixel MaskedImages can't be converted to scalars""" im = afwImage.MaskedImageF(10, 20) self.assertRaises(TypeError, float, im) # only single pixel images may be converted self.assertRaises(TypeError, float, im[0,0]) # actually, can't convert (img, msk, var) to scalar #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def printImg(img): print "%4s " % "", for c in range(img.getWidth()): print "%7d" % c, print for r in range(img.getHeight() - 1, -1, -1): print "%4d " % r, for c in range(img.getWidth()): print "%7.1f" % float(img.get(c, r)), print #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(MaskedImageTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    a3819593

    commit a3819593676f1da48225c1ff65e385882b40141b
    Author: bick 
    Date:   Mon Jan 11 20:15:41 2010 +0000
    
        Statistics returns nan instead of throwing exception (#1123).  Removed pdb from tests.
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    801abc84

    commit 801abc84e1280eac959362b940cd14026cb26f35
    Author: rhl 
    Date:   Wed Feb 25 16:48:35 2009 +0000
    
        Added test case for #653
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/detection/FootprintMerge.cc

    Diff:

                    /*
                     * LSST Data Management System
                     * Copyright 2008-2014 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    #include "boost/bind.hpp"
                    
                    #include "lsst/afw/detection/FootprintMerge.h"
                    #include "lsst/afw/detection/FootprintSet.h"
                    #include "lsst/afw/table/IdFactory.h"
                    
                    namespace lsst { namespace afw { namespace detection {
                    
                    namespace {
                    
                    FootprintSet mergeFootprintPair(Footprint const &foot1, Footprint const &foot2) {
                    
                        geom::Box2I bbox(foot1.getBBox());
                        bbox.include(foot2.getBBox());
                    
                        boost::uint16_t bits = 0x1;
                        image::Mask mask(bbox);
                        setMaskFromFootprint(&mask, foot1, bits);
                        setMaskFromFootprint(&mask, foot2, bits);
                        FootprintSet fpSet(mask, Threshold(bits, Threshold::BITMASK));
                        return fpSet;
                    }
                    
                    } // anonymous namespace
                    
                    class FootprintMerge {
                    public:
                    
                        typedef FootprintMergeList::KeyTuple KeyTuple;
                        typedef FootprintMergeList::FilterMap FilterMap;
                    
                        explicit FootprintMerge(
                            PTR(Footprint) footprint,
                            PTR(afw::table::SourceTable) sourceTable,
                            PTR(PeakTable) peakTable,
                            afw::table::SchemaMapper const & peakSchemaMapper,
                            KeyTuple const & keys
                        ) :
                            _footprints(1, footprint),
                            _source(sourceTable->makeRecord())
                        {
                            PTR(Footprint) newFootprint = boost::make_shared(*footprint);
                    
                            _source->set(keys.footprint, true);
                            // Replace all the Peaks in the merged Footprint with new ones that include the origin flags
                            newFootprint->getPeaks() = PeakCatalog(peakTable);
                            for (
                                PeakCatalog::iterator iter = footprint->getPeaks().begin();
                                iter != footprint->getPeaks().end();
                                ++iter
                            ) {
                                PTR(PeakRecord) newPeak = peakTable->copyRecord(*iter, peakSchemaMapper);
                                newPeak->set(keys.peak, true);
                                newFootprint->getPeaks().push_back(newPeak);
                            }
                            _source->setFootprint(newFootprint);
                        }
                    
                        /*
                         *  Does this Footprint overlap the merged Footprint.
                         *
                         *  The current implementation just builds an image from the two Footprints and
                         *  detects the number of peaks.  This is not very efficient and will be changed
                         *  within the Footprint class in the future.
                         */
                        bool overlaps(Footprint const &rhs) const {
                            return mergeFootprintPair(*getMergedFootprint(), rhs).getFootprints()->size() == 1u;
                        }
                    
                        /*
                         *  Add this Footprint to the merge.
                         *
                         *  If minNewPeakDist >= 0, it will add all peaks from foot to the merged Footprint
                         *  that are greater than minNewPeakDist away from the closest existing peak.
                         *  If minNewPeakDist < 0, no peaks will be added from foot.
                         *
                         *  If foot does not overlap it will do nothing.
                         */
                        void add(
                            PTR(Footprint) footprint,
                            afw::table::SchemaMapper const & peakSchemaMapper,
                            KeyTuple const & keys,
                            float minNewPeakDist=-1.,
                            float maxSamePeakDist=-1.
                        ) {
                            if (_addSpans(footprint)) {
                                _footprints.push_back(footprint);
                                _source->set(keys.footprint, true);
                                _addPeaks(footprint->getPeaks(), &peakSchemaMapper, &keys, minNewPeakDist, maxSamePeakDist);
                            }
                        }
                    
                        /*
                         *  Merge an already-merged clump of Footprints into this
                         *
                         *  If minNewPeakDist >= 0, it will add all peaks from foot to the merged Footprint
                         *  that are greater than minNewPeakDist away from the closest existing peak.
                         *  If minNewPeakDist < 0, no peaks will be added from foot.
                         *
                         *  If foot does not overlap it will do nothing.
                         */
                        void add(
                            FootprintMerge const & other,
                            FilterMap const & keys,
                            float minNewPeakDist=-1.,
                            float maxSamePeakDist=-1.
                            ) {
                            if (_addSpans(other.getMergedFootprint())) {
                                _footprints.insert(_footprints.end(), other._footprints.begin(), other._footprints.end());
                                // Set source flags to the OR of the flags of the two inputs
                                for (FilterMap::const_iterator i = keys.begin(); i != keys.end(); ++i) {
                                    afw::table::Key const & flagKey = i->second.footprint;
                                    _source->set(flagKey, _source->get(flagKey) || other._source->get(flagKey));
                                }
                                _addPeaks(other.getMergedFootprint()->getPeaks(), NULL, NULL, minNewPeakDist, maxSamePeakDist);
                            }
                        }
                    
                        // Get the bounding box of the merge
                        afw::geom::Box2I getBBox() const { return getMergedFootprint()->getBBox(); }
                    
                        PTR(Footprint) getMergedFootprint() const { return _source->getFootprint(); }
                    
                        PTR(afw::table::SourceRecord) getSource() const { return _source; }
                    
                    private:
                    
                        // Implementation helper for add() methods; returns true if the Footprint actually overlapped
                        // and was merged, and false otherwise.
                        bool _addSpans(PTR(Footprint) footprint) {
                            FootprintSet fpSet = mergeFootprintPair(*getMergedFootprint(), *footprint);
                            if (fpSet.getFootprints()->size() != 1u) return false;
                            getMergedFootprint()->_bbox.include(footprint->getBBox());
                            getMergedFootprint()->getSpans().swap(fpSet.getFootprints()->front()->getSpans());
                            return true;
                        }
                    
                        void _addPeaks(
                            PeakCatalog const & otherPeaks,
                            afw::table::SchemaMapper const * peakSchemaMapper,
                            KeyTuple const * keys,
                            float minNewPeakDist,
                            float maxSamePeakDist
                        ) {
                            if (minNewPeakDist < 0 && maxSamePeakDist < 0) return;
                    
                            PeakCatalog & currentPeaks = getMergedFootprint()->getPeaks();
                            PTR(PeakRecord) nearestPeak;
                            // Create new list of peaks
                            PeakCatalog newPeaks(currentPeaks.getTable());
                            float minNewPeakDist2 = minNewPeakDist*minNewPeakDist;
                            float maxSamePeakDist2 = maxSamePeakDist*maxSamePeakDist;
                            for (PeakCatalog::const_iterator otherIter = otherPeaks.begin();
                                 otherIter != otherPeaks.end(); ++otherIter) {
                    
                                float minDist2 = std::numeric_limits::infinity();
                    
                                for (PeakCatalog::const_iterator currentIter = currentPeaks.begin();
                                     currentIter != currentPeaks.end(); ++currentIter) {
                                    float dist2 = otherIter->getI().distanceSquared(currentIter->getI());
                    
                                    if (dist2 < minDist2) {
                                        minDist2 = dist2;
                                        nearestPeak = currentIter;
                                    }
                                }
                    
                                if (minDist2 < maxSamePeakDist2 && nearestPeak && keys && maxSamePeakDist > 0) {
                                    nearestPeak->set(keys->peak, true);
                                } else if (minDist2 > minNewPeakDist2 && !(minNewPeakDist < 0)) {
                                    if (peakSchemaMapper) {
                                        PTR(PeakRecord) newPeak = newPeaks.addNew();
                                        newPeak->assign(*otherIter, *peakSchemaMapper);
                                        newPeak->set(keys->peak, true);
                                    } else {
                                        newPeaks.push_back(otherIter);
                                    }
                                }
                    
                            }
                    
                            getMergedFootprint()->getPeaks().insert(
                                getMergedFootprint()->getPeaks().end(),
                                newPeaks.begin(), newPeaks.end(),
                                true // deep-copy
                            );
                        }
                    
                        std::vector _footprints;
                        PTR(afw::table::SourceRecord) _source;
                    };
                    
                    
                    FootprintMergeList::FootprintMergeList(
                        afw::table::Schema & sourceSchema,
                        std::vector const & filterList,
                        afw::table::Schema const & initialPeakSchema
                    ) : _peakSchemaMapper(initialPeakSchema) {
                        _initialize(sourceSchema, filterList);
                    }
                    
                    FootprintMergeList::FootprintMergeList(
                        afw::table::Schema & sourceSchema,
                        std::vector const & filterList
                    ) : _peakSchemaMapper(PeakTable::makeMinimalSchema()) {
                        _initialize(sourceSchema, filterList);
                    }
                    
                    void FootprintMergeList::_initialize(
                        afw::table::Schema & sourceSchema,
                        std::vector const & filterList
                    ) {
                        _peakSchemaMapper.addMinimalSchema(_peakSchemaMapper.getInputSchema(), true);
                        // Add Flags for the filters
                        for (
                            std::vector::const_iterator iter=filterList.begin();
                            iter != filterList.end();
                            ++iter
                        ) {
                            KeyTuple & keys = _filterMap[*iter];
                            keys.footprint = sourceSchema.addField(
                                "merge.footprint." + *iter,
                                "Detection footprint overlapped with a detection from filter " + *iter
                            );
                            keys.peak = _peakSchemaMapper.editOutputSchema().addField(
                                "merge.peak." + *iter,
                                "Peak detected in filter " + *iter
                            );
                        }
                        _peakTable = PeakTable::make(_peakSchemaMapper.getOutputSchema());
                    }
                    
                    void FootprintMergeList::addCatalog(
                        PTR(afw::table::SourceTable) sourceTable,
                        afw::table::SourceCatalog const &inputCat,
                        std::string const & filter,
                        float minNewPeakDist, bool doMerge, float maxSamePeakDist
                    ) {
                        FilterMap::const_iterator keyIter = _filterMap.find(filter);
                        if (keyIter == _filterMap.end()) {
                            throw LSST_EXCEPT(
    
    263 e3cdd56c - pex::exceptions::LogicErrorException,
    ? ---------
    263 f65a55f9 + pex::exceptions::LogicError,
    (boost::format("Filter %s not in original list") % filter).str() ); } // If list is empty don't check for any matches, just add all the objects bool checkForMatches = (_mergeList.size() > 0); for (afw::table::SourceCatalog::const_iterator srcIter = inputCat.begin(); srcIter != inputCat.end(); ++srcIter) { // Only consider unblended objects if (srcIter->getParent() != 0) continue; PTR(Footprint) foot = srcIter->getFootprint(); // Empty pointer to account for the first match in the catalog. If there is more than one // match, subsequent matches will be merged with this one PTR(FootprintMerge) first = PTR(FootprintMerge)(); if (checkForMatches) { FootprintMergeVec::iterator iter = _mergeList.begin(); while (iter != _mergeList.end()) { // Grow by one pixel to allow for touching geom::Box2I box((**iter).getBBox()); box.grow(geom::Extent2I(1,1)); if (box.overlaps(foot->getBBox()) && (**iter).overlaps(*foot)) { if (!first) { first = *iter; // Add Footprint to existing merge and set flag for this band if (doMerge) { first->add(foot, _peakSchemaMapper, keyIter->second, minNewPeakDist, maxSamePeakDist); } } else { // Add merged Footprint to first if (doMerge) { first->add(**iter, _filterMap, minNewPeakDist, maxSamePeakDist); iter = _mergeList.erase(iter); continue; } } } ++iter; } } if (!first) { _mergeList.push_back( boost::make_shared( foot, sourceTable, _peakTable, _peakSchemaMapper, keyIter->second ) ); } } } void FootprintMergeList::getFinalSources(afw::table::SourceCatalog &outputCat, bool doNorm) { // Now set the merged footprint as the footprint of the SourceRecord for (FootprintMergeVec::iterator iter = _mergeList.begin(); iter != _mergeList.end(); ++iter) { if (doNorm) (**iter).getMergedFootprint()->normalize(); outputCat.push_back((**iter).getSource()); } } }}} // namespace lsst::afw::detection

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    e3cdd56c

    commit e3cdd56cb8749e3a51538762c471a5e305795e55
    Author: Jim Bosch 
    Date:   Wed Dec 17 15:08:47 2014 -0500
    
        More careful handling of mismatched arrays in footprint-merge tests
        
        Some of this test code wasn't quite testing what it claimed to be testing,
        because the arrays being passed in were not all the same size, and zip()
        silently iterates over the smallest of its arguments.  The removal of
        some of the test utility code in this change is just to make it so we have
        to worry about that problem in fewer places.
        
        Also changed the failure mode to an exception instead of a warning
        and no-op; seems like a logic error that should be fatal in order to
        better catch bugs in higher-level code.
    

    Commits in /Users/nate/repos_lsst/afw/

    f65a55f9

    commit f65a55f97c110b934263cb7bf5f1cd8baff54b51
    Author: Lauren MacArthur 
    Date:   Wed Apr 22 13:48:07 2015 -0400
    
        Remove trailing Exception in exception names
    

    Return to list

    tests/stacker.py

    Diff:

    1 37817775 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # # -*- python -*- """ Tests for Stack Run with: ./Stacker.py or python >>> import Stacker; Stacker.run() """ ########################## # simpleStacker.py # Steve Bickerton # An example executible which calls the example 'stack' code import unittest import numpy import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom import lsst.utils.tests as utilsTests import lsst.pex.exceptions as pexEx import lsst.afw.display.ds9 as ds9
    51 4bae7ca1 + numpy.random.seed(1)
    52 4bae7ca1 +
    try: type(display) except: display = False ###################################### # main body of code ######################################
    58 6eed36a1 - class StackTestCase(utilsTests.TestCase):
    ? ^^^^ -
    61 37817775 + class StackTestCase(unittest.TestCase):
    ? ++ ^ def setUp(self): self.nImg = 10 self.nX, self.nY = 64, 64 self.values = [1.0, 2.0, 2.0, 3.0, 8.0 ] def testMean(self): """ Test the statisticsStack() function for a MEAN""" knownMean = 0.0 imgList = afwImage.vectorImageF() for iImg in range(self.nImg): imgList.push_back(afwImage.ImageF(afwGeom.Extent2I(self.nX, self.nY), iImg)) knownMean += iImg imgStack = afwMath.statisticsStack(imgList, afwMath.MEAN) knownMean /= self.nImg
    76 37817775 - self.assertEqual(imgStack.get(self.nX/2, self.nY/2), knownMean)
    79 b80fe1d3 + self.assertEqual(imgStack.get(self.nX//2, self.nY//2), knownMean)
    ? + + # Test in-place stacking afwMath.statisticsStack(imgStack, imgList, afwMath.MEAN)
    80 2ae27b97 - self.assertEqual(imgStack.get(self.nX/2, self.nY/2), knownMean)
    83 b80fe1d3 + self.assertEqual(imgStack.get(self.nX//2, self.nY//2), knownMean)
    ? + + def testStatistics(self): """ Test the statisticsStack() function """ imgList = afwImage.vectorImageF() for val in self.values: imgList.push_back(afwImage.ImageF(afwGeom.Extent2I(self.nX, self.nY), val)) imgStack = afwMath.statisticsStack(imgList, afwMath.MEAN) mean = reduce(lambda x, y: x+y, self.values)/float(len(self.values))
    91 37817775 - self.assertAlmostEqual(imgStack.get(self.nX/2, self.nY/2), mean)
    94 b80fe1d3 + self.assertAlmostEqual(imgStack.get(self.nX//2, self.nY//2), mean)
    ? + + imgStack = afwMath.statisticsStack(imgList, afwMath.MEDIAN) median = sorted(self.values)[len(self.values)//2]
    95 37817775 - self.assertEqual(imgStack.get(self.nX/2, self.nY/2), median)
    98 b80fe1d3 + self.assertEqual(imgStack.get(self.nX//2, self.nY//2), median)
    ? + + def testWeightedStack(self): """ Test statisticsStack() function when weighting by a variance plane""" sctrl = afwMath.StatisticsControl() sctrl.setWeighted(True) mimgList = afwImage.vectorMaskedImageF() for val in self.values: mimg = afwImage.MaskedImageF(afwGeom.Extent2I(self.nX, self.nY)) mimg.set(val, 0x0, val) mimgList.push_back(mimg) mimgStack = afwMath.statisticsStack(mimgList, afwMath.MEAN, sctrl) wvalues = [1.0/q for q in self.values] wmean = float(len(self.values)) / reduce(lambda x, y: x + y, wvalues)
    111 49a228bf - self.assertAlmostEqual(mimgStack.getImage().get(self.nX/2, self.nY/2), wmean)
    114 b80fe1d3 + self.assertAlmostEqual(mimgStack.getImage().get(self.nX//2, self.nY//2), wmean)
    ? + + # Test in-place stacking afwMath.statisticsStack(mimgStack, mimgList, afwMath.MEAN, sctrl)
    115 2ae27b97 - self.assertAlmostEqual(mimgStack.getImage().get(self.nX/2, self.nY/2), wmean)
    118 b80fe1d3 + self.assertAlmostEqual(mimgStack.getImage().get(self.nX//2, self.nY//2), wmean)
    ? + + def testConstantWeightedStack(self): """ Test statisticsStack() function when weighting by a vector of weights""" sctrl = afwMath.StatisticsControl() imgList = afwImage.vectorImageF() weights = afwMath.vectorF() for val in self.values: img = afwImage.ImageF(afwGeom.Extent2I(self.nX, self.nY), val) imgList.push_back(img) weights.push_back(val) imgStack = afwMath.statisticsStack(imgList, afwMath.MEAN, sctrl, weights) wsum = reduce(lambda x, y: x + y, self.values) wvalues = [x*x for x in self.values] wmean = reduce(lambda x, y: x + y, wvalues)/float(wsum)
    132 08c2b54a - self.assertAlmostEqual(imgStack.get(self.nX/2, self.nY/2), wmean)
    135 b80fe1d3 + self.assertAlmostEqual(imgStack.get(self.nX//2, self.nY//2), wmean)
    ? + + def testRequestMoreThanOneStat(self): """ Make sure we throw an exception if someone requests more than one type of statistics. """ sctrl = afwMath.StatisticsControl() imgList = afwImage.vectorImageF() for val in self.values: img = afwImage.ImageF(afwGeom.Extent2I(self.nX, self.nY), val) imgList.push_back(img) def tst(): imgStackBad = afwMath.statisticsStack(imgList, afwMath.MEAN | afwMath.MEANCLIP, sctrl)
    147 a3819593 - utilsTests.assertRaisesLsstCpp(self, pexEx.InvalidParameterException, tst)
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    150 6fc1c3d1 + self.assertRaises(pexEx.InvalidParameterError, tst)
    ? ^^ ^ ^^ ^ def testReturnInputs(self): """ Make sure that a single file put into the stacker is returned unscathed""" imgList = afwImage.vectorMaskedImageF() img = afwImage.MaskedImageF(afwGeom.Extent2I(10, 20)) for y in range(img.getHeight()): simg = img.Factory( img, afwGeom.Box2I(afwGeom.Point2I(0, y), afwGeom.Extent2I(img.getWidth(), 1)), afwImage.LOCAL) simg.set(y) imgList.push_back(img) imgStack = afwMath.statisticsStack(imgList, afwMath.MEAN) if display: ds9.mtv(img, frame=1, title="input") ds9.mtv(imgStack, frame=2, title="stack") self.assertEqual(img.get(0, 0)[0], imgStack.get(0, 0)[0]) def testStackBadPixels(self): """Check that we properly ignore masked pixels, and set noGoodPixelsMask where there are no good pixels""" mimgVec = afwImage.vectorMaskedImageF() DETECTED = afwImage.MaskU_getPlaneBitMask("DETECTED") EDGE = afwImage.MaskU_getPlaneBitMask("EDGE") INTRP = afwImage.MaskU_getPlaneBitMask("INTRP") SAT = afwImage.MaskU_getPlaneBitMask("SAT") sctrl = afwMath.StatisticsControl() sctrl.setNanSafe(False) sctrl.setAndMask(INTRP | SAT) sctrl.setNoGoodPixelsMask(EDGE) edgeBBox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(20, 20)) # set these pixels to EDGE width, height = 512, 512 dim=afwGeom.Extent2I(width, height) val, maskVal = 10, DETECTED for i in range(4): mimg = afwImage.MaskedImageF(dim) mimg.set(val, maskVal, 1) # # Set part of the image to NaN (with the INTRP bit set) # llc = afwGeom.Point2I(width//2*(i//2), height//2*(i%2))
    199 c9c89e06 - bbox = afwGeom.Box2I(llc, dim/2)
    202 4567a4cd + bbox = afwGeom.Box2I(llc, dim//2)
    ? + smimg = mimg.Factory(mimg, bbox, afwImage.LOCAL) #smimg.set(numpy.nan, INTRP, numpy.nan) del smimg # # And the bottom corner to SAT # smask = mimg.getMask().Factory(mimg.getMask(), edgeBBox, afwImage.LOCAL) smask |= SAT del smask mimgVec.push_back(mimg) if display > 1: ds9.mtv(mimg, frame=i, title=str(i)) mimgStack = afwMath.statisticsStack(mimgVec, afwMath.MEAN, sctrl) if display: i += 1 ds9.mtv(mimgStack, frame=i, title="Stack") i += 1 ds9.mtv(mimgStack.getVariance(), frame=i, title="var(Stack)") # # Check the output, ignoring EDGE pixels # sctrl = afwMath.StatisticsControl() sctrl.setAndMask(afwImage.MaskU_getPlaneBitMask("EDGE")) stats = afwMath.makeStatistics(mimgStack, afwMath.MIN | afwMath.MAX, sctrl) self.assertEqual(stats.getValue(afwMath.MIN), val) self.assertEqual(stats.getValue(afwMath.MAX), val) # # We have to clear EDGE in the known bad corner to check the mask # smask = mimgStack.getMask().Factory(mimgStack.getMask(), edgeBBox, afwImage.LOCAL) self.assertEqual(smask.get(edgeBBox.getMinX(), edgeBBox.getMinY()), EDGE) smask &= ~EDGE del smask self.assertEqual(afwMath.makeStatistics(mimgStack.getMask(), afwMath.SUM, sctrl).getValue(), maskVal) def testTicket1412(self): """Ticket 1412: ignored mask bits are propegated to output stack.""" mimg1 = afwImage.MaskedImageF(afwGeom.Extent2I(1, 1)) mimg1.set(0, 0, (1, 0x4, 1)) # set 0100 mimg2 = afwImage.MaskedImageF(afwGeom.Extent2I(1, 1)) mimg2.set(0, 0, (2, 0x3, 1)) # set 0010 and 0001 imgList = afwImage.vectorMaskedImageF() imgList.push_back(mimg1) imgList.push_back(mimg2) sctrl = afwMath.StatisticsControl() sctrl.setAndMask(0x1) # andmask only 0001 # try first with no sctrl (no andmask set), should see 0x0111 for all output mask pixels imgStack = afwMath.statisticsStack(imgList, afwMath.MEAN) self.assertEqual(imgStack.get(0, 0)[1], 0x7) # now try with sctrl (andmask = 0x0001), should see 0x0100 for all output mask pixels imgStack = afwMath.statisticsStack(imgList, afwMath.MEAN, sctrl) self.assertEqual(imgStack.get(0, 0)[1], 0x4) def test2145(self): """The how-to-repeat from #2145""" Size = 5 statsCtrl = afwMath.StatisticsControl() statsCtrl.setCalcErrorFromInputVariance(True) maskedImageList = afwImage.vectorMaskedImageF() weightList = [] for i in range(3): mi = afwImage.MaskedImageF(Size, Size) imArr, maskArr, varArr = mi.getArrays() imArr[:] = numpy.random.normal(10, 0.1, (Size, Size)) varArr[:] = numpy.random.normal(10, 0.1, (Size, Size)) maskedImageList.append(mi) weightList.append(1.0) stack = afwMath.statisticsStack(maskedImageList, afwMath.MEAN, statsCtrl, weightList) if False: print "image=", stack.getImage().getArray() print "variance=", stack.getVariance().getArray() self.assertNotEqual(numpy.sum(stack.getVariance().getArray()), 0.0)
    286 6eed36a1 - def testRejectedMaskPropagation(self):
    287 6eed36a1 - """Test that we can propagate mask bits from rejected pixels, when the amount
    288 6eed36a1 - of rejection crosses a threshold."""
    289 6eed36a1 - rejectedBit = 1 # use this bit to determine whether to reject a pixel
    290 6eed36a1 - propagatedBit = 2 # propagate this bit if a pixel with it set is rejected
    291 6eed36a1 - statsCtrl = afwMath.StatisticsControl()
    292 6eed36a1 - statsCtrl.setMaskPropagationThreshold(propagatedBit, 0.3)
    293 6eed36a1 - statsCtrl.setAndMask(1 << rejectedBit)
    294 6eed36a1 - statsCtrl.setWeighted(True)
    295 6eed36a1 - maskedImageList = afwImage.vectorMaskedImageF()
    296 6eed36a1 -
    297 6eed36a1 - # start with 4 images with no mask bits set
    298 6eed36a1 - partialSum = numpy.zeros((1, 4), dtype=numpy.float32)
    299 6eed36a1 - finalImage = numpy.array([12.0, 12.0, 12.0, 12.0], dtype=numpy.float32)
    300 6eed36a1 - for i in range(4):
    301 6eed36a1 - mi = afwImage.MaskedImageF(4, 1)
    302 6eed36a1 - imArr, maskArr, varArr = mi.getArrays()
    303 6eed36a1 - imArr[:,:] = numpy.ones((1, 4), dtype=numpy.float32)
    304 6eed36a1 - maskedImageList.append(mi)
    305 6eed36a1 - partialSum += imArr
    306 6eed36a1 - # add one more image with all permutations of the first two bits set in different pixels
    307 6eed36a1 - mi = afwImage.MaskedImageF(4, 1)
    308 6eed36a1 - imArr, maskArr, varArr = mi.getArrays()
    309 6eed36a1 - imArr[0,:] = finalImage
    310 6eed36a1 - maskArr[0,1] |= (1 << rejectedBit)
    311 6eed36a1 - maskArr[0,2] |= (1 << propagatedBit)
    312 6eed36a1 - maskArr[0,3] |= (1 << rejectedBit)
    313 6eed36a1 - maskArr[0,3] |= (1 << propagatedBit)
    314 6eed36a1 - maskedImageList.append(mi)
    315 6eed36a1 -
    316 6eed36a1 - # these will always be rejected
    317 6eed36a1 - finalImage[1] = 0.0
    318 6eed36a1 - finalImage[3] = 0.0
    319 6eed36a1 -
    320 6eed36a1 - # Uniform weights: we should only see pixel 2 set with propagatedBit, because it's not rejected;
    321 6eed36a1 - # pixel 3 is rejected, but its weight (0.2) below the propagation threshold (0.3)
    322 6eed36a1 - stack1 = afwMath.statisticsStack(maskedImageList, afwMath.MEAN, statsCtrl, [1.0, 1.0, 1.0, 1.0, 1.0])
    323 6eed36a1 - self.assertEqual(stack1.get(0,0)[1], 0x0)
    324 6eed36a1 - self.assertEqual(stack1.get(1,0)[1], 0x0)
    325 6eed36a1 - self.assertEqual(stack1.get(2,0)[1], 1 << propagatedBit)
    326 6eed36a1 - self.assertEqual(stack1.get(3,0)[1], 0x0)
    327 6eed36a1 - self.assertClose(stack1.getImage().getArray(),
    328 6eed36a1 - (partialSum + finalImage) / numpy.array([5.0, 4.0, 5.0, 4.0]),
    329 6eed36a1 - rtol=1E-7)
    330 6eed36a1 -
    331 6eed36a1 - # Give the masked image more weight: we should see pixel 2 and pixel 3 set with propagatedBit,
    332 6eed36a1 - # pixel 2 because it's not rejected, and pixel 3 because the weight of the rejection (0.3333)
    333 6eed36a1 - # is above the threshold (0.3)
    334 6eed36a1 - # Note that rejectedBit is never propagated, because we didn't include it in statsCtrl (of course,
    335 6eed36a1 - # normally the bits we'd propagate and the bits we'd reject would be the same)
    336 6eed36a1 - stack2 = afwMath.statisticsStack(maskedImageList, afwMath.MEAN, statsCtrl, [1.0, 1.0, 1.0, 1.0, 2.0])
    337 6eed36a1 - self.assertEqual(stack2.get(0,0)[1], 0x0)
    338 6eed36a1 - self.assertEqual(stack2.get(1,0)[1], 0x0)
    339 6eed36a1 - self.assertEqual(stack2.get(2,0)[1], 1 << propagatedBit)
    340 6eed36a1 - self.assertEqual(stack2.get(3,0)[1], 1 << propagatedBit)
    341 6eed36a1 - self.assertClose(stack2.getImage().getArray(),
    342 6eed36a1 - (partialSum + 2*finalImage) / numpy.array([6.0, 4.0, 6.0, 4.0]),
    343 6eed36a1 - rtol=1E-7)
    344 6eed36a1 -
    ################################################################# # Test suite boiler plate ################################################################# def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(StackTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    2ae27b97

    commit 2ae27b97d2b70c81bf5f9ed9fb9a3c95e95f0946
    Author: Paul Price 
    Date:   Fri Mar 30 14:59:39 2012 -0400
    
        Add tests for in-place stacking.
    

    6eed36a1

    commit 6eed36a1b6376390c028ec0a15a8d35d040b951c
    Author: Jim Bosch 
    Date:   Thu May 1 12:58:41 2014 -0400
    
        Propagate rejected pixel mask planes when the amount of rejection crosses a threshold.
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    49a228bf

    commit 49a228bf5fefad3542cad9b4ecddf97e2d7f0e9b
    Author: bick 
    Date:   Wed Dec 16 02:19:29 2009 +0000
    
        Added weighted statistics.
    

    37817775

    commit 3781777568b9eba0fdfbcfbb0ec37b3c2c1dfe3c
    Author: bick 
    Date:   Tue Dec 15 04:08:30 2009 +0000
    
        framework in place for image stacking. ... buggy, doesn't compile.
    

    a3819593

    commit a3819593676f1da48225c1ff65e385882b40141b
    Author: bick 
    Date:   Mon Jan 11 20:15:41 2010 +0000
    
        Statistics returns nan instead of throwing exception (#1123).  Removed pdb from tests.
    

    08c2b54a

    commit 08c2b54ac88a772d918683b51702fa9f9fe3aa25
    Author: bick 
    Date:   Thu Dec 31 22:43:51 2009 +0000
    
        #1092 requested functionality now operational.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    4bae7ca1

    commit 4bae7ca131d04a3f68e47748b0423617ffd33000
    Author: Paul Price 
    Date:   Wed Aug 6 16:40:49 2014 -0400
    
        tests: seed random number generator to make tests deterministic
    

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    37817775

    commit 3781777568b9eba0fdfbcfbb0ec37b3c2c1dfe3c
    Author: bick 
    Date:   Tue Dec 15 04:08:30 2009 +0000
    
        framework in place for image stacking. ... buggy, doesn't compile.
    

    Return to list

    tests/testGaussianProcess.py

    Diff:

    1 7f1ccc1f - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see < http://www.lsstcorp.org/LegalNotices/ > . #
    25 390b1ae1 - import os
    import unittest
    27 390b1ae1 - import warnings
    28 390b1ae1 - import sys
    import numpy as np import lsst.afw.math as gp import lsst.utils.tests as utilsTests import lsst.pex.exceptions as pex class GaussianProcessTestCase(unittest.TestCase): def testTooManyNeighbors(self): """ Test that GaussianProcess checks if too many neighbours are requested """ nData = 100 # number of data points dimen = 10 # dimension of each point data = np.zeros((nData,dimen)) fn = np.zeros(nData) gg = gp.GaussianProcessD(data, fn, gp.SquaredExpCovariogramD()) test = np.zeros(dimen) sigma = np.empty(1) mu_arr = np.empty(1)
    49 e5954e26 - self.assertRaises(pex.LsstCppException,gg.interpolate,sigma,test,2*nData)
    ? -------
    47 6fc1c3d1 + self.assertRaises(pex.Exception,gg.interpolate,sigma,test,2*nData)
    50 e5954e26 - self.assertRaises(pex.LsstCppException,gg.interpolate,sigma,test,-5)
    ? -------
    48 6fc1c3d1 + self.assertRaises(pex.Exception,gg.interpolate,sigma,test,-5)
    51 e5954e26 - self.assertRaises(pex.LsstCppException,gg.selfInterpolate,sigma,0,2*nData)
    ? -------
    49 6fc1c3d1 + self.assertRaises(pex.Exception,gg.selfInterpolate,sigma,0,2*nData)
    52 e5954e26 - self.assertRaises(pex.LsstCppException,gg.selfInterpolate,sigma,0,-5)
    ? -------
    50 6fc1c3d1 + self.assertRaises(pex.Exception,gg.selfInterpolate,sigma,0,-5)
    53 e5954e26 - self.assertRaises(pex.LsstCppException,gg.selfInterpolate,sigma,-1,nData-1)
    ? -------
    51 6fc1c3d1 + self.assertRaises(pex.Exception,gg.selfInterpolate,sigma,-1,nData-1)
    52 99f47645 + # the following segfaults, for unknown reasons, so run directly instead
    54 e5954e26 - self.assertRaises(pex.LsstCppException,gg.selfInterpolate,sigma,nData,nData-1)
    ? -------
    53 6fc1c3d1 + #self.assertRaises(pex.Exception,gg.selfInterpolate,sigma,nData,nData-1)
    ? +
    54 99f47645 + try:
    55 99f47645 + gg.interpolate(mu_arr,sigma,2*nData)
    56 99f47645 + self.fail("gg.interpolate(mu_arr,sigma,2*nData) did not fail")
    57 6fc1c3d1 + except pex.Exception:
    58 99f47645 + pass
    55 e5954e26 - self.assertRaises(pex.LsstCppException,gg.interpolate,mu_arr,sigma,2*nData)
    ? -------
    59 6fc1c3d1 + self.assertRaises(pex.Exception,gg.interpolate,mu_arr,sigma,2*nData)
    56 e5954e26 - self.assertRaises(pex.LsstCppException,gg.interpolate,mu_arr,sigma,-5)
    ? -------
    60 6fc1c3d1 + self.assertRaises(pex.Exception,gg.interpolate,mu_arr,sigma,-5)
    def testInterpolate(self): """ This will test GaussianProcess.interpolate using both the squared exponential covariogram and the neural network covariogram on data that was generated with known answers. The test will check that the code returns the correct values of both mu (interpolated function value) and sig2 (the variance) This test uses the GaussianProcess constructor that does not normalize coordinate values with minima and maxima. """ pp = 2000 #number of data points dd = 10 #number of dimensions kk = 15 #number of nearest neighbors being used tol = 1.0e-3 #the largest relative error that will be tolerated data = np.zeros((pp,dd),dtype = float) #input data points fn = np.zeros((pp),dtype = float) #input function values test = np.zeros((dd),dtype = float) #query points sigma = np.zeros((1),dtype = float) #variance xx=gp.SquaredExpCovariogramD() xx.setEllSquared(100.0) #read in the input data f = open("tests/data/gp_exp_covar_data.sav") ff = f.readlines() f.close() for i in range(len(ff)): s = ff[i].split() fn[i] = float(s[10]) for j in range(10): data[i][j] = float(s[j]) #first try the squared exponential covariogram (the default) try: gg = gp.GaussianProcessD(data,fn,xx)
    98 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    102 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    99 53b5190a - print e.args[0].what()
    ? --------
    103 6fc1c3d1 + print e.what()
    gg.setLambda(0.001) #now, read in the test points and their corresponding known solutions f = open("tests/data/gp_exp_covar_solutions.sav") ff = f.readlines() f.close() worstMuErr = -1.0 #keep track of the worst fractional error in mu worstSigErr = -1.0 #keep track of the worst fractional error in the variance for z in range(len(ff)): s = ff[z].split() #s will store the zth line of the solution file for i in range(dd): test[i] = float(s[i]) #read in the test point coordinates mushld = float(s[dd + kk]) #read in what mu should be sigshld = float(s[dd + kk + 1]) #read in what the variance should be mu = gg.interpolate(sigma,test,kk) err = (mu - mushld) if mushld != 0.0: err = err/mushld if err < 0.0: err = -1.0 * err if z == 0 or err > worstMuErr: worstMuErr = err err = (sigma[0] - sigshld) if sigshld != 0.0: err = err/sigshld if err < 0.0: err = -1.0 * err if z == 0 or err > worstSigErr: worstSigErr = err print "\nThe errors for squared exponent covariogram\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) #now try with the Neural Network covariogram kk = 50 nn=gp.NeuralNetCovariogramD() nn.setSigma0(1.23) nn.setSigma1(0.452) gg.setCovariogram(nn) gg.setLambda(0.0045) f = open("tests/data/gp_nn_solutions.sav") ff = f.readlines() f.close() worstMuErr = -1.0 worstSigErr = -1.0 for z in range(len(ff)): s = ff[z].split() for i in range(dd): test[i] = float(s[i]) mushld = float(s[dd + kk]) sigshld = float(s[dd + kk + 1]) mu = gg.interpolate(sigma,test,kk) err = (mu - mushld) if mushld != 0.0: err = err/mushld if err < 0.0: err = -1.0 * err if z == 0 or err > worstMuErr: worstMuErr = err err = (sigma[0] - sigshld) if sigshld != 0.0: err = err/sigshld if err < 0.0: err = -1.0 * err if z == 0 or err > worstSigErr: worstSigErr = err print "\nThe errors for neural net covariogram\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) def testMinMax(self): """ This test will test GaussianProcess.interpolate using the constructor that normalizes data point coordinates by minima and maxima. It will only use the squared exponential covariogram (since testInterpolate() presumably tested the performance of the neural network covariogram; this test is only concerned with the alternate constructor) This test proceeds largely like testInterpolate above """ pp = 2000 dd = 10 kk = 50 tol = 1.0e-4 data = np.zeros((pp,dd),dtype = float) fn = np.zeros((pp),dtype = float) test = np.zeros((dd),dtype = float) sigma = np.zeros((1),dtype = float) mins = np.zeros((dd),dtype = float) maxs = np.zeros((dd),dtype = float) nn=gp.NeuralNetCovariogramD() nn.setSigma0(0.555) nn.setSigma1(0.112) f = open("tests/data/gp_exp_covar_data.sav") ff = f.readlines() f.close() for i in range(len(ff)): s = ff[i].split() fn[i] = float(s[10]) for j in range(10): data[i][j] = float(s[j]) for i in range(pp): for j in range(dd): if (i == 0) or (data[i][j] < mins[j]): mins[j] = data[i][j] if (i == 0) or (data[i][j] > maxs[j]): maxs[j] = data[i][j] mins[2] = 0.0 maxs[2] = 10.0 try: gg = gp.GaussianProcessD(data,mins,maxs,fn,nn)
    248 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    252 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    249 53b5190a - print e.args[0].what()
    ? --------
    253 6fc1c3d1 + print e.what()
    gg.setLambda(0.0045) f = open("tests/data/gp_minmax_solutions.sav") ff = f.readlines() f.close() worstMuErr = -1.0 worstSigErr = -1.0 for z in range(len(ff)): s = ff[z].split() for i in range(dd): test[i] = float(s[i]) mushld = float(s[dd + kk]) sigshld = float(s[dd + kk + 1]) mu = gg.interpolate(sigma,test,kk) err = (mu - mushld) if mushld != 0.0: err = err/mushld if err < 0.0: err = -1.0 * err if z == 0 or err > worstMuErr: worstMuErr = err err = (sigma[0] - sigshld) if sigshld != 0.0: err = err/sigshld if err < 0.0: err = -1.0 * err if z == 0 or err > worstSigErr: worstSigErr = err print "\nThe errors for Gaussian process using min-max normalization\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) def testAddition(self): """ This will test the performance of interpolation after adding new points to GaussianProcess' data set """ pp = 1000 dd = 10 kk = 15 tol = 1.0e-4 data = np.zeros((pp,dd),dtype = float) fn = np.zeros((pp),dtype = float) test = np.zeros((dd),dtype = float) sigma = np.zeros((1),dtype = float) xx=gp.SquaredExpCovariogramD() xx.setEllSquared(5.0) f = open("tests/data/gp_additive_test_root.sav") ff = f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() fn[i] = float(s[10]) for j in range(10): data[i][j] = float(s[j]) #establish the Gaussian Process try: gg = gp.GaussianProcessD(data,fn,xx)
    326 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    330 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    327 53b5190a - print e.args[0].what()
    ? --------
    331 6fc1c3d1 + print e.what()
    gg.setLambda(0.002) #now add new points to it and see if GaussianProcess.interpolate performs #correctly f = open("tests/data/gp_additive_test_data.sav") ff = f.readlines() f.close() for z in range(len(ff)): s = ff[z].split() for i in range(dd): test[i] = float(s[i]) mushld = float(s[dd]) try: gg.addPoint(test,mushld)
    343 53b5190a - except pex.LsstCppException,e:
    ? ------- ^
    347 6fc1c3d1 + except pex.Exception as e:
    ? ^^^^
    344 53b5190a - print e.args[0].what()
    ? --------
    348 6fc1c3d1 + print e.what()
    f = open("tests/data/gp_additive_test_solutions.sav") ff = f.readlines() f.close() worstMuErr = -1.0 worstSigErr = -1.0 for z in range(len(ff)): s = ff[z].split() for i in range(dd): test[i] = float(s[i]) mushld = float(s[dd + kk]) sigshld = float(s[dd + kk + 1]) mu = gg.interpolate(sigma,test,kk) err = (mu - mushld) if mushld != 0: err = err/mushld if err < 0.0: err = -1.0 * err if z == 0 or err > worstMuErr: worstMuErr = err err = (sigma[0] - sigshld) if sigshld != 0: err = err/sigshld if err < 0.0: err = -1.0 * err if z == 0 or err > worstSigErr: worstSigErr = err print "\nThe errors for the test of adding points to the Gaussian process\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) def testKdTree(self): """ This test will test the construction of KdTree in the pathological case where many of the input data points are identical. """ pp = 100 dd = 5 data = np.zeros((pp,dd),dtype = float) tol=1.0e-10 f = open("tests/data/kd_test_data.sav") ff = f.readlines() f.close() for i in range(len(ff)): s = ff[i].split() for j in range(dd): data[i][j] = float(s[j]) kd = gp.KdTreeD() try: kd.Initialize(data)
    410 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    414 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    411 53b5190a - print e.args[0].what()
    ? --------
    415 6fc1c3d1 + print e.what()
    kds = gp.KdTreeD() try: kds.Initialize(data)
    417 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    421 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    418 53b5190a - print e.args[0].what()
    ? --------
    422 6fc1c3d1 + print e.what()
    try: kds.removePoint(2)
    422 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    426 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    423 53b5190a - print e.args[0].what()
    ? --------
    427 6fc1c3d1 + print e.what()
    worstErr=-1.0 for i in range(100): if i > 2: dd=0.0 for j in range(5): dd = dd+(kd.getData(i,j)-kds.getData(i-1,j))*(kd.getData(i,j)-kds.getData(i-1,j)) if dd>worstErr: worstErr=dd self.assertTrue(worstErr 437 53b5190a - except pex.LsstCppException, e: ? ------- ^
    441 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    438 53b5190a - print e.args[0].what()
    ? --------
    442 6fc1c3d1 + print e.what()
    try: kds.removePoint(10)
    442 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    446 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    443 53b5190a - print e.args[0].what()
    ? --------
    447 6fc1c3d1 + print e.what()
    for i in range(99): if i > 10: dd=0.0 for j in range(5): dd = dd+(kd.getData(i,j)-kds.getData(i-1,j))*(kd.getData(i,j)-kds.getData(i-1,j)) if dd>worstErr: worstErr=dd self.assertTrue(worstErr 456 53b5190a - except pex.LsstCppException, e: ? ------- ^
    460 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    457 53b5190a - print e.args[0].what()
    ? --------
    461 6fc1c3d1 + print e.what()
    try: kds.removePoint(21)
    461 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    465 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    462 53b5190a - print e.args[0].what()
    ? --------
    466 6fc1c3d1 + print e.what()
    for i in range(98): if i > 21: dd=0.0 for j in range(5): dd = dd+(kd.getData(i,j)-kds.getData(i-1,j))*(kd.getData(i,j)-kds.getData(i-1,j)) if dd>worstErr: worstErr=dd self.assertTrue(worstErr 501 53b5190a - except pex.LsstCppException, e: ? ------- ^
    505 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    502 53b5190a - print e.args[0].what()
    ? --------
    506 6fc1c3d1 + print e.what()
    gg.setLambda(0.0032) f = open("tests/data/gp_batch_solutions.sav","r") ff = f.readlines() f.close() ntest = len(ff) mushld = np.zeros((ntest),dtype = float) varshld = np.zeros((ntest),dtype = float) mu = np.zeros((ntest),dtype = float) var = np.zeros((ntest),dtype = float) queries = np.zeros((ntest,dd),dtype = float) for i in range(ntest): s = ff[i].split() for j in range(dd): queries[i][j] = float(s[j]) mushld[i] = float(s[dd]) varshld[i] = float(s[dd + 1]) #test with variance calculation gg.batchInterpolate(mu,var,queries) worstMuErr = -1.0 worstVarErr = -1.0 for i in range(ntest): err = mu[i]-mushld[i] if mushld[i] != 0.0: err = err/mushld[i] if err < 0.0: err = -1.0 * err if err > worstMuErr: worstMuErr = err err = var[i]-varshld[i] if varshld[i] != 0.0: err = err/varshld[i] if err < 0.0: err = -1.0 * err if err > worstVarErr: worstVarErr = err #test without variance interpolation #continue keeping track of worstMuErr gg.batchInterpolate(mu,queries) for i in range(ntest): err = mu[i]-mushld[i] if mushld[i] != 0.0: err = err/mushld[i] if err < 0.0: err = -1.0 * err if err > worstMuErr: worstMuErr = err self.assertTrue(worstMuErr < tol) self.assertTrue(worstVarErr < tol) print "\nThe errors for batch interpolation\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstVarErr def testSelf(self): """ This test will test GaussianProcess.selfInterpolation """ pp = 2000 dd = 10 tol = 1.0e-3 kk = 20 data = np.zeros((pp,dd),dtype = float) fn = np.zeros((pp),dtype = float) f = open("tests/data/gp_exp_covar_data.sav","r"); ff = f.readlines() f.close() for i in range(pp): s = ff[i].split() for j in range(dd): data[i][j] = float(s[j]) fn[i] = float(s[dd]) xx=gp.SquaredExpCovariogramD() xx.setEllSquared(20.0) try: gg = gp.GaussianProcessD(data,fn,xx)
    592 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    596 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    593 53b5190a - print e.args[0].what()
    ? --------
    597 6fc1c3d1 + print e.what()
    gg.setKrigingParameter(30.0) gg.setLambda(0.00002) f = open("tests/data/gp_self_solutions.sav","r") ff = f.readlines() f.close() variance = np.zeros((1),dtype = float) worstMuErr = -1.0 worstSigErr = -1.0 for i in range(pp): s = ff[i].split() mushld = float(s[0]) sig2shld = float(s[1]) try: mu = gg.selfInterpolate(variance,i,kk)
    613 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    617 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    614 53b5190a - print e.args[0].what()
    ? --------
    618 6fc1c3d1 + print e.what()
    err = mu - mushld if mushld != 0.0: err = err/mushld if err < 0.0: err = err * (-1.0) if i == 0 or err > worstMuErr: worstMuErr = err err = variance[0] - sig2shld if sig2shld != 0.0: err = err/sig2shld if err < 0.0: err = err * (-1.0) if i == 0 or err > worstSigErr: worstSigErr = err print "\nThe errors for self interpolation\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) def testVector(self): """ This will test interpolate using a vector of functions """ tol=1.0e-3 data=np.zeros((2000,10), dtype = float) fn=np.zeros((2000,4), dtype = float) mu=np.zeros((4), dtype=float) sig=np.zeros((4), dtype = float) mushld=np.zeros((4), dtype = float) vv=np.zeros((10), dtype = float) vvf=np.zeros((4), dtype = float) kk=30
    655 53b5190a - ll=0.0045
    656 53b5190a -
    f=open("tests/data/gp_vector_data.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() for j in range(10): data[i][j]=float(s[j]) for j in range(4): fn[i][j]=float(s[j+10]) nn=gp.NeuralNetCovariogramD() nn.setSigma0(2.25) nn.setSigma1(0.76) try: gg=gp.GaussianProcessD(data,fn,nn);
    672 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    674 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    673 53b5190a - print e.args[0].what()
    ? --------
    675 6fc1c3d1 + print e.what()
    gg.setLambda(0.0045) worstMuErr=-1.0 worstSigErr=-1.0 f=open("tests/data/gp_vector_solutions.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() for j in range(10): vv[j]=float(s[j]) for j in range(4): mushld[j]=float(s[j+10]) sigshld=float(s[14]) gg.interpolate(mu,sig,vv,kk) for j in range(4): muErr= (mu[j]-mushld[j])/mushld[j] sigErr = (sig[j]-sigshld)/sigshld if muErr < 0.0: muErr = -1.0 * muErr if sigErr < 0.0: sigErr = -1.0 * sigErr if (muErr > worstMuErr): worstMuErr=muErr if (sigErr > worstSigErr): worstSigErr=sigErr print "\nThe errors for vector interpolation\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) worstMuErr=-1.0 worstSigErr=-1.0 f=open("tests/data/gp_vector_selfinterpolate_solutions.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() try: gg.selfInterpolate(mu,sig,i,kk);
    721 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    723 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    722 53b5190a - print e.args[0].what()
    ? --------
    724 6fc1c3d1 + print e.what()
    for j in range(4): mushld[j]=float(s[j]) sigshld=float(s[4]) for j in range(4): muErr=(mu[j]-mushld[j])/mushld[j] if muErr < -1.0: muErr=-1.0 * muErr if muErr>worstMuErr: worstMuErr=muErr sigErr=(sig[j]-sigshld)/sigshld if sigErr<-1.0: sigErr = -1.0*sigErr if sigErr>worstSigErr: worstSigErr=sigErr print "\nThe errors for vector self interpolation\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) queries=np.zeros((100,10), dtype = float) batchMu=np.zeros((100,4), dtype = float) batchSig=np.zeros((100,4), dtype = float) batchMuShld=np.zeros((100,4), dtype = float) batchSigShld=np.zeros((100,4), dtype = float) batchData=np.zeros((200,10), dtype = float) batchFunctions=np.zeros((200,4), dtype = float) f=open("tests/data/gp_vectorbatch_data.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() for j in range(10): batchData[i][j]=float(s[j]) for j in range(4): batchFunctions[i][j]=float(s[j+10]) try: ggbatch=gp.GaussianProcessD(batchData,batchFunctions,nn)
    770 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    772 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    771 53b5190a - print e.args[0].what()
    ? --------
    773 6fc1c3d1 + print e.what()
    ggbatch.setLambda(0.0045) f=open("tests/data/gp_vectorbatch_solutions.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() for j in range(10): queries[i][j]=float(s[j]) for j in range(4): batchMuShld[i][j]=float(s[j+10]) sigShld=float(s[14]) for j in range(4): batchSigShld[i][j]=sigShld ggbatch.batchInterpolate(batchMu,batchSig,queries) worstMuErr=-1.0 worstSigErr=-1.0 for i in range(100): for j in range(4): muErr=(batchMu[i][j]-batchMuShld[i][j])/batchMuShld[i][j] sigErr=(batchSig[i][j]-batchSigShld[i][j])/batchSigShld[i][j] if muErr < 0.0: muErr = muErr * (-1.0) if sigErr < 0.0: sigErr = sigErr * (-1.0) if muErr>worstMuErr: worstMuErr=muErr if sigErr>worstSigErr: worstSigErr=sigErr print "\nThe errors for vector batch interpolation with variance\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) ggbatch.batchInterpolate(batchMu,queries) worstMuErr=-1.0 worstSigErr=-1.0 for i in range(100): for j in range(4): muErr=(batchMu[i][j]-batchMuShld[i][j])/batchMuShld[i][j] if muErr < 0.0: muErr = muErr * (-1.0) if muErr>worstMuErr: worstMuErr=muErr print "\nThe errors for vector batch interpolation without variance\n" print "worst mu error ",worstMuErr self.assertTrue(worstMuErr < tol) f=open("tests/data/gp_vector_add_data.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() for j in range(10): vv[j]=float(s[j]) for j in range(4): vvf[j]=float(s[j+10]) try: gg.addPoint(vv,vvf)
    841 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    843 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    842 53b5190a - print e.args[0].what()
    ? --------
    844 6fc1c3d1 + print e.what()
    f=open("tests/data/gp_vector_add_solutions.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() try: gg.selfInterpolate(mu,sig,i,kk);
    851 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    853 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    852 53b5190a - print e.args[0].what()
    ? --------
    854 6fc1c3d1 + print e.what()
    for j in range(4): mushld[j]=float(s[j]) sigshld=float(s[4]) for j in range(4): muErr=(mu[j]-mushld[j])/mushld[j] if muErr < 0.0: muErr=-1.0 * muErr if muErr>worstMuErr: worstMuErr=muErr worstMu=mu[j] sigErr=(sig[j]-sigshld)/sigshld if sigErr<0.0: sigErr = -1.0*sigErr if sigErr>worstSigErr: worstSigErr=sigErr print "\nThe errors for vector add interpolation\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) def testSubtraction(self): """ This will test interpolate after subtracting points """ tol=1.0e-3 data=np.zeros((2000,10), dtype = float) fn=np.zeros((2000,4), dtype = float) mu=np.zeros((4), dtype=float) sig=np.zeros((4), dtype = float) mushld=np.zeros((4), dtype = float) vv=np.zeros((10), dtype = float) kk=30
    893 53b5190a - ll=0.002
    f=open("tests/data/gp_subtraction_data.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() for j in range(10): data[i][j]=float(s[j]) for j in range(4): fn[i][j]=float(s[j+10]) xx=gp.SquaredExpCovariogramD() xx.setEllSquared(2.3) try: gg=gp.GaussianProcessD(data,fn,xx);
    909 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    910 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    910 63df72f1 - print e.args[0].what()
    ? --------
    911 6fc1c3d1 + print e.what()
    gg.setLambda(0.002) j=1 for i in range(1000): try: gg.removePoint(j)
    918 cad31a6c - except pex.LsstCppException, e:
    ? ------- ^
    919 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    919 53b5190a - print e.args[0].what()
    ? --------
    920 6fc1c3d1 + print e.what()
    j=j+1 worstMuErr=-1.0 worstSigErr=-1.0 f=open("tests/data/gp_subtraction_solutions.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() for j in range(10): vv[j]=float(s[j]) for j in range(4): mushld[j]=float(s[j+10]) sigshld=float(s[14]) gg.interpolate(mu,sig,vv,kk) for j in range(4): muErr= (mu[j]-mushld[j])/mushld[j] sigErr = (sig[j]-sigshld)/sigshld if muErr < 0.0: muErr = -1.0 * muErr if sigErr < 0.0: sigErr = -1.0 * sigErr if (muErr > worstMuErr): worstMuErr=muErr if (sigErr > worstSigErr): worstSigErr=sigErr print "\nThe errors for subtraction interpolation\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) worstMuErr=-1.0 worstSigErr=-1.0 f=open("tests/data/gp_subtraction_selfinterpolate_solutions.sav","r") ff=f.readlines() f.close() for i in range(len(ff)): s=ff[i].split() try: gg.selfInterpolate(mu,sig,i,kk);
    967 53b5190a - except pex.LsstCppException, e:
    ? ------- ^
    968 6fc1c3d1 + except pex.Exception as e:
    ? ^^^
    968 53b5190a - print e.args[0].what()
    ? --------
    969 6fc1c3d1 + print e.what()
    for j in range(4): mushld[j]=float(s[j]) sigshld=float(s[4]) for j in range(4): muErr=(mu[j]-mushld[j])/mushld[j] if muErr < 0.0: muErr=-1.0 * muErr if muErr>worstMuErr: worstMuErr=muErr sigErr=(sig[j]-sigshld)/sigshld if sigErr<0.0: sigErr = -1.0*sigErr if sigErr>worstSigErr: worstSigErr=sigErr print "\nThe errors for subtraction self interpolation\n" print "worst mu error ",worstMuErr print "worst sig2 error ",worstSigErr self.assertTrue(worstMuErr < tol) self.assertTrue(worstSigErr < tol) def suite(): utilsTests.init() suites = [] suites += unittest.makeSuite(GaussianProcessTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): utilsTests.run(suite(),shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    63df72f1

    commit 63df72f125543b4ce078cf2fa9b9392445d1cca1
    Author: danielsf 
    Date:   Thu Apr 25 15:01:53 2013 -0700
    
        I have implemented all of the functionality requested in the code review
        (except that GaussianProcessTimer remains)
        
        When I compile, I get a warning to the effect that I have not declared a shared_ptr
        for boost::noncopyable (from which Covariogram inherits)
        
        I still need to edit for style
    

    53b5190a

    commit 53b5190a42d09b4187f62b4c4819584c1467164c
    Author: danielsf 
    Date:   Fri Apr 26 13:51:48 2013 -0700
    
        Changed GaussianProcessTimer to protect the timing variables
        
        edited code for style
    

    e5954e26

    commit e5954e261893d2cf599adb45c5c1ba214682d228
    Author: danielsf 
    Date:   Fri Jan 10 13:23:27 2014 -0800
    
        use assertRaises in testGaussianProcess.py
    

    390b1ae1

    commit 390b1ae1ba78aa04eced70fc2534fee716885d6b
    Author: danielsf 
    Date:   Fri Feb 15 09:15:10 2013 -0800
    
        adding the python test script for GaussianProcess
    

    7f1ccc1f

    commit 7f1ccc1fa5447e768a61385b27302489c65ad6e7
    Author: danielsf 
    Date:   Tue Mar 19 14:08:25 2013 -0700
    
        documented testGaussianProcess.py
    

    cad31a6c

    commit cad31a6c9a92bb796e8c5e6fd4c8992aed67c813
    Author: danielsf 
    Date:   Wed May 1 10:55:13 2013 -0700
    
        removed trailing whitespace from testGaussianProcess.py
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    99f47645

    commit 99f476458ad1140348ab8976eb00976f5d4ae9df
    Author: Russell Owen 
    Date:   Tue Jun 17 16:14:26 2014 -0700
    
        tests/testGaussianProcess.py: tweaked the code to avoid a segfault. Unfortunately the tweak
        is unexplained magic. I also removed a few unused imports and computation of two variables
        that were unused (leaving one that is unused because it can potentially raise an error if the index
        is out of range).
    

    Return to list

    tests/testWcsFitsTable.py

    Diff:

    1 b52d64a7 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . #
    25 b52d64a7 - import os
    26 b52d64a7 - import math
    import unittest import pyfits import lsst.afw.image import lsst.afw.geom import lsst.utils.tests as utilsTests import lsst.daf.base class WcsFitsTableTestCase(unittest.TestCase): """Test that we can read and write Wcs objects saved to FITS binary tables. """ def setUp(self): #metadata taken from CFHT data #v695856-e0/v695856-e0-c000-a00.sci.fits self.metadata = lsst.daf.base.PropertySet() self.metadata.set("SIMPLE", "T") self.metadata.set("BITPIX", -32) self.metadata.set("NAXIS", 2) self.metadata.set("NAXIS1", 1024) self.metadata.set("NAXIS2", 1153) self.metadata.set("RADECSYS", "FK5") self.metadata.set("EQUINOX", 2000.) self.metadata.setDouble("CRVAL1", 215.604025685476) self.metadata.setDouble("CRVAL2", 53.1595451514076) self.metadata.setDouble("CRPIX1", 1109.99981456774) self.metadata.setDouble("CRPIX2", 560.018167811613) self.metadata.set("CTYPE1", "RA---SIN") self.metadata.set("CTYPE2", "DEC--SIN") self.metadata.setDouble("CD1_1", 5.10808596133527E-05) self.metadata.setDouble("CD1_2", 1.85579539217196E-07) self.metadata.setDouble("CD2_2", -5.10281493481982E-05) self.metadata.setDouble("CD2_1", -8.27440751733828E-07) def tearDown(self): del self.metadata
    68 b52d64a7 - def doFitsRoundTrip(self, wcsIn):
    67 c605dfcd + def doFitsRoundTrip(self, fileName, wcsIn):
    ? ++++++++++
    69 b52d64a7 - fileName = "wcs-table-test.fits"
    wcsIn.writeFits(fileName) wcsOut = lsst.afw.image.Wcs.readFits(fileName)
    72 b52d64a7 - os.remove(fileName)
    return wcsOut def testSimpleWcs(self):
    73 c605dfcd + with utilsTests.getTempFilePath(".fits") as fileName:
    76 b52d64a7 - wcsIn = lsst.afw.image.makeWcs(self.metadata)
    74 c605dfcd + wcsIn = lsst.afw.image.makeWcs(self.metadata)
    ? ++++
    77 b52d64a7 - wcsOut = self.doFitsRoundTrip(wcsIn)
    75 c605dfcd + wcsOut = self.doFitsRoundTrip(fileName, wcsIn)
    ? ++++ ++++++++++
    78 b52d64a7 - self.assertEqual(wcsIn, wcsOut)
    76 c605dfcd + self.assertEqual(wcsIn, wcsOut)
    ? ++++ def addSipMetadata(self): self.metadata.add("A_ORDER", 3) self.metadata.add("A_0_0", -3.4299726900155e-05) self.metadata.add("A_0_2", 2.9999243742039e-08) self.metadata.add("A_0_3", 5.3160367322875e-12) self.metadata.add("A_1_0", -1.1102230246252e-16) self.metadata.add("A_1_1", 1.7804837804549e-07) self.metadata.add("A_1_2", -3.9117665277930e-10) self.metadata.add("A_2_0", 1.2614116305773e-07) self.metadata.add("A_2_1", 2.4753748298399e-12) self.metadata.add("A_3_0", -4.0559790823371e-10) self.metadata.add("B_ORDER", 3) self.metadata.add("B_0_0", -0.00040333633853922) self.metadata.add("B_0_2", 2.7329405108287e-07) self.metadata.add("B_0_3", -4.1945333823804e-10) self.metadata.add("B_1_1", 1.0211300606274e-07) self.metadata.add("B_1_2", -1.1907781112538e-12) self.metadata.add("B_2_0", 7.1256679698479e-08) self.metadata.add("B_2_1", -4.0026664120969e-10) self.metadata.add("B_3_0", 7.2509034631981e-14) self.metadata.add("AP_ORDER", 5) self.metadata.add("AP_0_0", 0.065169424373537) self.metadata.add("AP_0_1", 3.5323035231808e-05) self.metadata.add("AP_0_2", -2.4878457741060e-08) self.metadata.add("AP_0_3", -1.4288745247360e-11) self.metadata.add("AP_0_4", -2.0000000098183) self.metadata.add("AP_0_5", 4.3337569354109e-19) self.metadata.add("AP_1_0", 1.9993638555698) self.metadata.add("AP_1_1", -2.0722860000493e-07) self.metadata.add("AP_1_2", 4.7562056847339e-10) self.metadata.add("AP_1_3", -8.5172068319818e-06) self.metadata.add("AP_1_4", -1.3242986537057e-18) self.metadata.add("AP_2_0", -1.4594781790233e-07) self.metadata.add("AP_2_1", -2.9254828606617e-12) self.metadata.add("AP_2_2", -2.7203380713516e-11) self.metadata.add("AP_2_3", 1.5030517486646e-19) self.metadata.add("AP_3_0", 4.7856034999197e-10) self.metadata.add("AP_3_1", 1.5571061278960e-15) self.metadata.add("AP_3_2", -3.2422164667295e-18) self.metadata.add("AP_4_0", 5.8904402441647e-16) self.metadata.add("AP_4_1", -4.5488928339401e-20) self.metadata.add("AP_5_0", -1.3198044795585e-18) self.metadata.add("BP_ORDER", 5) self.metadata.add("BP_0_0", 0.00025729974056661) self.metadata.add("BP_0_1", -0.00060857907313083) self.metadata.add("BP_0_2", -3.1283728005742e-07) self.metadata.add("BP_0_3", 5.0413932972962e-10) self.metadata.add("BP_0_4", -0.0046142128142681) self.metadata.add("BP_0_5", -2.2359607268985e-18) self.metadata.add("BP_1_0", 0.0046783112625990) self.metadata.add("BP_1_1", -1.2304042740813e-07) self.metadata.add("BP_1_2", -2.3756827881344e-12) self.metadata.add("BP_1_3", -3.9300202582816e-08) self.metadata.add("BP_1_4", -9.7385290942256e-21) self.metadata.add("BP_2_0", -6.5238116398890e-08) self.metadata.add("BP_2_1", 4.7855579009100e-10) self.metadata.add("BP_2_2", -1.2297758131839e-13) self.metadata.add("BP_2_3", -3.0849793267035e-18) self.metadata.add("BP_3_0", -9.3923321275113e-12) self.metadata.add("BP_3_1", -1.3193479628568e-17) self.metadata.add("BP_3_2", 2.1762350028059e-19) self.metadata.add("BP_4_0", -5.9687252632035e-16) self.metadata.add("BP_4_1", -1.4096893423344e-18) self.metadata.add("BP_5_0", 2.8085458107813e-19) self.metadata.set("CTYPE1", "RA---TAN-SIP") self.metadata.set("CTYPE2", "DEC--TAN-SIP") def testTanWcs(self): self.addSipMetadata() wcsIn = lsst.afw.image.makeWcs(self.metadata)
    148 c605dfcd + with utilsTests.getTempFilePath(".fits") as fileName:
    150 bd336d49 - wcsOut = self.doFitsRoundTrip(wcsIn)
    149 c605dfcd + wcsOut = self.doFitsRoundTrip(fileName, wcsIn)
    ? ++++ ++++++++++
    151 bd336d49 - wcsIn1 = lsst.afw.image.cast_TanWcs(wcsIn)
    150 c605dfcd + wcsIn1 = lsst.afw.image.cast_TanWcs(wcsIn)
    ? ++++
    152 bd336d49 - wcsOut1 = lsst.afw.image.cast_TanWcs(wcsOut)
    151 c605dfcd + wcsOut1 = lsst.afw.image.cast_TanWcs(wcsOut)
    ? ++++
    153 bd336d49 - self.assert_(wcsIn1 is not None)
    152 c605dfcd + self.assert_(wcsIn1 is not None)
    ? ++++
    154 bd336d49 - self.assert_(wcsOut1 is not None)
    153 c605dfcd + self.assert_(wcsOut1 is not None)
    ? ++++
    155 bd336d49 - self.assert_(wcsIn1.hasDistortion())
    154 c605dfcd + self.assert_(wcsIn1.hasDistortion())
    ? ++++
    156 bd336d49 - self.assert_(wcsOut1.hasDistortion())
    155 c605dfcd + self.assert_(wcsOut1.hasDistortion())
    ? ++++
    157 bd336d49 - self.assertEqual(wcsIn1, wcsOut1)
    156 c605dfcd + self.assertEqual(wcsIn1, wcsOut1)
    ? ++++ def testExposure(self): """Test that we load the Wcs from the binary table instead of headers when possible.""" self.addSipMetadata() wcsIn = lsst.afw.image.makeWcs(self.metadata) dim = lsst.afw.geom.Extent2I(20, 30) expIn = lsst.afw.image.ExposureF(dim) expIn.setWcs(wcsIn)
    166 4f859dd5 - fileName = "wcs-table-test.fits"
    165 c605dfcd + with utilsTests.getTempFilePath(".fits") as fileName:
    167 4f859dd5 - expIn.writeFits(fileName)
    166 c605dfcd + expIn.writeFits(fileName)
    ? ++++
    168 023e7f9f - # Manually mess up the headers, so we'd know if we were loading the Wcs from that;
    167 c605dfcd + # Manually mess up the headers, so we'd know if we were loading the Wcs from that;
    ? ++++
    169 023e7f9f - # when there is a WCS in the header and a WCS in the FITS table, we should use the
    168 c605dfcd + # when there is a WCS in the header and a WCS in the FITS table, we should use the
    ? ++++
    170 023e7f9f - # latter, because the former might just be an approximation.
    169 c605dfcd + # latter, because the former might just be an approximation.
    ? ++++
    171 4f859dd5 - fits = pyfits.open(fileName)
    170 c605dfcd + fits = pyfits.open(fileName)
    ? ++++
    172 4f859dd5 - os.remove(fileName)
    173 4f859dd5 - fits[1].header.remove("CTYPE1")
    171 c605dfcd + fits[1].header.remove("CTYPE1")
    ? ++++
    174 4f859dd5 - fits[1].header.remove("CTYPE2")
    172 c605dfcd + fits[1].header.remove("CTYPE2")
    ? ++++
    175 4f859dd5 - fits.writeto(fileName)
    173 c605dfcd + fits.writeto(fileName, clobber=True)
    ? ++++ ++++++++++++++
    176 4f859dd5 - # now load it using afw
    174 c605dfcd + # now load it using afw
    ? ++++
    177 4f859dd5 - expOut = lsst.afw.image.ExposureF(fileName)
    175 c605dfcd + expOut = lsst.afw.image.ExposureF(fileName)
    ? ++++
    178 4f859dd5 - wcsOut = expOut.getWcs()
    176 c605dfcd + wcsOut = expOut.getWcs()
    ? ++++
    179 4f859dd5 - self.assertEqual(wcsIn, wcsOut)
    177 c605dfcd + self.assertEqual(wcsIn, wcsOut)
    ? ++++
    178 c605dfcd +
    ##### def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(WcsFitsTableTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4f859dd5

    commit 4f859dd5ad7dd3301410833d48076da3d552a387
    Author: Jim Bosch 
    Date:   Mon Dec 17 17:13:45 2012 -0500
    
        ExposureInfo now saves Psf and Wcs.
    

    b52d64a7

    commit b52d64a7980b0ff1616d6aa94ed7b0b98c76df8e
    Author: Jim Bosch 
    Date:   Sun Dec 9 15:38:59 2012 -0500
    
        Wcs and TanWcs now inherit from table::io::Persistable
    

    023e7f9f

    commit 023e7f9f4cf99ad6c287507d18eeaf1b8515bbaf
    Author: Jim Bosch 
    Date:   Sat Feb 16 00:00:56 2013 -0500
    
        Doc fixes and minor code cleanups from review for #2470.
    

    bd336d49

    commit bd336d49ea252e1630e1f50dc258d49503170f2d
    Author: Jim Bosch 
    Date:   Mon Dec 10 16:02:32 2012 -0500
    
        Implement table-based persistence for TanWcs.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    Return to list

    tests/testGaussianPsf.py

    Diff:

    1 36e9b23a - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008-2014 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for detection.GaussianPsf Run with: ./testGaussianPsf.py or python >>> import testGaussianPsf; testGaussianPsf.run() """
    35 36e9b23a - import sys
    36 36e9b23a - import os
    import unittest import numpy import lsst.utils.tests import lsst.pex.exceptions import lsst.afw.table import lsst.afw.geom import lsst.afw.coord import lsst.afw.fits import lsst.afw.detection try: type(display) except NameError: display = False def makeGaussianImage(bbox, sigma, xc=0.0, yc=0.0): image = lsst.afw.image.ImageD(bbox) array = image.getArray() for yi, yv in enumerate(xrange(bbox.getBeginY(), bbox.getEndY())): for xi, xv in enumerate(xrange(bbox.getBeginX(), bbox.getEndX())): array[yi, xi] = numpy.exp(-0.5*((xv - xc)**2 + (yv - yc)**2)/sigma**2) array /= array.sum() return image def computeNaiveApertureFlux(image, radius, xc=0.0, yc=0.0):
    63 36e9b23a - bbox = image.getBBox(lsst.afw.image.PARENT)
    62 93994d54 + bbox = image.getBBox()
    array = image.getArray() s = 0.0 for yi, yv in enumerate(xrange(bbox.getBeginY(), bbox.getEndY())): for xi, xv in enumerate(xrange(bbox.getBeginX(), bbox.getEndX())): if (xv - xc)**2 + (yv - yc)**2 < radius**2: s += array[yi, xi] return s class GaussianPsfTestCase(lsst.utils.tests.TestCase): def setUp(self): self.psf = lsst.afw.detection.GaussianPsf(51, 51, 4.0) def tearDown(self): del self.psf def testKernelImage(self): image = self.psf.computeKernelImage()
    82 36e9b23a - check = makeGaussianImage(image.getBBox(lsst.afw.image.PARENT), self.psf.getSigma())
    ? ---------------------
    81 93994d54 + check = makeGaussianImage(image.getBBox(), self.psf.getSigma())
    self.assertClose(image.getArray(), check.getArray()) self.assertClose(image.getArray().sum(), 1.0, atol=1E-14) def testOffsetImage(self): image = self.psf.computeImage(lsst.afw.geom.Point2D(0.25, 0.25))
    88 36e9b23a - check = makeGaussianImage(image.getBBox(lsst.afw.image.PARENT), self.psf.getSigma(), 0.25, 0.25)
    ? ---------------------
    87 93994d54 + check = makeGaussianImage(image.getBBox(), self.psf.getSigma(), 0.25, 0.25)
    self.assertClose(image.getArray(), check.getArray(), atol=1E-4, rtol=1E-4, plotOnFailure=True) def testApertureFlux(self): image = self.psf.computeKernelImage(lsst.afw.geom.Point2D(0.0, 0.0)) # test aperture implementation is very crude; can only test to about 10% self.assertClose(self.psf.computeApertureFlux(5.0), computeNaiveApertureFlux(image, 5.0), rtol=0.1) self.assertClose(self.psf.computeApertureFlux(7.0), computeNaiveApertureFlux(image, 7.0), rtol=0.1) def testShape(self): self.assertClose(self.psf.computeShape().getDeterminantRadius(), 4.0) def testPersistence(self):
    101 36e9b23a - filename = "testGaussianPsf.fits"
    100 c605dfcd + with lsst.utils.tests.getTempFilePath(".fits") as filename:
    102 36e9b23a - self.psf.writeFits(filename)
    101 c605dfcd + self.psf.writeFits(filename)
    ? ++++
    103 36e9b23a - psf = lsst.afw.detection.GaussianPsf.readFits(filename)
    102 c605dfcd + psf = lsst.afw.detection.GaussianPsf.readFits(filename)
    ? ++++
    104 36e9b23a - os.remove(filename)
    105 36e9b23a - self.assertEqual(self.psf.getSigma(), psf.getSigma())
    103 c605dfcd + self.assertEqual(self.psf.getSigma(), psf.getSigma())
    ? ++++
    106 36e9b23a - self.assertEqual(self.psf.getDimensions(), psf.getDimensions())
    104 c605dfcd + self.assertEqual(self.psf.getDimensions(), psf.getDimensions())
    ? ++++ #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" lsst.utils.tests.init() suites = [] suites += unittest.makeSuite(GaussianPsfTestCase) suites += unittest.makeSuite(lsst.utils.tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" lsst.utils.tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    36e9b23a

    commit 36e9b23afb36ae6f687979faa53a547079183c25
    Author: Jim Bosch 
    Date:   Tue Jan 21 18:22:55 2014 -0500
    
        Add Python, unit tests for GaussianPsf (#3115)
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    Return to list

    python/lsst/afw/image/imageLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define imageLib_DOCSTRING
                    "
                    Basic routines to talk to lsst::afw::image classes
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.image", docstring=imageLib_DOCSTRING) imageLib
                    
                    // Suppress swig complaints
                    #pragma SWIG nowarn=314                 // print is a python keyword (--> _print)
                    #pragma SWIG nowarn=362                 // operator=  ignored
                    
                    
                    %{
                    #include "boost/cstdint.hpp"
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging.h"
                    #include "lsst/pex/policy.h"
                    #include "lsst/afw/cameraGeom.h"
                    #include "lsst/afw/image.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/coord/Coord.h"
                    #include "lsst/afw/image/Color.h"
                    #include "lsst/afw/image/Defect.h"
                    #include "lsst/afw/fits.h" // just for exceptions
                    
    
    55 ad4a9b08 - #define PY_ARRAY_UNIQUE_SYMBOL LSST_AFW_IMAGE_NUMPY_ARRAY_API
    56 ad4a9b08 - #include "numpy/arrayobject.h"
    57 a7ce1e71 - #include "ndarray/swig.h"
    58 a7ce1e71 - #include "ndarray/swig/eigen.h"
    59 84523580 -
    #include "lsst/afw/formatters/WcsFormatter.h" #include "lsst/afw/formatters/TanWcsFormatter.h" #include "lsst/afw/formatters/ExposureFormatter.h" #include "lsst/afw/formatters/DecoratedImageFormatter.h" #pragma clang diagnostic ignored "-Warray-bounds" // PyTupleObject has an array declared as [1] %} %include "lsst/afw/fits/fits_reduce.i"
    70 ad4a9b08 - %init %{
    71 ad4a9b08 - import_array();
    72 ad4a9b08 - %}
    73 1d88db56 -
    namespace boost { namespace mpl { } } /************************************************************************************************************/ %typemap(typecheck, precedence=SWIG_TYPECHECK_BOOL, noblock=1) bool { $1 = PyBool_Check($input) ? 1 : 0; } %include "lsst/p_lsstSwig.i"
    76 853c5734 + %initializeNumPy(afw_image)
    77 853c5734 + %{
    78 853c5734 + #include "ndarray/swig.h"
    79 853c5734 + #include "ndarray/swig/eigen.h"
    80 853c5734 + %}
    %include "lsst/daf/base/persistenceMacros.i" %include "lsst/base.h" /******************************************************************************/ %import "lsst/daf/base/baseLib.i" %import "lsst/pex/policy/policyLib.i" %import "lsst/daf/persistence/persistenceLib.i" %import "lsst/afw/geom/geomLib.i" %import "lsst/afw/coord/coordLib.i" %import "lsst/afw/fits/fitsLib.i" // just for FITS exceptions %include "ndarray.i" %declareNumPyConverters(Eigen::MatrixXd); %declareNumPyConverters(Eigen::VectorXd); %declareNumPyConverters(Eigen::Matrix2d); %declareNumPyConverters(Eigen::Vector2d); %declareNumPyConverters(Eigen::Matrix3d); %declareNumPyConverters(Eigen::Vector3d); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %lsst_exceptions(); /******************************************************************************/ %template(pairIntInt) std::pair; %template(pairIntDouble) std::pair; %template(pairDoubleInt) std::pair; %template(pairDoubleDouble) std::pair; %template(mapStringInt) std::map; %define %defineClone(PY_TYPE, TYPE, PIXEL_TYPES...) %extend TYPE {
    134 091bc8b7 - %pythoncode {
    130 81c3bd10 + %pythoncode %{
    ? +
    135 091bc8b7 - def clone(self):
    ? ----
    131 81c3bd10 + def clone(self):
    136 091bc8b7 - """Return a deep copy of self"""
    ? ----
    132 81c3bd10 + """Return a deep copy of self"""
    137 091bc8b7 - return PY_TYPE(self, True)
    ? ----
    133 81c3bd10 + return PY_TYPE(self, True)
    138 091bc8b7 - #
    134 81c3bd10 +
    139 091bc8b7 - # Call our ctor with the provided arguments
    ? ----
    135 81c3bd10 + # Call our ctor with the provided arguments
    140 091bc8b7 - #
    141 091bc8b7 - def Factory(self, *args):
    ? ----
    136 81c3bd10 + def Factory(self, *args):
    142 091bc8b7 - """Return an object of this type"""
    ? ----
    137 81c3bd10 + """Return an object of this type"""
    143 091bc8b7 - return PY_TYPE(*args)
    ? ----
    138 81c3bd10 + return PY_TYPE(*args)
    144 091bc8b7 - }
    139 81c3bd10 + %}
    ? + } %enddef /************************************************************************************************************/
    150 a66d6f8e - %pythoncode {
    145 81c3bd10 + %pythoncode %{
    ? +
    151 a66d6f8e - def _getBBoxFromSliceTuple(img, imageSlice):
    ? ----
    146 81c3bd10 + def _getBBoxFromSliceTuple(img, imageSlice):
    152 c07d7476 - """Given a slice specification return the proper Box2I
    ? ----
    147 81c3bd10 + """Given a slice specification return the proper Box2I
    This is the worker routine behind __getitem__ and __setitem__ The imageSlice may be: lsst.afw.geom.Box2I slice, slice : Only the first one or two parts of the slice are recognised (no stride), a single int is interpreted as n:n+1, and negative indices are interpreted relative to the end of the array, so supported slices include: 2 -1 1:10 :-2 : (equivalent to ... (python's Ellipsis) which is also supported) E.g. im[-1, :] im[..., 18] im[4, 10] im[-3:, -2:] im[-2, -2] im[1:4, 6:10] im[:] """
    177 0fea4663 - afwGeom = lsst.afw.geom.geomLib
    ? ----
    172 81c3bd10 + afwGeom = lsst.afw.geom.geomLib
    179 0fea4663 - if isinstance(imageSlice, afwGeom.Box2I):
    ? ----
    174 81c3bd10 + if isinstance(imageSlice, afwGeom.Box2I):
    180 0fea4663 - return imageSlice
    ? ----
    175 81c3bd10 + return imageSlice
    182 a66d6f8e - if isinstance(imageSlice, slice) and imageSlice.start is None and imageSlice.stop is None:
    ? ----
    177 81c3bd10 + if isinstance(imageSlice, slice) and imageSlice.start is None and imageSlice.stop is None:
    183 a66d6f8e - imageSlice = (Ellipsis, Ellipsis,)
    ? ----
    178 81c3bd10 + imageSlice = (Ellipsis, Ellipsis,)
    185 a66d6f8e - if not (isinstance(imageSlice, tuple) and len(imageSlice) == 2 and \
    ? ----
    180 81c3bd10 + if not (isinstance(imageSlice, tuple) and len(imageSlice) == 2 and \
    186 a66d6f8e - sum([isinstance(_, (slice, type(Ellipsis), int)) for _ in imageSlice]) == 2):
    ? ----
    181 81c3bd10 + sum([isinstance(_, (slice, type(Ellipsis), int)) for _ in imageSlice]) == 2):
    187 a66d6f8e - raise IndexError("Images may only be indexed as a 2-D slice not %s",
    ? ----
    182 81c3bd10 + raise IndexError("Images may only be indexed as a 2-D slice not %s",
    188 a66d6f8e - imageSlice[0], imageSlice[1])
    ? ----
    183 81c3bd10 + imageSlice[0], imageSlice[1])
    189 a66d6f8e -
    184 81c3bd10 +
    190 079e0cfe - imageSlice, _imageSlice = [], imageSlice
    ? ----
    185 81c3bd10 + imageSlice, _imageSlice = [], imageSlice
    191 079e0cfe - for s, wh in zip(_imageSlice, img.getDimensions()):
    ? ----
    186 81c3bd10 + for s, wh in zip(_imageSlice, img.getDimensions()):
    192 079e0cfe - if isinstance(s, slice):
    ? ----
    187 81c3bd10 + if isinstance(s, slice):
    193 079e0cfe - pass
    ? ----
    188 81c3bd10 + pass
    194 079e0cfe - elif isinstance(s, int):
    ? ----
    189 81c3bd10 + elif isinstance(s, int):
    195 079e0cfe - if s < 0:
    ? ----
    190 81c3bd10 + if s < 0:
    196 079e0cfe - s += wh
    ? ----
    191 81c3bd10 + s += wh
    197 079e0cfe - s = slice(s, s + 1)
    ? ----
    192 81c3bd10 + s = slice(s, s + 1)
    198 079e0cfe - else:
    ? ----
    193 81c3bd10 + else:
    199 079e0cfe - s = slice(0, wh)
    ? ----
    194 81c3bd10 + s = slice(0, wh)
    201 079e0cfe - imageSlice.append(s)
    ? ----
    196 81c3bd10 + imageSlice.append(s)
    203 a66d6f8e - x, y = [_.indices(wh) for _, wh in zip(imageSlice, img.getDimensions())]
    ? ----
    198 81c3bd10 + x, y = [_.indices(wh) for _, wh in zip(imageSlice, img.getDimensions())]
    204 a66d6f8e - return afwGeom.Box2I(afwGeom.Point2I(x[0], y[0]), afwGeom.Point2I(x[1] - 1, y[1] - 1))
    ? ----
    199 81c3bd10 + return afwGeom.Box2I(afwGeom.Point2I(x[0], y[0]), afwGeom.Point2I(x[1] - 1, y[1] - 1))
    205 a66d6f8e - }
    200 81c3bd10 + %}
    ? + %define %supportSlicing(TYPE, PIXEL_TYPES...) %extend TYPE {
    209 a66d6f8e - %pythoncode {
    204 81c3bd10 + %pythoncode %{
    ? +
    210 a66d6f8e - #
    205 81c3bd10 + #
    211 a66d6f8e - # Support image slicing
    ? ----
    206 81c3bd10 + # Support image slicing
    212 a66d6f8e - #
    207 81c3bd10 + #
    213 a66d6f8e - def __getitem__(self, imageSlice):
    ? ----
    208 81c3bd10 + def __getitem__(self, imageSlice):
    214 a66d6f8e - """
    ? ----
    209 81c3bd10 + """
    215 a66d6f8e - __getitem__(self, imageSlice) -> NAME""" + """PIXEL_TYPES
    ? ----
    210 81c3bd10 + __getitem__(self, imageSlice) -> NAME""" + """PIXEL_TYPES
    216 a66d6f8e - """
    ? ----
    211 81c3bd10 + """
    217 091bc8b7 - return self.Factory(self, _getBBoxFromSliceTuple(self, imageSlice))
    ? ----
    212 81c3bd10 + return self.Factory(self, _getBBoxFromSliceTuple(self, imageSlice), LOCAL)
    ? +++++++
    219 a66d6f8e - def __setitem__(self, imageSlice, rhs):
    ? ----
    214 81c3bd10 + def __setitem__(self, imageSlice, rhs):
    220 a66d6f8e - """
    ? ----
    215 81c3bd10 + """
    221 a66d6f8e - __setitem__(self, imageSlice, value)
    ? ----
    216 81c3bd10 + __setitem__(self, imageSlice, value)
    222 a66d6f8e - """
    ? ----
    217 81c3bd10 + """
    223 091bc8b7 - lhs = self.Factory(self, _getBBoxFromSliceTuple(self, imageSlice))
    ? ----
    218 81c3bd10 + lhs = self.Factory(self, _getBBoxFromSliceTuple(self, imageSlice), LOCAL)
    ? +++++++
    224 a66d6f8e - try:
    ? ----
    219 81c3bd10 + try:
    225 a66d6f8e - lhs <<= rhs
    ? ----
    220 81c3bd10 + lhs <<= rhs
    226 a66d6f8e - except TypeError:
    ? ----
    221 81c3bd10 + except TypeError:
    227 a66d6f8e - lhs.set(rhs)
    ? ----
    222 81c3bd10 + lhs.set(rhs)
    229 fffc4bea - def __float__(self):
    ? ----
    224 81c3bd10 + def __float__(self):
    230 fffc4bea - """Convert a 1x1 image to a floating scalar"""
    ? ----
    225 81c3bd10 + """Convert a 1x1 image to a floating scalar"""
    231 23615386 - if self.getDimensions() != lsst.afw.geom.geomLib.Extent2I(1, 1):
    ? ----
    226 81c3bd10 + if self.getDimensions() != lsst.afw.geom.geomLib.Extent2I(1, 1):
    232 fffc4bea - raise TypeError("Only single-pixel images may be converted to python scalars")
    ? ----
    227 81c3bd10 + raise TypeError("Only single-pixel images may be converted to python scalars")
    234 23615386 - try:
    ? ----
    229 81c3bd10 + try:
    235 23615386 - return float(self.get(0, 0))
    ? ----
    230 81c3bd10 + return float(self.get(0, 0))
    236 23615386 - except AttributeError:
    ? ----
    231 81c3bd10 + except AttributeError:
    237 23615386 - raise TypeError("Unable to extract a single pixel for type %s" % "TYPE")
    ? ----
    232 81c3bd10 + raise TypeError("Unable to extract a single pixel for type %s" % "TYPE")
    238 23615386 - except TypeError:
    ? ----
    233 81c3bd10 + except TypeError:
    239 23615386 - raise TypeError("Unable to convert a %s<%s> pixel to a scalar" % ("TYPE", "PIXEL_TYPES"))
    ? ----
    234 81c3bd10 + raise TypeError("Unable to convert a %s<%s> pixel to a scalar" % ("TYPE", "PIXEL_TYPES"))
    241 fffc4bea - def __int__(self):
    ? ----
    236 81c3bd10 + def __int__(self):
    242 fffc4bea - """Convert a 1x1 image to a integral scalar"""
    ? ----
    237 81c3bd10 + """Convert a 1x1 image to a integral scalar"""
    243 fffc4bea - return int(float(self))
    ? ----
    238 81c3bd10 + return int(float(self))
    244 a66d6f8e - }
    239 81c3bd10 + %}
    ? + } %enddef /************************************************************************************************************/ // Images, Masks, and MaskedImages %include "lsst/afw/image/LsstImageTypes.h" %ignore lsst::afw::image::Filter::operator int; %include "lsst/afw/image/Filter.h" #if defined(IMPORT_FUNCTION_I) %{ #include "lsst/afw/math.h" %} %import "lsst/afw/math/function.i" #undef IMPORT_FUNCTION_I #endif %include "image.i" %include "mask.i" %include "maskedImage.i" %include "imageSlice.i" %apply double &OUTPUT { double & }; %rename(positionToIndexAndResidual) lsst::afw::image::positionToIndex(double &, double); %clear double &OUTPUT; %include "lsst/afw/image/ImageUtils.h" %include "wcs.i" /************************************************************************************************************/ #if !defined(CAMERA_GEOM_LIB_I) %import "lsst/afw/cameraGeom/cameraGeomLib.i" #endif /************************************************************************************************************/ %include "lsst/afw/image/Calib.i"
    288 d0950ae6 - %include "lsst/afw/image/ApCorrMap.i"
    %{ #include "lsst/afw/detection.h" #include "lsst/afw/image/ExposureInfo.h" #include "lsst/afw/image/Exposure.h" %} // Must go Before the %include %define %exposurePtr(PIXEL_TYPE) %shared_ptr(lsst::afw::image::Exposure); %enddef // Must go After the %include %define %exposure(TYPE, PIXEL_TYPE) %newobject makeExposure; %template(Exposure##TYPE) lsst::afw::image::Exposure; %template(makeExposure) lsst::afw::image::makeExposure; %lsst_persistable(lsst::afw::image::Exposure); %fits_reduce(lsst::afw::image::Exposure); %supportSlicing(lsst::afw::image::Exposure, PIXEL_TYPE, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %defineClone(Exposure##TYPE, lsst::afw::image::Exposure, PIXEL_TYPE, lsst::afw::image::MaskPixel, lsst::afw::image::VariancePixel); %enddef %exposurePtr(boost::uint16_t); %exposurePtr(boost::uint64_t); %exposurePtr(int); %exposurePtr(float); %exposurePtr(double); namespace lsst { namespace afw { namespace detection { class Psf; }}} %shared_ptr(lsst::afw::detection::Psf); %shared_ptr(lsst::afw::image::CoaddInputs); %shared_ptr(lsst::afw::image::ExposureInfo); %import "lsst/afw/table/Exposure.i" %include "lsst/afw/image/CoaddInputs.h" %include "lsst/afw/image/ExposureInfo.h" %include "lsst/afw/image/Exposure.h" %exposure(U, boost::uint16_t); %exposure(L, boost::uint64_t); %exposure(I, int); %exposure(F, float); %exposure(D, double); %extend lsst::afw::image::Exposure { %newobject convertF; lsst::afw::image::Exposure convertF() { return lsst::afw::image::Exposure(*self, true); } } %extend lsst::afw::image::Exposure { %newobject convertD; lsst::afw::image::Exposure convertD() { return lsst::afw::image::Exposure(*self, true); } } /************************************************************************************************************/ %include "lsst/afw/image/Color.h" /************************************************************************************************************/ %shared_ptr(lsst::afw::image::DefectBase); %include "lsst/afw/image/Defect.h" %template(DefectSet) std::vector >; /************************************************************************************************************/

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    091bc8b7

    commit 091bc8b7af5e51a6968030599971e77fc8440ecf
    Author: Robert Lupton the Good 
    Date:   Tue Jan 8 17:25:51 2013 -0500
    
        Merge branch 'tickets/2525'
        
        Resolved conflicts:
        Added %defineClone and %supportSlicing:
            python/lsst/afw/image/image.i
            python/lsst/afw/image/imageLib.i (and use Factory not clone when slicing)
            python/lsst/afw/image/mask.i
            python/lsst/afw/image/maskedImage.i
        Added overlapping tests:
            tests/image.py
    

    c07d7476

    commit c07d7476a382174d750b078189f1815a7c09f9f1
    Author: Robert Lupton the Good 
    Date:   Fri Jan 4 15:35:03 2013 -0500
    
        Improved doc string
    

    1d88db56

    commit 1d88db56e6d54c1184638f487cd340ea3231b440
    Author: dubcovsky 
    Date:   Fri Mar 13 00:27:36 2009 +0000
    
        added utility function for generating  DiaSources from Sources
    

    a66d6f8e

    commit a66d6f8ed4e59a00aed1cf9a2aefe243547b23b9
    Author: Robert Lupton the Good 
    Date:   Fri Jan 4 12:50:22 2013 -0500
    
        Refactor slicing implementation in preparation to implementing for other Image types
    

    84523580

    commit 84523580aaa6454a0e33b858b8c836c8ab355169
    Author: cloomis 
    Date:   Wed Feb 23 05:55:55 2011 +0000
    
        Mineo's persistence changes for HSC DC2
    

    a7ce1e71

    commit a7ce1e71d391ee1b194eabea9cead705bd9858da
    Author: Jim Bosch 
    Date:   Mon Mar 19 16:09:24 2012 -0400
    
        moved ndarray out of lsst namespace and header directories
    

    0fea4663

    commit 0fea466345c71fc0b992b448402df08a0d4fffb8
    Author: Robert Lupton the Good 
    Date:   Fri Jan 4 15:34:51 2013 -0500
    
        Allow us to index an image with a Box2I
        
        e.g. im[bbox] += 1
    

    079e0cfe

    commit 079e0cfee47219568525ef49dec79e095bd5b56f
    Author: Robert Lupton the Good 
    Date:   Fri Jan 4 13:19:34 2013 -0500
    
        Support indexing with negative numbers
    

    ad4a9b08

    commit ad4a9b08c6591e9890063580eccae794e67b4341
    Author: jbosch 
    Date:   Wed Jan 13 01:54:23 2010 +0000
    
        afw/#0
         - changes for #1130 (implemented directly in trunk)
         - adding temporary fix for #1131 (not yet done, but trunk builds better than it did before, and I have to go home now and work from there)
    

    23615386

    commit 236153869a9b321e896f4e7e786b74cfa7423c73
    Author: Robert Lupton the Good 
    Date:   Fri Jan 4 14:52:04 2013 -0500
    
        Handle inability to convert Exposure/MaskedImage pixels more cleanly
    

    d0950ae6

    commit d0950ae605e9f616b9ce46becebe81807151ed03
    Author: Jim Bosch 
    Date:   Mon Jun 2 15:51:03 2014 -0400
    
        Python wrappers, unit tests for ApCorrMap
    

    fffc4bea

    commit fffc4bea3c8f5006272ed340560a41a566f1e58b
    Author: Robert Lupton the Good 
    Date:   Fri Jan 4 14:07:55 2013 -0500
    
        Allow single-pixel images to be converted to float or int
        
        This permits e.g. print float(im[5, 6])
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    853c5734

    commit 853c5734ee13f55fd35e9e18ed5ac69a0073b97f
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:18:28 2015 -0400
    
        Utilize new numeric scalar typemaps and NumPy import macro.
    

    Return to list

    tests/statBug1697.py

    Diff:

    1 d27ed89c - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import unittest import numpy import lsst.utils.tests as utilsTests import lsst.afw.math as afwMath import lsst.afw.image as afwImage class weightedStatsBugTestCase(unittest.TestCase): def reportBadPixels(self, maskedImage, badPixelMask): """Report the number of bad pixels in each plane of a masked image Reports: - the number of non-finite values in the image plane - the number of bad pixels in the mask plane - the number of non-finite values in the variance plane """ arrayList = maskedImage.getArrays() nBadImg = numpy.logical_not(numpy.isfinite(arrayList[0])).sum() nBadMsk = numpy.sum(numpy.bitwise_and(arrayList[1], badPixelMask) > 0) nBadVar = numpy.logical_not(numpy.isfinite(arrayList[2])).sum() print "%d bad image pixels, %d bad mask pixels, %d bad variance pixels" % (nBadImg, nBadMsk, nBadVar) self.assertEqual(nBadImg, 0) self.assertEqual(nBadMsk, 0) self.assertEqual(nBadVar, 0) def testWeightedStats(self): """Test that bug from #1697 (weighted stats returning NaN) stays fixed.""" rand = afwMath.Random() mu = 10000 edgeMask = afwImage.MaskU.getPlaneBitMask("EDGE") badPixelMask = afwImage.MaskU.getPlaneBitMask("EDGE") statsCtrl = afwMath.StatisticsControl() statsCtrl.setNumSigmaClip(3.0) statsCtrl.setNumIter(2) statsCtrl.setAndMask(badPixelMask) for weight in (300.0, 10.0, 1.0): print "Testing with weight=%0.1f" % (weight,) maskedImageList = afwImage.vectorMaskedImageF() # [] is rejected by afwMath.statisticsStack weightList = [] nx, ny = 256, 256 for i in range(3): print "Processing ", i maskedImage = afwImage.MaskedImageF(nx, ny) maskedImageList.append(maskedImage) afwMath.randomPoissonImage(maskedImage.getImage(), rand, mu) maskedImage.getVariance().set(mu) weightList.append(weight) self.reportBadPixels(maskedImage, badPixelMask) print "Stack: ", coaddMaskedImage = afwMath.statisticsStack( maskedImageList, afwMath.MEANCLIP, statsCtrl, weightList) self.reportBadPixels(coaddMaskedImage, badPixelMask) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(weightedStatsBugTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) if __name__ == "__main__": utilsTests.run(suite())

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d27ed89c

    commit d27ed89ce52ffd37976091bf916a61cfa37a263f
    Author: bick 
    Date:   Sun Jun 5 17:08:29 2011 +0000
    
        added test for #1697 bug.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    src/math/Stack.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file Stack.cc
                     * @brief Provide functions to stack images
                     * @ingroup stack
                     * @author Steve Bickerton
                     *
                     */
                    #include 
                    #include 
                    #include "boost/shared_ptr.hpp"
                    
                    #include "lsst/base.h"
                    #include "lsst/utils/ieee.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/Stack.h"
                    #include "lsst/afw/math/MaskedVector.h"
                    
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwImage = lsst::afw::image;
                    namespace afwMath  = lsst::afw::math;
                    namespace pexExcept = lsst::pex::exceptions;
                    
                    namespace {
                        typedef std::vector WeightVector; // vector of weights (yes, really)
                    /*
                     * A bit counter (to make sure that only one type of statistics has been requested)
                     */
                    int bitcount(unsigned int x)
                    {
                        int b;
                        for (b = 0; x != 0; x >>= 1) {
                            if (x & 01) {
                                b++;
                            }
                        }
                        return b;
                    }
                    
                    /*
                     * Check that only one type of statistics has been requested.
                     */
                    void checkOnlyOneFlag(unsigned int flags) {
                        if (bitcount(flags & ~afwMath::ERRORS) != 1) {
    
    68 a3f53cb9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    68 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ "Requested more than one type of statistic to make the image stack."); } } /* * Check that we have objects, and the right number of weights (or none) */ template void checkObjectsAndWeights(ObjectVectorT const& objects, WeightVectorT const& wvector ) { if (objects.size() == 0) {
    84 55b55c0a - throw LSST_EXCEPT(pexExcept::LengthErrorException, "Please specify at least one object to stack");
    ? ---------
    84 21597d88 + throw LSST_EXCEPT(pexExcept::LengthError, "Please specify at least one object to stack");
    } if (!wvector.empty() && wvector.size() != objects.size() ) {
    88 55b55c0a - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    88 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ str(boost::format("Weight vector has different length " "from number of objects to be stacked: %d v. %d") % wvector.size() % objects.size())); } } template void checkImageSizes(ImageT const& out, std::vector const& images) { afwGeom::Extent2I const& dim = out.getDimensions(); for (unsigned int i = 0; i < images.size(); ++i) { if (images[i]->getDimensions() != dim) {
    101 f82e07fb - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    101 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ (boost::format("Bad dimensions for image %d: %dx%d vs %dx%d") % i % images[i]->getDimensions().getX() % images[i]->getDimensions().getY() % dim.getX() % dim.getY()).str()); } } } /**************************************************************************** * * stack MaskedImages * ****************************************************************************/ /* * A function to handle MaskedImage stacking * * A boolean template variable has been used to allow the compiler to generate the different instantiations * to handle cases when we are, or are not, weighting * * Additionally, we may or may not want to weight based on the variance -- another template boolean */ template void computeMaskedImageStack( afwImage::MaskedImage & imgStack, std::vector::Ptr > const &images, afwMath::Property flags, afwMath::StatisticsControl const& sctrl, WeightVector const &wvector=WeightVector() ) { // get a list of row_begin iterators typedef typename afwImage::MaskedImage::x_iterator x_iterator; std::vector rows; rows.reserve(images.size()); afwMath::MaskedVector pixelSet(images.size()); // a pixel from x,y for each image WeightVector weights; // weights; non-const version // afwMath::StatisticsControl sctrlTmp(sctrl); if (useVariance) { // weight using the variance image assert(isWeighted); assert(wvector.empty()); weights.resize(images.size()); sctrlTmp.setWeighted(true); } else if (isWeighted) { weights.assign(wvector.begin(), wvector.end()); sctrlTmp.setWeighted(true); } assert (weights.empty() || weights.size() == images.size()); // loop over x,y ... the loop over the stack to fill pixelSet // - get the stats on pixelSet and put the value in the output image at x,y for (int y = 0; y != imgStack.getHeight(); ++y) { for (unsigned int i = 0; i < images.size(); ++i) { x_iterator ptr = images[i]->row_begin(y); if (y == 0) { rows.push_back(ptr); } else { rows[i] = ptr; } } for (x_iterator ptr = imgStack.row_begin(y), end = imgStack.row_end(y); ptr != end; ++ptr) { typename afwMath::MaskedVector::iterator psPtr = pixelSet.begin(); WeightVector::iterator wtPtr = weights.begin(); for (unsigned int i = 0; i < images.size(); ++rows[i], ++i, ++psPtr, ++wtPtr) { *psPtr = *rows[i]; if (useVariance) { // we're weighting using the variance *wtPtr = 1.0/rows[i].variance(); } } afwMath::Property const eflags = static_cast(flags | afwMath::NPOINT | afwMath::ERRORS); afwMath::Statistics stat = isWeighted ? afwMath::makeStatistics(pixelSet, weights, eflags, sctrlTmp) : afwMath::makeStatistics(pixelSet, eflags, sctrlTmp); PixelT variance = ::pow(stat.getError(flags), 2); afwImage::MaskPixel msk(stat.getOrMask()); int const npoint = stat.getValue(afwMath::NPOINT); if (npoint == 0) { msk = sctrlTmp.getNoGoodPixelsMask(); } else if (npoint == 1) { /* * you should be using sctrl.setCalcErrorFromInputVariance(true) if you want to avoid * getting a variance of NaN when you only have one input */ } *ptr = typename afwImage::MaskedImage::Pixel(stat.getValue(flags), msk, variance); } } } } // end anonymous namespace /* * A function to compute some statistics of a stack of Masked Images * * If none of the input images are valid for some pixel, * the afwMath::StatisticsControl::getNoGoodPixelsMask() bit(s) are set. * * All the work is done in the function computeMaskedImageStack. */ template typename afwImage::MaskedImage::Ptr afwMath::statisticsStack( std::vector::Ptr > &images, afwMath::Property flags, afwMath::StatisticsControl const& sctrl, WeightVector const &wvector ) { if (images.size() == 0) {
    221 f82e07fb - throw LSST_EXCEPT(pexExcept::LengthErrorException, "Please specify at least one image to stack");
    ? ---------
    221 21597d88 + throw LSST_EXCEPT(pexExcept::LengthError, "Please specify at least one image to stack");
    } typename afwImage::MaskedImage::Ptr out( new afwImage::MaskedImage(images[0]->getDimensions())); statisticsStack(*out, images, flags, sctrl, wvector); return out; } template void afwMath::statisticsStack( afwImage::MaskedImage& out, std::vector::Ptr > &images, afwMath::Property flags, afwMath::StatisticsControl const& sctrl, WeightVector const &wvector ) { checkObjectsAndWeights(images, wvector); checkOnlyOneFlag(flags); checkImageSizes(out, images); if (sctrl.getWeighted()) { if (wvector.empty()) { return computeMaskedImageStack(out, images, flags, sctrl); // use variance } else { return computeMaskedImageStack(out, images, flags, sctrl, wvector); // use wvector } } else { return computeMaskedImageStack(out, images, flags, sctrl); } } namespace { /**************************************************************************** * * stack Images * * All the work is done in the function comuteImageStack. * A boolean template variable has been used to allow the compiler to generate the different instantiations * to handle cases when we are, or are not, weighting * ****************************************************************************/ /* * A function to compute some statistics of a stack of regular images * * A boolean template variable has been used to allow the compiler to generate the different instantiations * to handle cases when we are, or are not, weighting */ template void computeImageStack( afwImage::Image & imgStack, std::vector::Ptr > &images, afwMath::Property flags, afwMath::StatisticsControl const& sctrl, WeightVector const &weights=WeightVector() ) { afwMath::MaskedVector pixelSet(images.size()); // a pixel from x,y for each image afwMath::StatisticsControl sctrlTmp(sctrl); // set the mask to be an infinite iterator afwMath::MaskImposter msk; if (!weights.empty()) { sctrlTmp.setWeighted(true); } // get the desired statistic for (int y = 0; y != imgStack.getHeight(); ++y) { for (int x = 0; x != imgStack.getWidth(); ++x) { for (unsigned int i = 0; i != images.size(); ++i) { (*pixelSet.getImage())(i, 0) = (*images[i])(x, y); } if (isWeighted) { imgStack(x, y) = afwMath::makeStatistics(pixelSet, weights, flags, sctrlTmp).getValue(); } else { imgStack(x, y) = afwMath::makeStatistics(pixelSet, weights, flags, sctrlTmp).getValue(); } } } } } // end anonymous namespace template typename afwImage::Image::Ptr afwMath::statisticsStack( std::vector::Ptr > &images, afwMath::Property flags, afwMath::StatisticsControl const& sctrl, WeightVector const &wvector ) { if (images.size() == 0) {
    318 f82e07fb - throw LSST_EXCEPT(pexExcept::LengthErrorException, "Please specify at least one image to stack");
    ? ---------
    318 21597d88 + throw LSST_EXCEPT(pexExcept::LengthError, "Please specify at least one image to stack");
    } typename afwImage::Image::Ptr out(new afwImage::Image(images[0]->getDimensions())); statisticsStack(*out, images, flags, sctrl, wvector); return out; } template void afwMath::statisticsStack( afwImage::Image & out, std::vector::Ptr > &images, afwMath::Property flags, afwMath::StatisticsControl const& sctrl, WeightVector const &wvector ) { checkObjectsAndWeights(images, wvector); checkOnlyOneFlag(flags); checkImageSizes(out, images); if (wvector.empty()) { return computeImageStack(out, images, flags, sctrl); } else { return computeImageStack(out, images, flags, sctrl, wvector); } } /**************************************************************************** * * stack VECTORS * ****************************************************************************/ namespace { /**********************************************************************************/ /* * A function to compute some statistics of a stack of vectors * * A boolean template variable has been used to allow the compiler to generate the different instantiations * to handle cases when we are, or are not, weighting */ template typename boost::shared_ptr > computeVectorStack( std::vector > > &vectors, afwMath::Property flags, afwMath::StatisticsControl const& sctrl, WeightVector const &wvector=WeightVector() ) { // create the image to be returned typedef std::vector Vect; boost::shared_ptr vecStack(new Vect(vectors[0]->size(), 0.0)); afwMath::MaskedVector pixelSet(vectors.size()); // values from a given pixel of each image afwMath::StatisticsControl sctrlTmp(sctrl); // set the mask to be an infinite iterator afwMath::MaskImposter msk; if (!wvector.empty()) { sctrlTmp.setWeighted(true); } // collect elements from the stack into the MaskedVector to do stats for (unsigned int x = 0; x < vectors[0]->size(); ++x) { typename afwMath::MaskedVector::iterator psPtr = pixelSet.begin(); for (unsigned int i = 0; i < vectors.size(); ++i, ++psPtr) { psPtr.value() = (*vectors[i])[x]; } if (isWeighted) { (*vecStack)[x] = afwMath::makeStatistics(pixelSet, wvector, flags, sctrlTmp).getValue(flags); } else { (*vecStack)[x] = afwMath::makeStatistics(pixelSet, flags, sctrlTmp).getValue(flags); } } return vecStack; } } // end anonymous namespace template boost::shared_ptr > afwMath::statisticsStack( std::vector > > &vectors, afwMath::Property flags, afwMath::StatisticsControl const& sctrl, WeightVector const &wvector ) { checkObjectsAndWeights(vectors, wvector); checkOnlyOneFlag(flags); if (wvector.empty()) { return computeVectorStack(vectors, flags, sctrl); } else { return computeVectorStack(vectors, flags, sctrl, wvector); } } /************************************************************************** * * XY row column stacking * **************************************************************************/ template typename afwImage::MaskedImage::Ptr afwMath::statisticsStack( afwImage::Image const &image, afwMath::Property flags, char dimension, afwMath::StatisticsControl const& sctrl ) { int x0 = image.getX0(); int y0 = image.getY0(); typedef afwImage::MaskedImage MImage; typename MImage::Ptr imgOut; // do each row or column, one at a time // - create a subimage with a bounding box, and get the stats and assign the value to the output image if (dimension == 'x') { imgOut = typename MImage::Ptr( new MImage(geom::Extent2I(1, image.getHeight())) ); int y = y0; typename MImage::y_iterator oEnd = imgOut->col_end(0); for (typename MImage::y_iterator oPtr = imgOut->col_begin(0); oPtr != oEnd; ++oPtr, ++y) { geom::Box2I bbox = afwGeom::Box2I( geom::Point2I(x0, y), geom::Extent2I(image.getWidth(), 1) );
    454 9964091c - afwImage::Image subImage(image, bbox, afwImage::PARENT);
    ? ------------------
    454 93994d54 + afwImage::Image subImage(image, bbox);
    Statistics stat = makeStatistics(subImage, flags | afwMath::ERRORS, sctrl); *oPtr = typename afwImage::MaskedImage::Pixel( stat.getValue(), 0x0, stat.getError()*stat.getError() ); } } else if (dimension == 'y') { imgOut = typename MImage::Ptr(new MImage(geom::Extent2I(image.getWidth(), 1))); int x = x0; typename MImage::x_iterator oEnd = imgOut->row_end(0); for (typename MImage::x_iterator oPtr = imgOut->row_begin(0); oPtr != oEnd; ++oPtr, ++x) { geom::Box2I bbox = geom::Box2I( geom::Point2I(x, y0), geom::Extent2I(1, image.getHeight()) );
    470 9964091c - afwImage::Image subImage(image, bbox, afwImage::PARENT);
    ? ------------------
    470 93994d54 + afwImage::Image subImage(image, bbox);
    afwMath::Statistics stat = makeStatistics(subImage, flags | afwMath::ERRORS, sctrl); *oPtr = typename afwImage::MaskedImage::Pixel(stat.getValue(), 0x0, stat.getError()*stat.getError()); } } else {
    476 a3f53cb9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    476 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ "Can only run statisticsStack in x or y for single image."); } return imgOut; } template typename afwImage::MaskedImage::Ptr afwMath::statisticsStack( afwImage::MaskedImage const &image, afwMath::Property flags, char dimension, afwMath::StatisticsControl const& sctrl ) { int const x0 = image.getX0(); int const y0 = image.getY0(); typedef afwImage::MaskedImage MImage; typename MImage::Ptr imgOut; // do each row or column, one at a time // - create a subimage with a bounding box, and get the stats and assign the value to the output image if (dimension == 'x') { imgOut = typename MImage::Ptr(new MImage(geom::Extent2I(1, image.getHeight()))); int y = 0; typename MImage::y_iterator oEnd = imgOut->col_end(0); for (typename MImage::y_iterator oPtr = imgOut->col_begin(0); oPtr != oEnd; ++oPtr, ++y) { afwGeom::Box2I bbox = afwGeom::Box2I(afwGeom::Point2I(x0, y), geom::Extent2I(image.getWidth(), 1));
    506 9964091c - afwImage::MaskedImage subImage(image, bbox, afwImage::PARENT);
    ? ------------------
    506 93994d54 + afwImage::MaskedImage subImage(image, bbox);
    afwMath::Statistics stat = makeStatistics(subImage, flags | afwMath::ERRORS, sctrl); *oPtr = typename afwImage::MaskedImage::Pixel(stat.getValue(), 0x0, stat.getError()*stat.getError()); } } else if (dimension == 'y') { imgOut = typename MImage::Ptr(new MImage(geom::Extent2I(image.getWidth(), 1))); int x = 0; typename MImage::x_iterator oEnd = imgOut->row_end(0); for (typename MImage::x_iterator oPtr = imgOut->row_begin(0); oPtr != oEnd; ++oPtr, ++x) { afwGeom::Box2I bbox = afwGeom::Box2I(afwGeom::Point2I(x, y0), geom::Extent2I(1, image.getHeight()));
    518 9964091c - afwImage::MaskedImage subImage(image, bbox, afwImage::PARENT);
    ? ------------------
    518 93994d54 + afwImage::MaskedImage subImage(image, bbox);
    afwMath::Statistics stat = makeStatistics(subImage, flags | afwMath::ERRORS, sctrl); *oPtr = typename afwImage::MaskedImage::Pixel(stat.getValue(), 0x0, stat.getError()*stat.getError()); } } else {
    524 a3f53cb9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    524 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ "Can only run statisticsStack in x or y for single image."); } return imgOut; } /************************************************************************************************************/ /* * Explicit Instantiations * */ /// \cond #define INSTANTIATE_STACKS(TYPE) \ template afwImage::Image::Ptr afwMath::statisticsStack( \ std::vector::Ptr > &images, \ afwMath::Property flags, \ afwMath::StatisticsControl const& sctrl, \ WeightVector const &wvector); \ template void afwMath::statisticsStack( \ afwImage::Image &out, \ std::vector::Ptr > &images, \ afwMath::Property flags, \ afwMath::StatisticsControl const& sctrl, \ WeightVector const &wvector); \ template afwImage::MaskedImage::Ptr afwMath::statisticsStack( \ std::vector::Ptr > &images, \ afwMath::Property flags, \ afwMath::StatisticsControl const& sctrl, \ WeightVector const &wvector); \ template void afwMath::statisticsStack( \ afwImage::MaskedImage &out, \ std::vector::Ptr > &images, \ afwMath::Property flags, \ afwMath::StatisticsControl const& sctrl, \ WeightVector const &wvector); \ template boost::shared_ptr > afwMath::statisticsStack( \ std::vector > > &vectors, \ afwMath::Property flags, \ afwMath::StatisticsControl const& sctrl, \ WeightVector const &wvector); \ template afwImage::MaskedImage::Ptr afwMath::statisticsStack( \ afwImage::Image const &image, \ afwMath::Property flags, \ char dimension, \ afwMath::StatisticsControl const& sctrl); \ template afwImage::MaskedImage::Ptr afwMath::statisticsStack( \ afwImage::MaskedImage const &image, \ afwMath::Property flags, \ char dimension, \ afwMath::StatisticsControl const& sctrl); INSTANTIATE_STACKS(double) INSTANTIATE_STACKS(float) /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    55b55c0a

    commit 55b55c0a8b974350d6cedbaf17cd20ad859f46e1
    Author: rhl 
    Date:   Fri Sep 30 04:44:00 2011 +0000
    
        Cleanup
    

    9964091c

    commit 9964091c98bc6b9daa98b6379ea1b22c6fa85e91
    Author: rowen 
    Date:   Wed Mar 16 23:04:33 2011 +0000
    
        I tried to eliminate doxygen warnings in afw 1556. I came pretty close. There are two known issues:
        - Doxygen has a bug that prevents documenting template specializations. There are two of these in
           src/geom/Extent.cc
           that I hide from Doxygen with a note and \cond BUG406027
        - src/coord/Coord.cc produces two Doxygen warnings that I've not been able to eliminate. I don't have any idea what is causing them.
        
        Unfortunately, fixing Doxygen warnings requires some cluttering up the the code, in particular spelling out namespaces in arguments.
        
        
        Other changes:
        - std::osstream operator<< functions in AffineTransform.h and LinearTransform.h were friend functions, but did not need to be. I changed this, partly because Doxygen was unhappy.
        - I removed all use of "namespace foo=lsst::..."  in header files.
        - I replaced daf::base:: with lsst::daf::base:: in some header files. I'm surprised the former worked; I've reported it as a bug against daf_base.
        
        BTW: this code fails on Mac OS X Leopard; the tests/footprintArray.cc fails to compile.
    

    a3f53cb9

    commit a3f53cb981bddaceba2f5dd70935493304af7840
    Author: rhl 
    Date:   Fri Sep 30 03:52:12 2011 +0000
    
        Reworked Stack code to separate variances from weight vectors
    

    f82e07fb

    commit f82e07fbdabd41f76e11abe937b7918e1df107d6
    Author: Paul Price 
    Date:   Fri Mar 30 14:39:21 2012 -0400
    
        Add in-place option for statisticsStack
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    include/lsst/afw/image/Calib.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    //
                    /**
                     * \file
                     *
                     * Classes to support calibration (e.g. photometric zero points, exposure times)
                     */
                    #ifndef LSST_AFW_IMAGE_CALIB_H
                    #define LSST_AFW_IMAGE_CALIB_H
                    
    
    34 f5211fdc + #include
    #include #include "boost/shared_ptr.hpp" #include "ndarray_fwd.h" #include "lsst/base.h" #include "lsst/daf/base/DateTime.h" #include "lsst/afw/geom/Point.h" #include "lsst/afw/table/io/Persistable.h" namespace lsst { namespace daf { namespace base { class PropertySet; } } namespace afw { namespace cameraGeom { class Detector; } namespace image {
    55 f5211fdc +
    56 f5211fdc + static double const JanskysPerABFlux = 3631.0;
    57 f5211fdc +
    58 f5211fdc + /// Compute AB magnitude from flux in Janskys
    59 f5211fdc + inline double abMagFromFlux(double flux) {
    60 f5211fdc + return -2.5*std::log10(flux/JanskysPerABFlux);
    61 f5211fdc + }
    62 f5211fdc +
    63 f5211fdc + /// Compute AB magnitude error from flux and flux error in Janskys
    64 f5211fdc + inline double abMagErrFromFluxErr(double fluxErr, double flux) {
    65 f5211fdc + return std::abs(fluxErr/(-0.4*flux*std::log(10)));
    66 f5211fdc + }
    67 f5211fdc +
    68 f5211fdc + /// Compute flux in Janskys from AB magnitude
    69 f5211fdc + inline double fluxFromABMag(double mag) {
    70 f5211fdc + return std::pow(10.0, -0.4*mag)*JanskysPerABFlux;
    71 f5211fdc + }
    72 f5211fdc +
    73 f5211fdc + /// Compute flux error in Janskys from AB magnitude error and AB magnitude
    74 f5211fdc + inline double fluxErrFromABMagErr(double magErr, double mag) {
    75 f5211fdc + return std::abs(-0.4*magErr*fluxFromABMag(mag)*std::log(10.0));
    76 f5211fdc + }
    77 f5211fdc +
    /** * Describe an exposure's calibration */ class Calib : public table::io::PersistableFacade, public table::io::Persistable { public : typedef boost::shared_ptr Ptr; typedef boost::shared_ptr ConstPtr; explicit Calib(); explicit Calib(std::vector const& calibs); explicit Calib(CONST_PTR(lsst::daf::base::PropertySet)); void setMidTime(lsst::daf::base::DateTime const& midTime); lsst::daf::base::DateTime getMidTime () const; lsst::daf::base::DateTime getMidTime(boost::shared_ptr, lsst::afw::geom::Point2I const&) const; void setExptime(double exptime); double getExptime() const; void setFluxMag0(double fluxMag0, double fluxMag0Sigma=0.0); void setFluxMag0(std::pair fluxMag0AndSigma); std::pair getFluxMag0() const; double getFlux(double const mag) const; std::pair getFlux(double const mag, double const magErr) const; ndarray::Array getFlux(ndarray::Array const & mag) const; std::pair< ndarray::Array, ndarray::Array > getFlux( ndarray::Array const & mag, ndarray::Array const & magErr ) const; double getMagnitude(double const flux) const; std::pair getMagnitude(double const flux, double const fluxErr) const; ndarray::Array getMagnitude(ndarray::Array const & flux) const; std::pair< ndarray::Array,ndarray::Array > getMagnitude( ndarray::Array const & flux, ndarray::Array const & fluxErr ) const; static void setThrowOnNegativeFlux(bool raiseException); static bool getThrowOnNegativeFlux(); /* * Compare two Calibs */ bool operator==(Calib const& rhs) const; bool operator!=(Calib const& rhs) const { return !(*this == rhs); }
    109 f3d3029c - void operator*=(double const scale);
    110 f3d3029c - void operator/=(double const scale) { (*this) *= 1.0/scale; }
    111 f3d3029c -
    bool isPersistable() const { return true; } protected: virtual std::string getPersistenceName() const; virtual void write(OutputArchiveHandle & handle) const; private: lsst::daf::base::DateTime _midTime; double _exptime; double _fluxMag0; double _fluxMag0Sigma; static bool _throwOnNegativeFlux; }; namespace detail { int stripCalibKeywords(PTR(lsst::daf::base::PropertySet) metadata); } }}} // lsst::afw::image #endif // LSST_AFW_IMAGE_CALIB_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f3d3029c

    commit f3d3029c561b957069cbf280b62ea8e37447c068
    Author: Paul Price 
    Date:   Mon Apr 27 18:09:36 2015 -0400
    
        Calib: add operator*= for scaling zeropoint
    

    Commits in /Users/nate/repos_lsst/afw/

    f5211fdc

    commit f5211fdc4ea87f97d53c76931c3a5d62b1fcbd7c
    Author: Russell Owen 
    Date:   Fri Mar 6 14:57:36 2015 -0800
    
        Add functions to convert between flux in Jy and AB magnitudes
    

    Return to list

    tests/kernelIo1.py

    Diff:

    1 47a633de - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import unittest import numpy import lsst.utils.tests as utilsTests import lsst.pex.logging as pexLog import lsst.pex.policy as pexPolicy import lsst.daf.base as dafBase import lsst.daf.persistence as dafPersist import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom import lsst.afw.image.testUtils as imTestUtils Verbosity = 0 # increase to see trace pexLog.Debug("lsst.afw", Verbosity) # pexLog.Debug("afw.math.KernelFormatter", 30) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class KernelIOTestCase(unittest.TestCase): """A test case for Kernel I/O""" def kernelCheck(self, k1, k2): self.assertEqual(k1.getWidth(), k2.getWidth()) self.assertEqual(k1.getHeight(), k2.getHeight()) self.assertEqual(k1.getCtrX(), k2.getCtrX()) self.assertEqual(k1.getCtrY(), k2.getCtrY()) self.assertEqual(k1.getNKernelParameters(), k2.getNKernelParameters()) self.assertEqual(k1.getNSpatialParameters(), k2.getNSpatialParameters()) self.assertEqual(k1.getKernelParameters(), k2.getKernelParameters()) self.assertEqual(k1.getSpatialParameters(), k2.getSpatialParameters()) self.assertEqual(k1.isSpatiallyVarying(), k2.isSpatiallyVarying()) self.assertEqual(k1.toString(), k2.toString()) def testFixedKernel(self): """Test FixedKernel using a ramp function """ kWidth = 5 kHeight = 6 inArr = numpy.arange(kWidth * kHeight, dtype=float) inArr.shape = [kWidth, kHeight] inImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) for row in range(inImage.getHeight()): for col in range(inImage.getWidth()): inImage.set(col, row, inArr[col, row]) k = afwMath.FixedKernel(inImage) pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel1.boost") persistence = dafPersist.Persistence.getPersistence(pol) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("FixedKernel", storageList2, additionalData) k2 = afwMath.FixedKernel.swigConvert(x) self.kernelCheck(k, k2) outImage = afwImage.ImageD(k2.getDimensions()) k2.computeImage(outImage, False) outArr = outImage.getArray().transpose() if not numpy.allclose(inArr, outArr): self.fail("%s = %s != %s (not normalized)" % \ (k2.__class__.__name__, inArr, outArr)) normInArr = inArr / inArr.sum() normOutImage = afwImage.ImageD(k2.getDimensions()) k2.computeImage(normOutImage, True) normOutArr = normOutImage.getArray().transpose() if not numpy.allclose(normOutArr, normInArr): self.fail("%s = %s != %s (normalized)" % \ (k2.__class__.__name__, normInArr, normOutArr)) def testAnalyticKernel(self): """Test AnalyticKernel using a Gaussian function """ kWidth = 5 kHeight = 8 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel2.boost") persistence = dafPersist.Persistence.getPersistence(pol) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) k = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) fArr = numpy.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) for xsigma in (0.1, 1.0, 3.0): for ysigma in (0.1, 1.0, 3.0): for angle in (0.0, 0.4, 1.1): gaussFunc.setParameters((xsigma, ysigma, angle)) # compute array of function values and normalize for row in range(k.getHeight()): y = row - k.getCtrY() for col in range(k.getWidth()): x = col - k.getCtrX() fArr[col, row] = gaussFunc(x, y) fArr /= fArr.sum() k.setKernelParameters((xsigma, ysigma, angle)) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("AnalyticKernel", storageList2, additionalData) k2 = afwMath.AnalyticKernel.swigConvert(x) self.kernelCheck(k, k2) kImage = afwImage.ImageD(k2.getDimensions()) k2.computeImage(kImage, True) kArr = kImage.getArray().transpose() if not numpy.allclose(fArr, kArr): self.fail("%s = %s != %s for xsigma=%s, ysigma=%s" % \ (k2.__class__.__name__, kArr, fArr, xsigma, ysigma)) def testDeltaFunctionKernel(self): """Test DeltaFunctionKernel """ pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel3.boost") persistence = dafPersist.Persistence.getPersistence(pol) for kWidth in range(1, 4): for kHeight in range(1, 4): for activeCol in range(kWidth): for activeRow in range(kHeight): kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, afwGeom.Point2I(activeCol, activeRow)) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(kernel, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("DeltaFunctionKernel", storageList2, additionalData) k2 = afwMath.DeltaFunctionKernel.swigConvert(x) self.kernelCheck(kernel, k2) self.assertEqual(kernel.getPixel(), k2.getPixel()) kImage = afwImage.ImageD(k2.getDimensions()) kSum = k2.computeImage(kImage, False) self.assertEqual(kSum, 1.0) kArr = kImage.getArray().transpose() self.assertEqual(kArr[activeCol, activeRow], 1.0) kArr[activeCol, activeRow] = 0.0 self.assertEqual(kArr.sum(), 0.0) def testSeparableKernel(self): """Test SeparableKernel using a Gaussian function """ kWidth = 5 kHeight = 8 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel4.boost") persistence = dafPersist.Persistence.getPersistence(pol) gaussFunc1 = afwMath.GaussianFunction1D(1.0) k = afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1) fArr = numpy.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) gArr = numpy.zeros(shape=[k.getWidth(), k.getHeight()], dtype=float) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) for xsigma in (0.1, 1.0, 3.0): gaussFunc1.setParameters((xsigma,)) for ysigma in (0.1, 1.0, 3.0): gaussFunc.setParameters((xsigma, ysigma, 0.0)) # compute array of function values and normalize for row in range(k.getHeight()): y = row - k.getCtrY() for col in range(k.getWidth()): x = col - k.getCtrX() fArr[col, row] = gaussFunc(x, y) fArr /= fArr.sum() k.setKernelParameters((xsigma, ysigma)) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("SeparableKernel", storageList2, additionalData) k2 = afwMath.SeparableKernel.swigConvert(x) self.kernelCheck(k, k2) kImage = afwImage.ImageD(k2.getDimensions()) k2.computeImage(kImage, True) kArr = kImage.getArray().transpose() if not numpy.allclose(fArr, kArr): self.fail("%s = %s != %s for xsigma=%s, ysigma=%s" % \ (k2.__class__.__name__, kArr, fArr, xsigma, ysigma)) def testLinearCombinationKernel(self): """Test LinearCombinationKernel using a set of delta basis functions """ kWidth = 3 kHeight = 2 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel5.boost") persistence = dafPersist.Persistence.getPersistence(pol) # create list of kernels basisImArrList = [] kVec = afwMath.KernelList() for row in range(kHeight): for col in range(kWidth): kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, afwGeom.Point2I(col, row)) basisImage = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(basisImage, True) basisImArrList.append(basisImage.getArray().transpose().copy()) kVec.append(kernel) kParams = [0.0]*len(kVec) k = afwMath.LinearCombinationKernel(kVec, kParams) for ii in range(len(kVec)): kParams = [0.0]*len(kVec) kParams[ii] = 1.0 k.setKernelParameters(kParams) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("LinearCombinationKernel", storageList2, additionalData) k2 = afwMath.LinearCombinationKernel.swigConvert(x) self.kernelCheck(k, k2) kIm = afwImage.ImageD(k2.getDimensions()) k2.computeImage(kIm, True) kImArr = kIm.getArray().transpose() if not numpy.allclose(kImArr, basisImArrList[ii]): self.fail("%s = %s != %s for the %s'th basis kernel" % \ (k2.__class__.__name__, kImArr, basisImArrList[ii], ii)) def testSVLinearCombinationKernel(self): """Test a spatially varying LinearCombinationKernel """ kWidth = 3 kHeight = 2 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel6.boost") persistence = dafPersist.Persistence.getPersistence(pol) # create image arrays for the basis kernels basisImArrList = [] imArr = numpy.zeros((kWidth, kHeight), dtype=float) imArr += 0.1 imArr[kWidth//2, :] = 0.9 basisImArrList.append(imArr) imArr = numpy.zeros((kWidth, kHeight), dtype=float) imArr += 0.2 imArr[:, kHeight//2] = 0.8 basisImArrList.append(imArr) # create a list of basis kernels from the images kVec = afwMath.KernelList() for basisImArr in basisImArrList: basisImage = afwImage.makeImageFromArray(basisImArr.transpose().copy()) kernel = afwMath.FixedKernel(basisImage) kVec.append(kernel) # create spatially varying linear combination kernel spFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (0.0, 1.0, 0.0), (0.0, 0.0, 1.0), ) k = afwMath.LinearCombinationKernel(kVec, spFunc) k.setSpatialParameters(sParams) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("LinearCombinationKernel", storageList2, additionalData) k2 = afwMath.LinearCombinationKernel.swigConvert(x) self.kernelCheck(k, k2) kImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) for colPos, rowPos, coeff0, coeff1 in [ (0.0, 0.0, 0.0, 0.0), (1.0, 0.0, 1.0, 0.0), (0.0, 1.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0), (0.5, 0.5, 0.5, 0.5), ]: k2.computeImage(kImage, False, colPos, rowPos) kImArr = kImage.getArray().transpose() refKImArr = (basisImArrList[0] * coeff0) + (basisImArrList[1] * coeff1) if not numpy.allclose(kImArr, refKImArr): self.fail("%s = %s != %s at colPos=%s, rowPos=%s" % \ (k2.__class__.__name__, kImArr, refKImArr, colPos, rowPos)) def testSetCtr(self): """Test setCtrCol/Row""" kWidth = 3 kHeight = 4 pol = pexPolicy.Policy() additionalData = dafBase.PropertySet() loc = dafPersist.LogicalLocation("tests/data/kernel7.boost") persistence = dafPersist.Persistence.getPersistence(pol) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) k = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) for xCtr in range(kWidth): k.setCtrX(xCtr) for yCtr in range(kHeight): k.setCtrY(yCtr) storageList = dafPersist.StorageList() storage = persistence.getPersistStorage("XmlStorage", loc) storageList.append(storage) persistence.persist(k, storageList, additionalData) storageList2 = dafPersist.StorageList() storage2 = persistence.getRetrieveStorage("XmlStorage", loc) storageList2.append(storage2) x = persistence.unsafeRetrieve("AnalyticKernel", storageList2, additionalData) k2 = afwMath.AnalyticKernel.swigConvert(x) self.kernelCheck(k, k2) self.assertEqual(k2.getCtrX(), xCtr) self.assertEqual(k2.getCtrY(), yCtr) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(KernelIOTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    47a633de

    commit 47a633de7b0dbe1ab8a1496cd5c09e6bb6e4435a
    Author: ktlim 
    Date:   Thu Mar 5 15:15:43 2009 +0000
    
        Major update for persistence of Kernels and Functions.
        
         * Add test cases for Kernel (and indirectly Function) persistence.
         * Make Kernel a Persistable.
         * Include %lsst_persistable() invocation for all Kernel types.
         * Move KernelFormatter from lsst::afw::math to lsst::afw::formatters.
         * Add registrations for Kernel subclasses (using same Formatter).
         * Make SConscript for lib and tests more generic.
         * Add boost::serialization::void_cast_register for non-default-constructor subclasses.
         * Template Function save_construct_data friends properly.
         * Move BOOST_CLASS_EXPORT invocations to Formatter.
         * Fix DeltaFunctionKernel save/load_construct_data.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    src/detection/FootprintSet.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     *
                     * \brief Utilities to detect sets of Footprint%s
                     *
                     * Create and use an lsst::afw::detection::FootprintSet, a collection of pixels above (or below) a threshold
                     * in an Image
                     *
                     * The "collections of pixels" are represented as lsst::afw::detection::Footprint%s, so an example application
                     * would be:
                     * \code
                        namespace image = lsst::afw::image; namespace detection = lsst::afw::detection;
                    
                        image::MaskedImage img(10,20);
                        *img.getImage() = 100;
                    
                        detection::FootprintSet sources(img, 10);
                        cout << "Found " << sources.getFootprints()->size() << " sources" << std::endl;
                     * \endcode
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include "boost/format.hpp"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/Statistics.h"
                    #include "lsst/afw/detection/Peak.h"
                    #include "lsst/afw/detection/FootprintFunctor.h"
                    #include "lsst/afw/detection/FootprintSet.h"
                    #include "lsst/afw/detection/FootprintCtrl.h"
                    #include "lsst/afw/detection/HeavyFootprint.h"
                    
                    namespace detection = lsst::afw::detection;
                    namespace image = lsst::afw::image;
                    namespace math = lsst::afw::math;
                    namespace pexLogging = lsst::pex::logging;
                    namespace geom = lsst::afw::geom;
                    
                    /************************************************************************************************************/
                    namespace {
                        /// Don't let doxygen see this block  \cond
                    
                        typedef boost::uint64_t IdPixelT;    // Type of temporary Images used in merging Footprints
                    
                        struct Threshold_traits {
                        };
                        struct ThresholdLevel_traits : public Threshold_traits { // Threshold is a single number
                        };
                        struct ThresholdPixelLevel_traits : public Threshold_traits { // Threshold varies from pixel to pixel
                        };
                        struct ThresholdBitmask_traits : public Threshold_traits { // Threshold ORs with a bitmask
                        };
                    
                        //
                        // Define our own functions to handle NaN tests;  this gives us the
                        // option to define a value for e.g. image::MaskPixel or int
                        //
                        template
                        inline bool isBadPixel(T) {
                            return false;
                        }
                    
                        template<>
                        inline bool isBadPixel(float val) {
                            return std::isnan(val);
                        }
                    
                        template<>
                        inline bool isBadPixel(double val) {
                            return std::isnan(val);
                        }
                    
                        /*
                         * Return the number of bits required to represent a unsigned long
                         */
                        int nbit(unsigned long i) {
                            int n = 0;
                            while (i > 0) {
                                ++n;
                                i >>= 1;
                            }
                    
                            return n;
                        }
                        /*
                         * Find the list of pixel values that lie in a Footprint
                         *
                         * Used when the Footprints are constructed from an Image containing Footprint indices
                         */
                        template 
                        class FindIdsInFootprint: public detection::FootprintFunctor {
                        public:
                            explicit FindIdsInFootprint(ImageT const& image ///< The image the source lives in
                                                       ) : detection::FootprintFunctor(image), _ids(), _old(0) {}
                            /// \brief Reset everything for a new Footprint
                            void reset() {
                                _ids.clear();
                                _old = 0;
                            }
                            
                            /// \brief method called for each pixel by apply()
                            void operator()(typename ImageT::xy_locator loc, ///< locator pointing at the pixel
                                            int x,                           ///< column-position of pixel
                                            int y                            ///< row-position of pixel
                                           ) {
                                typename ImageT::Pixel val = loc(0, 0);
                    
                                if (val != _old) {
                                    _ids.insert(val);
                                    _old = val;
                                }
                            }
                    
                            std::set const& getIds() const {
                                return _ids;
                            }
                    
                        private:
                            std::set _ids;
                            typename ImageT::Pixel _old;
                        };
                    
                        /********************************************************************************************************/
                        /*
                         * Sort peaks by decreasing pixel value.  N.b. -ve peaks are sorted the same way as +ve ones
                         */
                        struct SortPeaks {
                        bool operator()(CONST_PTR(detection::PeakRecord) a, CONST_PTR(detection::PeakRecord) b) {
                                if (a->getPeakValue() != b->getPeakValue()) {
                                    return (a->getPeakValue() > b->getPeakValue());
                                }
                    
                                if (a->getIx() != b->getIx()) {
                                    return (a->getIx() < b->getIx());
                                }
                    
                                return (a->getIy() < b->getIy());
                            }
                        };
                        /********************************************************************************************************/
                        /*
                         * Worker routine for merging two FootprintSets, possibly growing them as we proceed
                         */
                        detection::FootprintSet
                        mergeFootprintSets(
                            detection::FootprintSet const &lhs, // the FootprintSet to be merged to
                            int rLhs,                                         // Grow lhs Footprints by this many pixels
                            detection::FootprintSet const &rhs, // the FootprintSet to be merged into lhs
                            int rRhs,                                         // Grow rhs Footprints by this many pixels
                            detection::FootprintControl const& ctrl           // Control how the grow is done
                                          )
                        {
                            typedef detection::Footprint Footprint;
                            typedef detection::FootprintSet::FootprintList FootprintList;
                            // The isXXX routines return 
                            bool const circular = ctrl.isCircular().first && ctrl.isCircular().second;
                            bool const isotropic = ctrl.isIsotropic().second; // isotropic grow as opposed to a Manhattan metric
                                                            // n.b. Isotropic grows are significantly slower
                            bool const left =  ctrl.isLeft().first  && ctrl.isLeft().second;
                            bool const right = ctrl.isRight().first && ctrl.isRight().second;
                            bool const up =    ctrl.isUp().first    && ctrl.isUp().second;
                            bool const down =  ctrl.isDown().first  && ctrl.isDown().second;
                    
                            geom::Box2I const region = lhs.getRegion();
                            if (region != rhs.getRegion()) {
    
    194 28187378 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    194 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ boost::format("The two FootprintSets must have the same region").str()); } image::Image::Ptr idImage(new image::Image(region)); idImage->setXY0(region.getMinX(), region.getMinY()); *idImage = 0; FootprintList const& lhsFootprints = *lhs.getFootprints(); FootprintList const& rhsFootprints = *rhs.getFootprints(); int const nLhs = lhsFootprints.size(); int const nRhs = rhsFootprints.size(); /* * In general the lists of Footprints overlap, so we need to make sure that the IDs can be * uniquely recovered from the idImage. We do this by allocating a range of bits to the lhs IDs */ int const lhsIdNbit = nbit(nLhs); int const lhsIdMask = (lhsIdNbit == 0) ? 0x0 : (1 << lhsIdNbit) - 1; if (std::size_t(nRhs << lhsIdNbit) > std::numeric_limits::max() - 1) {
    214 28187378 - throw LSST_EXCEPT(lsst::pex::exceptions::OverflowErrorException,
    ? ---------
    214 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::OverflowError,
    (boost::format("%d + %d footprints need too many bits; change IdPixelT typedef") % nLhs % nRhs).str()); } /* * When we insert grown Footprints into the idImage we can potentially overwrite an entire Footprint, * losing any peaks that it might contain. We'll preserve the overwritten Ids in case we need to * get them back (n.b. Footprints that overlap, but both if which survive, will appear in this list) */ typedef std::map > OldIdMap; OldIdMap overwrittenIds; // here's a map from id -> overwritten IDs IdPixelT id = 1; // the ID inserted into the image for (FootprintList::const_iterator ptr = lhsFootprints.begin(), end = lhsFootprints.end(); ptr != end; ++ptr, ++id) { CONST_PTR(Footprint) foot = *ptr; if (rLhs > 0) { foot = circular ? growFootprint(*foot, rLhs, isotropic) : growFootprint(*foot, rLhs, left, right, up, down); } std::set overwritten; foot->insertIntoImage(*idImage, id, true, 0x0, &overwritten); if (!overwritten.empty()) { overwrittenIds.insert(overwrittenIds.end(), std::make_pair(id, overwritten)); } } assert (id <= std::size_t(1 << lhsIdNbit)); id = (1 << lhsIdNbit); for (FootprintList::const_iterator ptr = rhsFootprints.begin(), end = rhsFootprints.end(); ptr != end; ++ptr, id += (1 << lhsIdNbit)) { CONST_PTR(Footprint) foot = *ptr; if (rRhs > 0) { foot = circular ? growFootprint(*foot, rRhs, isotropic) : growFootprint(*foot, rRhs, left, right, up, down); } std::set overwritten; foot->insertIntoImage(*idImage, id, true, lhsIdMask, &overwritten); if (!overwritten.empty()) { overwrittenIds.insert(overwrittenIds.end(), std::make_pair(id, overwritten)); } } detection::FootprintSet fs(*idImage, detection::Threshold(1), 1, false); // detect all pixels in rhs + lhs /* * Now go through the new Footprints looking up and remembering their progenitor's IDs; we'll use * these IDs to merge the peaks in a moment * * We can't do this as we go through the idFinder as the IDs it returns are * (lhsId + 1) | ((rhsId + 1) << nbit) * and, depending on the geometry, values of lhsId and/or rhsId can appear multiple times * (e.g. if nbit is 2, idFinder IDs 0x5 and 0x6 both contain lhsId = 0) so we get duplicates * of peaks. This is not too bad, but it's a bit of a pain to make the lists unique again, * and we avoid this by this two-step process. */ FindIdsInFootprint > idFinder(*idImage); for (FootprintList::iterator ptr = fs.getFootprints()->begin(), end = fs.getFootprints()->end(); ptr != end; ++ptr) { PTR(Footprint) foot = *ptr; idFinder.apply(*foot); // find the (mangled) [lr]hsFootprint IDs that contribute to foot std::set lhsFootprintIndxs, rhsFootprintIndxs; // indexes into [lr]hsFootprints for (std::set::iterator idptr = idFinder.getIds().begin(), idend = idFinder.getIds().end(); idptr != idend; ++idptr) { unsigned int indx = *idptr; if ((indx & lhsIdMask) > 0) { boost::uint64_t i = (indx & lhsIdMask) - 1; lhsFootprintIndxs.insert(i); /* * Now allow for Footprints that vanished beneath this one */ OldIdMap::iterator mapPtr = overwrittenIds.find(indx); if (mapPtr != overwrittenIds.end()) { std::set &overwritten = mapPtr->second; for (std::set::iterator ptr = overwritten.begin(), end = overwritten.end(); ptr != end; ++ptr){ lhsFootprintIndxs.insert((*ptr & lhsIdMask) - 1); } } } indx >>= lhsIdNbit; if (indx > 0) { boost::uint64_t i = indx - 1; rhsFootprintIndxs.insert(i); /* * Now allow for Footprints that vanished beneath this one */ OldIdMap::iterator mapPtr = overwrittenIds.find(indx); if (mapPtr != overwrittenIds.end()) { std::set &overwritten = mapPtr->second; for (std::set::iterator ptr = overwritten.begin(), end = overwritten.end(); ptr != end; ++ptr) { rhsFootprintIndxs.insert(*ptr - 1); } } } } /* * We now have a complete set of Footprints that contributed to this one, so merge * all their Peaks into the new one */ detection::PeakCatalog &peaks = foot->getPeaks(); for (std::set::iterator ptr = lhsFootprintIndxs.begin(), end = lhsFootprintIndxs.end(); ptr != end; ++ptr) { boost::uint64_t i = *ptr; assert (i < lhsFootprints.size()); detection::PeakCatalog const& oldPeaks = lhsFootprints[i]->getPeaks(); int const nold = peaks.size(); peaks.insert(peaks.end(), oldPeaks.begin(), oldPeaks.end()); // We use getInternal() here to get the vector of shared_ptr that Catalog uses internally, // which causes the STL algorithm to copy pointers instead of PeakRecords (which is what // it'd try to do if we passed Catalog's own iterators). std::inplace_merge(peaks.getInternal().begin(), peaks.getInternal().begin() + nold, peaks.getInternal().end(), SortPeaks()); } for (std::set::iterator ptr = rhsFootprintIndxs.begin(), end = rhsFootprintIndxs.end(); ptr != end; ++ptr) { boost::uint64_t i = *ptr; assert (i < rhsFootprints.size()); detection::PeakCatalog const& oldPeaks = rhsFootprints[i]->getPeaks(); int const nold = peaks.size(); peaks.insert(peaks.end(), oldPeaks.begin(), oldPeaks.end()); // See note above on why we're using getInternal() here. std::inplace_merge(peaks.getInternal().begin(), peaks.getInternal().begin() + nold, peaks.getInternal().end(), SortPeaks()); } } return fs; } /* * run-length code for part of object */ class IdSpan { public: typedef boost::shared_ptr Ptr; explicit IdSpan(int id, int y, int x0, int x1, double good) : id(id), y(y), x0(x0), x1(x1), good(good) {} int id; /* ID for object */ int y; /* Row wherein IdSpan dwells */ int x0, x1; /* inclusive range of columns */ bool good; /* includes a value over the desired threshold? */ }; /* * comparison functor; sort by ID then row */ struct IdSpanCompar : public std::binary_function { bool operator()(IdSpan::Ptr const a, IdSpan::Ptr const b) { if (a->id < b->id) { return true; } else if (a->id > b->id) { return false; } else { return (a->y < b->y) ? true : false; } } }; /* * Follow a chain of aliases, returning the final resolved value. */ int resolve_alias(std::vector const &aliases, /* list of aliases */ int id) { /* alias to look up */ int resolved = id; /* resolved alias */ while (id != aliases[id]) { resolved = id = aliases[id]; } return(resolved); } /// \endcond } /************************************************************************************************************/ namespace { /* * Find all the Peaks within a Footprint */ template class FindPeaksInFootprint: public detection::FootprintFunctor { public: explicit FindPeaksInFootprint(ImageT const& image, ///< The image the source lives in bool polarity, ///< true if we're looking for -ve "peaks" detection::PeakCatalog &peaks ) : detection::FootprintFunctor(image), _polarity(polarity), _peaks(peaks) {} /// \brief method called for each pixel by apply() void operator()(typename ImageT::xy_locator loc, ///< locator pointing at the pixel int x, ///< column-position of pixel int y ///< row-position of pixel ) { typename ImageT::Pixel val = loc(0, 0); if (_polarity) { // look for +ve peaks if (loc(-1, 1) > val || loc( 0, 1) > val || loc( 1, 1) > val || loc(-1, 0) > val || loc( 1, 0) > val || loc(-1, -1) > val || loc( 0, -1) > val || loc( 1, -1) > val) { return; } } else { // look for -ve "peaks" (pits) if (loc(-1, 1) < val || loc( 0, 1) < val || loc( 1, 1) < val || loc(-1, 0) < val || loc( 1, 0) < val || loc(-1, -1) < val || loc( 0, -1) < val || loc( 1, -1) < val) { return; } } PTR(detection::PeakRecord) newPeak = _peaks.addNew(); newPeak->setIx(x); newPeak->setIy(y); newPeak->setFx(x); newPeak->setFy(y); newPeak->setPeakValue(val); } private: bool _polarity; detection::PeakCatalog &_peaks; }; /* * Find the maximum (or minimum, if polarity is false) pixel in a Footprint */ template class FindMaxInFootprint : public detection::FootprintFunctor { public: explicit FindMaxInFootprint(ImageT const& image, ///< The image the source lives in bool polarity ///< true if we're looking for -ve "peaks" ) : detection::FootprintFunctor(image), _polarity(polarity), _x(0), _y(0), _min( std::numeric_limits::max()), _max(-std::numeric_limits::max()) {} /// \brief Reset everything for a new Footprint void reset() { _x = _y = 0; _min = std::numeric_limits::max(); _max = -std::numeric_limits::max(); } virtual void reset(detection::Footprint const&) {} /// \brief method called for each pixel by apply() void operator()(typename ImageT::xy_locator loc, ///< locator pointing at the pixel int x, ///< column-position of pixel int y ///< row-position of pixel ) { typename ImageT::Pixel val = loc(0, 0); if (_polarity) { if (val > _max) { _max = val; _x = x; _y = y; } } else { if (val < _min) { _min = val; _x = x; _y = y; } } } // Add the Footprint's peak to the given PeakCatalog void addPeak(detection::PeakCatalog & peakCat) const { PTR(detection::PeakRecord) newPeak = peakCat.addNew(); newPeak->setIx(_x); newPeak->setIy(_y); newPeak->setFx(_x); newPeak->setFy(_y); newPeak->setPeakValue(_polarity ? _max : _min); } private: bool _polarity; int _x, _y; double _min, _max; }; template void findPeaks(PTR(detection::Footprint) foot, ImageT const& img, bool polarity, ThresholdT) { FindPeaksInFootprint peakFinder(img, polarity, foot->getPeaks()); peakFinder.apply(*foot, 1); // We use getInternal() here to get the vector of shared_ptr that Catalog uses internally, // which causes the STL algorithm to copy pointers instead of PeakRecords (which is what // it'd try to do if we passed Catalog's own iterators). std::stable_sort(foot->getPeaks().getInternal().begin(), foot->getPeaks().getInternal().end(), SortPeaks()); if (foot->getPeaks().empty()) { FindMaxInFootprint maxFinder(img, polarity); maxFinder.apply(*foot); maxFinder.addPeak(foot->getPeaks()); } } // No need to search for peaks when processing a Mask template void findPeaks(PTR(detection::Footprint), ImageT const&, bool, ThresholdBitmask_traits) { ; } } /************************************************************************************************************/ /* * Functions to determine if a pixel's in a Footprint */ template static inline bool inFootprint(ImagePixelT pixVal, IterT, bool polarity, double thresholdVal, ThresholdLevel_traits) { return (polarity ? pixVal : -pixVal) >= thresholdVal; } template static inline bool inFootprint(ImagePixelT pixVal, IterT var, bool polarity, double thresholdVal, ThresholdPixelLevel_traits) { return (polarity ? pixVal : -pixVal) >= thresholdVal*::sqrt(*var); } template static inline bool inFootprint(ImagePixelT pixVal, IterT, bool, double thresholdVal, ThresholdBitmask_traits) { return (pixVal & static_cast(thresholdVal)); } /* * Advance the x_iterator to the variance image, when relevant (it may be NULL otherwise) */ template static inline IterT advancePtr(IterT varPtr, Threshold_traits) { return varPtr; } template static inline IterT advancePtr(IterT varPtr, ThresholdPixelLevel_traits) { return varPtr + 1; } /* * Here's the working routine for the FootprintSet constructors; see documentation * of the constructors themselves */ template static void findFootprints( typename detection::FootprintSet::FootprintList *_footprints, // Footprints geom::Box2I const& _region, // BBox of pixels that are being searched image::ImageBase const &img, // Image to search for objects image::Image const *var, // img's variance double const footprintThreshold, // threshold value for footprint double const includeThresholdMultiplier, // threshold (relative to footprintThreshold) for inclusion bool const polarity, // if false, search _below_ thresholdVal int const npixMin, // minimum number of pixels in an object bool const setPeaks // should I set the Peaks list? ) { int id; /* object ID */ int in_span; /* object ID of current IdSpan */ int nobj = 0; /* number of objects found */ int x0 = 0; /* unpacked from a IdSpan */ typedef typename image::Image ImageT; double includeThreshold = footprintThreshold * includeThresholdMultiplier; // Threshold for inclusion int const row0 = img.getY0(); int const col0 = img.getX0(); int const height = img.getHeight(); int const width = img.getWidth(); /* * Storage for arrays that identify objects by ID. We want to be able to * refer to idp[-1] and idp[width], hence the (width + 2) */ std::vector id1(width + 2); std::fill(id1.begin(), id1.end(), 0); std::vector id2(width + 2); std::fill(id2.begin(), id2.end(), 0); std::vector::iterator idc = id1.begin() + 1; // object IDs in current/ std::vector::iterator idp = id2.begin() + 1; // previous row std::vector aliases; // aliases for initially disjoint parts of Footprints aliases.reserve(1 + height/20); // initial size of aliases std::vector spans; // y:x0,x1 for objects spans.reserve(aliases.capacity()); // initial size of spans aliases.push_back(0); // 0 --> 0 /* * Go through image identifying objects */ typedef typename image::Image::x_iterator x_iterator; typedef typename image::Image::x_iterator x_var_iterator; in_span = 0; // not in a span for (int y = 0; y != height; ++y) { if (idc == id1.begin() + 1) { idc = id2.begin() + 1; idp = id1.begin() + 1; } else { idc = id1.begin() + 1; idp = id2.begin() + 1; } std::fill_n(idc - 1, width + 2, 0); in_span = 0; /* not in a span */ bool good = (includeThresholdMultiplier == 1.0); /* Span exceeds the threshold? */ x_iterator pixPtr = img.row_begin(y); x_var_iterator varPtr = (var == NULL) ? NULL : var->row_begin(y); for (int x = 0; x < width; ++x, ++pixPtr, varPtr = advancePtr(varPtr, ThresholdTraitT())) { ImagePixelT const pixVal = *pixPtr; if (isBadPixel(pixVal) || !inFootprint(pixVal, varPtr, polarity, footprintThreshold, ThresholdTraitT())) { if (in_span) { IdSpan::Ptr sp(new IdSpan(in_span, y, x0, x - 1, good)); spans.push_back(sp); in_span = 0; good = false; } } else { /* a pixel to fix */ if (idc[x - 1] != 0) { id = idc[x - 1]; } else if (idp[x - 1] != 0) { id = idp[x - 1]; } else if (idp[x] != 0) { id = idp[x]; } else if (idp[x + 1] != 0) { id = idp[x + 1]; } else { id = ++nobj; aliases.push_back(id); } idc[x] = id; if (!in_span) { x0 = x; in_span = id; } /* * Do we need to merge ID numbers? If so, make suitable entries in aliases[] */ if (idp[x + 1] != 0 && idp[x + 1] != id) { aliases[resolve_alias(aliases, idp[x + 1])] = resolve_alias(aliases, id); idc[x] = id = idp[x + 1]; } if (!good && inFootprint(pixVal, varPtr, polarity, includeThreshold, ThresholdTraitT())) { good = true; } } } if (in_span) { IdSpan::Ptr sp(new IdSpan(in_span, y, x0, width - 1, good)); spans.push_back(sp); } } /* * Resolve aliases; first alias chains, then the IDs in the spans */ for (unsigned int i = 0; i < spans.size(); i++) { spans[i]->id = resolve_alias(aliases, spans[i]->id); } /* * Sort spans by ID, so we can sweep through them once */ if (spans.size() > 0) { std::sort(spans.begin(), spans.end(), IdSpanCompar()); } /* * Build Footprints from spans */ unsigned int i0; // initial value of i if (spans.size() > 0) { id = spans[0]->id; i0 = 0; for (unsigned int i = 0; i <= spans.size(); i++) { // <= size to catch the last object if (i == spans.size() || spans[i]->id != id) { PTR(detection::Footprint) fp(new detection::Footprint(i - i0, _region)); bool good = false; // Span includes pixel sufficient to include footprint in set? for (; i0 < i; i0++) { good |= spans[i0]->good; fp->addSpan(spans[i0]->y + row0, spans[i0]->x0 + col0, spans[i0]->x1 + col0); } if (good && !(fp->getNpix() < npixMin)) { _footprints->push_back(fp); } } if (i < spans.size()) { id = spans[i]->id; } } } /* * Find all peaks within those Footprints */ if (setPeaks) { typedef detection::FootprintSet::FootprintList::iterator fiterator; for (fiterator ptr = _footprints->begin(), end = _footprints->end(); ptr != end; ++ptr) { findPeaks(*ptr, img, polarity, ThresholdTraitT()); } } } /************************************************************************************************************/ /* * \brief Find a FootprintSet given an Image and a threshold */ template detection::FootprintSet::FootprintSet( image::Image const &img, //!< Image to search for objects Threshold const &threshold, //!< threshold to find objects int const npixMin, //!< minimum number of pixels in an object bool const setPeaks //!< should I set the Peaks list? ) : lsst::daf::base::Citizen(typeid(this)), _footprints(new FootprintList()),
    756 a8f86353 - _region(img.getBBox(image::PARENT))
    ? -------------
    756 93994d54 + _region(img.getBBox())
    { typedef float VariancePixelT; findFootprints( _footprints.get(), _region, img, NULL, threshold.getValue(img), threshold.getIncludeMultiplier(), threshold.getPolarity(), npixMin, setPeaks ); } // NOTE: not a template to appease swig (see note by instantiations at bottom) /* * \brief Find a FootprintSet given a Mask and a threshold */ template detection::FootprintSet::FootprintSet( image::Mask const &msk, //!< Image to search for objects Threshold const &threshold, //!< threshold to find objects int const npixMin //!< minimum number of pixels in an object ) : lsst::daf::base::Citizen(typeid(this)), _footprints(new FootprintList()),
    783 5ba4f880 - _region(msk.getBBox(image::PARENT))
    ? -------------
    783 93994d54 + _region(msk.getBBox())
    { switch (threshold.getType()) { case Threshold::BITMASK: findFootprints( _footprints.get(), _region, msk, NULL, threshold.getValue(), threshold.getIncludeMultiplier(), threshold.getPolarity(), npixMin, false); break; case Threshold::VALUE: findFootprints( _footprints.get(), _region, msk, NULL, threshold.getValue(), threshold.getIncludeMultiplier(), threshold.getPolarity(), npixMin, false); break; default:
    799 5ba4f880 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    799 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "You must specify a numerical threshold value with a Mask"); } } /** * \brief Find a FootprintSet given a MaskedImage and a threshold * * Go through an image, finding sets of connected pixels above threshold * and assembling them into Footprint%s; the resulting set of objects * is returned as an \c array * * If threshold.getPolarity() is true, pixels above the Threshold are * assembled into Footprints; if it's false, then pixels \e below Threshold * are processed (Threshold will probably have to be below the background level * for this to make sense, e.g. for difference imaging) */ template detection::FootprintSet::FootprintSet( const image::MaskedImage &maskedImg, //!< MaskedImage to search for objects Threshold const &threshold, //!< threshold for footprints (controls size) std::string const &planeName, //!< mask plane to set (if != "") int const npixMin, //!< minimum number of pixels in an object bool const setPeaks //!< should I set the Peaks list? ) : lsst::daf::base::Citizen(typeid(this)), _footprints(new FootprintList()), _region( geom::Point2I(maskedImg.getX0(), maskedImg.getY0()), geom::Extent2I(maskedImg.getWidth(), maskedImg.getHeight()) ) { typedef typename image::MaskedImage::Variance::Pixel VariancePixelT; // Find the Footprints switch (threshold.getType()) { case Threshold::PIXEL_STDEV: findFootprints( _footprints.get(), _region, *maskedImg.getImage(), maskedImg.getVariance().get(), threshold.getValue(maskedImg), threshold.getIncludeMultiplier(), threshold.getPolarity(), npixMin, setPeaks ); break; default: findFootprints( _footprints.get(), _region, *maskedImg.getImage(), maskedImg.getVariance().get(), threshold.getValue(maskedImg), threshold.getIncludeMultiplier(), threshold.getPolarity(), npixMin, setPeaks ); break; } // Set Mask if requested if (planeName == "") { return; } // // Define the maskPlane // const typename image::Mask::Ptr mask = maskedImg.getMask(); mask->addMaskPlane(planeName); MaskPixelT const bitPlane = mask->getPlaneBitMask(planeName); // // Set the bits where objects are detected // typedef image::Mask MaskT; class MaskFootprint : public detection::FootprintFunctor { public: MaskFootprint(MaskT const& mimage, MaskPixelT bit) : detection::FootprintFunctor(mimage), _bit(bit) {} void operator()(typename MaskT::xy_locator loc, int, int) { *loc |= _bit; } private: MaskPixelT _bit; }; MaskFootprint maskit(*maskedImg.getMask(), bitPlane); for (FootprintList::const_iterator fiter = _footprints->begin(); fiter != _footprints->end(); ++fiter ) { Footprint::Ptr const foot = *fiter; maskit.apply(*foot); } } /************************************************************************************************************/ namespace { /// Don't let doxygen see this block \cond /* * A data structure to hold the starting point for a search for pixels above threshold, * used by pmFindFootprintAtPoint * * We don't want to find this span again --- it's already part of the footprint --- * so we set appropriate mask bits */ // // An enum for what we should do with a Startspan // enum DIRECTION {DOWN = 0, // scan down from this span UP, // scan up from this span RESTART, // restart scanning from this span DONE // this span is processed }; // // A Class that remembers how to [re-]start scanning the image for pixels // template class Startspan { public: typedef std::vector > Ptr; Startspan(detection::Span const *span, image::Mask *mask, DIRECTION const dir); ~Startspan() { delete _span; } bool getSpan() { return _span; } bool Stop() { return _stop; } DIRECTION getDirection() { return _direction; } static int detectedPlane; // The MaskPlane to use for detected pixels static int stopPlane; // The MaskPlane to use for pixels that signal us to stop searching private: detection::Span::Ptr const _span; // The initial Span DIRECTION _direction; // How to continue searching for further pixels bool _stop; // should we stop searching? }; template Startspan::Startspan(detection::Span const *span, // The span in question image::Mask *mask, // Pixels that we've already detected DIRECTION const dir // Should we continue searching towards the top of the image? ) : _span(span), _direction(dir), _stop(false) { if (mask != NULL) { // remember that we've detected these pixels mask->setMaskPlaneValues(detectedPlane, span->getX0(), span->getX1(), span->getY()); int const y = span->getY() - mask->getY0(); for (int x = span->getX0() - mask->getX0(); x <= span->getX1() - mask->getX0(); x++) { if (mask(x, y, stopPlane)) { _stop = true; break; } } } } template class StartspanSet { public: StartspanSet(image::MaskedImage& image) : _image(image->getImage()), _mask(image->getMask()) {} ~StartspanSet() {} bool add(detection::Span *span, DIRECTION const dir, bool addToMask = true); bool process(detection::Footprint *fp, // the footprint that we're building detection::Threshold const &threshold, // Threshold double const param = -1); // parameter that Threshold may need private: image::Image const *_image; // the Image we're searching image::Mask *_mask; // the mask that tells us where we've got to std::vector::Ptr> _spans; // list of Startspans }; // // Add a new Startspan to a StartspansSet. Iff we see a stop bit, return true // template bool StartspanSet::add(detection::Span *span, // the span in question DIRECTION const dir, // the desired direction to search bool addToMask) { // should I add the Span to the mask? if (dir == RESTART) { if (add(span, UP) || add(span, DOWN, false)) { return true; } } else { typename Startspan::Ptr sspan(new Startspan(span, dir)); if (sspan->stop()) { // we detected a stop bit return true; } else { _spans.push_back(sspan); } } return false; } /************************************************************************************************/ /* * Search the image for pixels above threshold, starting at a single Startspan. * We search the array looking for one to process; it'd be better to move the * ones that we're done with to the end, but it probably isn't worth it for * the anticipated uses of this routine. * * This is the guts of pmFindFootprintAtPoint */ template bool StartspanSet::process( detection::Footprint *fp, // the footprint that we're building detection::Threshold const &threshold, // Threshold double const param // parameter that Threshold may need ) { int const row0 = _image->getY0(); int const col0 = _image->getOffsetCols(); int const height = _image->getHeight(); /**********************************************************************************************/
    1025 f8edfe90 - typedef typename std::vector::Ptr> StartspanListT;
    1026 f8edfe90 - typedef typename std::vector::Ptr>::iterator StartspanListIterT;
    1027 f8edfe90 -
    Startspan *sspan = NULL;
    1029 9fdf87da - for (StartspanListIterT iter = _spans.begin(); iter != _spans.end(); iter++) {
    ? ^ ^^^^^^^^^^^^^^^^
    1026 4be175e8 + for (auto iter = _spans.begin(); iter != _spans.end(); iter++) {
    ? ^^ ^ *sspan = *iter; if (sspan->getDirection() != DONE) { break; } if (sspan->Stop()) { break; } } if (sspan == NULL || sspan->getDirection() == DONE) { // no more Startspans to process return false; } if (sspan->Stop()) { // they don't want any more spans processed return false; } /* * Work */ DIRECTION const dir = sspan->getDirection(); /* * Set initial span to the startspan */ int x0 = sspan->getSpan()->getX0() - col0; /* * Go through image identifying objects */ int nx0 = -1; // new value of x0 int const di = (dir == UP) ? 1 : -1; // how much i changes to get to the next row bool stop = false; // should I stop searching for spans? typedef typename image::Image::pixel_accessor pixAccessT; double const thresholdVal = threshold.getValue(param); bool const polarity = threshold.getPolarity(); for (int i = sspan->span->y -row0 + di; i < height && i >= 0; i += di) { pixAccessT imgRow = _image->origin().advance(0, i); // row pointer //maskPixAccessT maskRow = _mask->origin.advance(0, i); // masks's row pointer // // Search left from the pixel diagonally to the left of (i - di, x0). If there's // a connected span there it may need to grow up and/or down, so push it onto // the stack for later consideration // nx0 = -1; for (int j = x0 - 1; j >= -1; j--) { ImagePixelT pixVal = (j < 0) ? thresholdVal - 100 : (polarity ? imgRow[j] : -imgRow[j]); if (_mask(j, i, Startspan::detectedPlane) || pixVal < threshold) { if (j < x0 - 1) { // we found some pixels above threshold nx0 = j + 1; } break; } } #if 0 if (nx0 < 0) { // no span to the left nx1 = x0 - 1; // we're going to resume searching at nx1 + 1 } else { // // Search right in leftmost span // //nx1 = 0; // make gcc happy for (int j = nx0 + 1; j <= width; j++) { ImagePixelT pixVal = (j >= width) ? threshold - 100 : (polarity ? (F32 ? imgRowF32[j] : imgRowS32[j]) : (F32 ? -imgRowF32[j] : -imgRowS32[j])); if ((maskRow[j] & DETECTED) || pixVal < threshold) { nx1 = j - 1; break; } } pmSpan const *sp = pmFootprintAddSpan(fp, i + row0, nx0 + col0, nx1 + col0); if (add_startspan(startspans, sp, mask, RESTART)) { stop = true; break; } } // // Now look for spans connected to the old span. The first of these we'll // simply process, but others will have to be deferred for later consideration. // // In fact, if the span overhangs to the right we'll have to defer the overhang // until later too, as it too can grow in both directions // // Note that column width exists virtually, and always ends the last span; this // is why we claim below that sx1 is always set // bool first = false; // is this the first new span detected? for (int j = nx1 + 1; j <= x1 + 1; j++) { ImagePixelT pixVal = (j >= width) ? threshold - 100 : (polarity ? (F32 ? imgRowF32[j] : imgRowS32[j]) : (F32 ? -imgRowF32[j] : -imgRowS32[j])); if (!(maskRow[j] & DETECTED) && pixVal >= threshold) { int sx0 = j++; // span that we're working on is sx0:sx1 int sx1 = -1; // We know that if we got here, we'll also set sx1 for (; j <= width; j++) { ImagePixelT pixVal = (j >= width) ? threshold - 100 : (polarity ? (F32 ? imgRowF32[j] : imgRowS32[j]) : (F32 ? -imgRowF32[j] : -imgRowS32[j])); if ((maskRow[j] & DETECTED) || pixVal < threshold) { // end of span sx1 = j; break; } } assert (sx1 >= 0); pmSpan const *sp; if (first) { if (sx1 <= x1) { sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); if (add_startspan(startspans, sp, mask, DONE)) { stop = true; break; } } else { // overhangs to right sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, x1 + col0); if (add_startspan(startspans, sp, mask, DONE)) { stop = true; break; } sp = pmFootprintAddSpan(fp, i + row0, x1 + 1 + col0, sx1 + col0 - 1); if (add_startspan(startspans, sp, mask, RESTART)) { stop = true; break; } } first = false; } else { sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); if (add_startspan(startspans, sp, mask, RESTART)) { stop = true; break; } } } } if (stop || first == false) { // we're done break; } x0 = nx0; x1 = nx1; #endif } /* * Cleanup */ sspan->_direction = DONE; return stop ? false : true; } /// \endcond } #if 0 /* * Go through an image, starting at (row, col) and assembling all the pixels * that are connected to that point (in a chess kings-move sort of way) into * a pmFootprint. * * This is much slower than pmFindFootprints if you want to find lots of * footprints, but if you only want a small region about a given point it * can be much faster * * N.b. The returned pmFootprint is not in "normal form"; that is the pmSpans * are not sorted by increasing y, x0, x1. If this matters to you, call * pmFootprintNormalize() */ pmFootprint * pmFindFootprintAtPoint(psImage const *img, // image to search Threshold const &threshold, // Threshold psArray const *peaks, // array of peaks; finding one terminates search for footprint int row, int col) { // starting position (in img's parent's coordinate system) assert(img != NULL); bool F32 = false; // is this an F32 image? if (img->type.type == PS_TYPE_F32) { F32 = true; } else if (img->type.type == PS_TYPE_S32) { F32 = false; } else { // N.b. You can't trivially add more cases here; F32 is just a bool psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type); return NULL; } psF32 *imgRowF32 = NULL; // row pointer if F32 psS32 *imgRowS32 = NULL; // " " " " !F32 int const row0 = img->row0; int const col0 = img->col0; int const height = img->getHeight(); int const width = img->getWidth(); /* * Is point in image, and above threshold? */ row -= row0; col -= col0; if (row < 0 || row >= height || col < 0 || col >= width) { psError(PS_ERR_BAD_PARAMETER_VALUE, true, "row/col == (%d, %d) are out of bounds [%d--%d, %d--%d]", row + row0, col + col0, row0, row0 + height - 1, col0, col0 + width - 1); return NULL; } ImagePixelT pixVal = F32 ? img->data.F32[row][col] : img->data.S32[row][col]; if (pixVal < threshold) { return pmFootprintAlloc(0, img); } pmFootprint *fp = pmFootprintAlloc(1 + img->getHeight()/10, img); /* * We need a mask for two purposes; to indicate which pixels are already detected, * and to store the "stop" pixels --- those that, once reached, should stop us * looking for the rest of the pmFootprint. These are generally set from peaks. */ psImage *mask = psImageAlloc(width, height, PS_TYPE_MASK); P_PSIMAGE_SET_ROW0(mask, row0); P_PSIMAGE_SET_COL0(mask, col0); psImageInit(mask, INITIAL); // // Set stop bits from peaks list // assert (peaks == NULL || peaks->n == 0 || pmIsPeak(peaks->data[0])); if (peaks != NULL) { for (int i = 0; i < peaks->n; i++) { pmPeak *peak = peaks->data[i]; mask->data.PS_TYPE_MASK_DATA[peak->y - mask->row0][peak->x - mask->col0] |= STOP; } } /* * Find starting span passing through (row, col) */ psArray *startspans = psArrayAllocEmpty(1); // spans where we have to restart the search imgRowF32 = img->data.F32[row]; // only one of imgRowS32 = img->data.S32[row]; // these is valid! psMaskType *maskRow = mask->data.PS_TYPE_MASK_DATA[row]; { int i; for (i = col; i >= 0; i--) { pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; if ((maskRow[i] & DETECTED) || pixVal < threshold) { break; } } int i0 = i; for (i = col; i < width; i++) { pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; if ((maskRow[i] & DETECTED) || pixVal < threshold) { break; } } int i1 = i; pmSpan const *sp = pmFootprintAddSpan(fp, row + row0, i0 + col0 + 1, i1 + col0 - 1); (void)add_startspan(startspans, sp, mask, RESTART); } /* * Now workout from those Startspans, searching for pixels above threshold */ while (do_startspan(fp, img, mask, threshold, startspans)) continue; /* * Cleanup */ psFree(mask); psFree(startspans); // restores the image pixel return fp; // pmFootprint really } #endif /************************************************************************************************************/ /** * Construct an empty FootprintSet given a region that its footprints would have lived in */ detection::FootprintSet::FootprintSet(geom::Box2I region ///< the desired region ) : lsst::daf::base::Citizen(typeid(this)), _footprints(PTR(FootprintList)(new FootprintList)), _region(region) { } /** * Copy constructor */ detection::FootprintSet::FootprintSet( FootprintSet const &rhs //!< the input FootprintSet ) : lsst::daf::base::Citizen(typeid(this)), _footprints(new FootprintList), _region(rhs._region) { _footprints->reserve(rhs._footprints->size()); for (FootprintSet::FootprintList::const_iterator ptr = rhs._footprints->begin(), end = rhs._footprints->end(); ptr != end; ++ptr) { _footprints->push_back(PTR(Footprint)(new Footprint(**ptr))); } } /// Assignment operator. detection::FootprintSet & detection::FootprintSet::operator=(FootprintSet const& rhs) { FootprintSet tmp(rhs); swap(tmp); // See Meyers, Effective C++, Item 11 return *this; } /************************************************************************************************************/ /** * Merge a FootprintSet into *this */ void detection::FootprintSet::merge( detection::FootprintSet const& rhs, ///< the Footprints to merge int tGrow, ///< No. of pixels to grow this Footprints int rGrow, ///< No. of pixels to grow rhs Footprints bool isotropic ///< Use (expensive) isotropic grow ) { detection::FootprintControl const ctrl(true, isotropic); detection::FootprintSet fs = mergeFootprintSets(*this, tGrow, rhs, rGrow, ctrl); swap(fs); // Swap the new FootprintSet into place } /// Set the corners of the FootprintSet's MaskedImage to region /// /// N.b. updates all the Footprints' regions too // void detection::FootprintSet::setRegion( geom::Box2I const& region ///< desired region ) { _region = region; for (FootprintSet::FootprintList::iterator ptr = _footprints->begin(), end = _footprints->end(); ptr != end; ++ptr ) { (*ptr)->setRegion(region); } } /************************************************************************************************************/ /** * Grow all the Footprints in the input FootprintSet, returning a new FootprintSet * * The output FootprintSet may contain fewer Footprints, as some may well have been merged */ detection::FootprintSet::FootprintSet( FootprintSet const &rhs, //!< the input FootprintSet int r, //!< Grow Footprints by r pixels bool isotropic //!< Grow isotropically (as opposed to a Manhattan metric) //!< @note Isotropic grows are significantly slower ) : lsst::daf::base::Citizen(typeid(this)), _footprints(new FootprintList), _region(rhs._region) { if (r == 0) { FootprintSet fs = rhs; swap(fs); // Swap the new FootprintSet into place return; } else if (r < 0) {
    1386 4b1be60a - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    1383 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("I cannot grow by negative numbers: %d") % r).str()); } detection::FootprintControl const ctrl(true, isotropic); detection::FootprintSet fs = mergeFootprintSets(FootprintSet(rhs.getRegion()), 0, rhs, r, ctrl); swap(fs); // Swap the new FootprintSet into place } /************************************************************************************************************/ detection::FootprintSet::FootprintSet(detection::FootprintSet const& rhs, int ngrow, detection::FootprintControl const& ctrl) : lsst::daf::base::Citizen(typeid(this)), _footprints(new FootprintList), _region(rhs._region) { if (ngrow == 0) { FootprintSet fs = rhs; swap(fs); // Swap the new FootprintSet into place return; } else if (ngrow < 0) {
    1407 868f131e - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    1404 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("I cannot grow by negative numbers: %d") % ngrow)); } detection::FootprintSet fs = mergeFootprintSets(FootprintSet(rhs.getRegion()), 0, rhs, ngrow, ctrl); swap(fs); // Swap the new FootprintSet into place } /************************************************************************************************************/ /** * Return the FootprintSet corresponding to the merge of two input FootprintSets * * \todo Implement this. There's RHL Pan-STARRS code to do it, but it isn't yet converted to LSST C++ */ detection::FootprintSet::FootprintSet( FootprintSet const& fs1, FootprintSet const& fs2, bool const ) : lsst::daf::base::Citizen(typeid(this)), _footprints(new FootprintList()), _region(fs1._region) { _region.include(fs2._region);
    1431 4afba64d - throw LSST_EXCEPT(lsst::pex::exceptions::LogicErrorException, "NOT IMPLEMENTED");
    ? ---------
    1428 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LogicError, "NOT IMPLEMENTED");
    } /************************************************************************************************************/ /** * Return an Image with pixels set to the Footprint%s in the FootprintSet * * \returns an image::Image::Ptr */ PTR(image::Image) detection::FootprintSet::insertIntoImage( bool const relativeIDs ///< Use IDs starting at 0 (rather than the ones in the Footprint%s) ) const { PTR(image::Image) im( new image::Image(_region) ); *im = 0; detection::FootprintIdPixel id = 0; for (FootprintList::const_iterator fiter = _footprints->begin(); fiter != _footprints->end(); fiter++ ) { Footprint::Ptr const foot = *fiter; if (relativeIDs) { id++; } else { id = foot->getId(); } foot->insertIntoImage(*im.get(), id); } return im; } /************************************************************************************************************/ /** * Convert all the Footprints in the FootprintSet to be HeavyFootprint%s */ template void detection::FootprintSet::makeHeavy( image::MaskedImage const& mimg, ///< the image providing pixel values HeavyFootprintCtrl const *ctrl ///< Control how we manipulate HeavyFootprints ) { HeavyFootprintCtrl ctrl_s = HeavyFootprintCtrl(); if (!ctrl) { ctrl = &ctrl_s; } for (FootprintList::iterator ptr = _footprints->begin(), end = _footprints->end(); ptr != end; ++ptr) { ptr->reset(new detection::HeavyFootprint(**ptr, mimg, ctrl)); } } void detection::FootprintSet::makeSources( lsst::afw::table::SourceCatalog & cat ) const { for (FootprintList::const_iterator i = _footprints->begin(); i != _footprints->end(); ++i) { PTR(afw::table::SourceRecord) r = cat.addNew(); r->setFootprint(*i); } } /************************************************************************************************************/ // // Explicit instantiations // #ifndef DOXYGEN #define INSTANTIATE(PIXEL) \ template detection::FootprintSet::FootprintSet( \ image::Image const &, Threshold const &, int const, bool const); \ template detection::FootprintSet::FootprintSet( \ image::MaskedImage const &, Threshold const &, \ std::string const &, int const, bool const);\ template void detection::FootprintSet::makeHeavy(image::MaskedImage const &, \ HeavyFootprintCtrl const *) template detection::FootprintSet::FootprintSet(image::Mask const &, Threshold const &, int const); template void detection::FootprintSet::setMask(image::Mask *, std::string const &); template void detection::FootprintSet::setMask(PTR(image::Mask), std::string const &); INSTANTIATE(boost::uint16_t); INSTANTIATE(int); INSTANTIATE(float); INSTANTIATE(double); #endif // !DOXYGEN

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    28187378

    commit 28187378ccba6e7311aa2d7ad5759293d8bc9e07
    Author: rhl 
    Date:   Mon Oct 24 17:28:15 2011 +0000
    
        Fix bugs shown up by clang++
    

    4afba64d

    commit 4afba64d7fe74d4c1ed99f21d17cbb2008c4b024
    Author: Jim Bosch 
    Date:   Mon Jan 30 19:32:36 2012 -0500
    
        removed template parameters from FootprintSet class (now constructors and a few member functions are templated); removed now-pointless(?) makeFootprintSet functions
    

    5ba4f880

    commit 5ba4f880058b4c6103dc292fa248cd4ab6dc6558
    Author: rhl 
    Date:   Sat Oct 22 22:03:52 2011 +0000
    
        Reverted r24389 (Paul) and r24632 (Steve).  Fixed #1783, although the implementation is poor [sorting twice to get unique Peak lists as Footprints can overlap more than one other Footprint) I want to get it in before more sturm and drang
    

    a8f86353

    commit a8f86353b4d794d8e2accd0ce6950e72a06c3f66
    Merge: a128aac 246b6dd
    Author: dubcovsky 
    Date:   Thu Mar 31 20:50:37 2011 +0000
    
        #1556 trunk merged to ticket branch
    

    4b1be60a

    commit 4b1be60a1d27c771b92829b02a37d9db164482f8
    Author: rhl 
    Date:   Sun Mar 1 16:00:32 2009 +0000
    
        Implement DetectionSet copy constructor that grows the Footprints; adjust growFootprint signature to make this possible; #0
    

    9fdf87da

    commit 9fdf87da399be2fb3e9e4bc41984a2b5c6c2f838
    Author: jarvis 
    Date:   Thu Jun 24 05:21:13 2010 +0000
    
        Made a few changes to Footprint and FootprintSet to get rid of
        bare pointers which are not exception safe and were causing memory leaks.
        
        In Footprint:
        Changed _spans and _peaks to std::vector, rather than std::vector&
        (which were both initialized as *new std::vector<...> and then the address
        of the reference was deleted in the destructor).  These didn't require any
        such functionality, so leave them as normal vector's and let std::vector
        do the memory management itself.
        
        By the way, it doesn't seem like _peaks is being used.  The only use is
        in a line that is commented out.  Should this member be removed?
        
        In FootprintSet:
        Changed _footprints and _region to be boost::shared_ptr<> rather than
        a reference (which again was initialized with *new, and only _footprints
        was being deleted).  I think these could probably also switch to being
        stored by value, but that would technically change some of the functionality
        of the class -- specifically shallow copies.  I believe storing these
        values as shared_ptr's keeps the shallow copy behavior, but now without
        the memory leaks.  (It is also more exception safe now.)  However, it
        should be considered whether this is the desired behavior for this class
        or if shallow copies were an oversight.
        
        
        Furthermore, I checked that no other pieces of code in afw contain the
        string "*new ", so I believe there aren't any other similar
        memory leaks lurking in other parts of afw at least.  I didn't grep
        through all the other modules, though.
    

    868f131e

    commit 868f131edf514c22c8eb9172a5bda322f7f27b66
    Author: Robert Lupton the Good 
    Date:   Fri Jun 1 16:14:51 2012 -0500
    
        Implemented left/right grows
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    4be175e8

    commit 4be175e82e7ffdea41f40e53ca6065c2bf831300
    Author: Jim Bosch 
    Date:   Wed Jan 21 18:23:26 2015 -0500
    
        Remove unused local typedefs to address gcc warnings
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    tests/color.py

    Diff:

    1 14d7dac1 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Calib, Color, and Filter Run with: color.py or python >>> import color; color.run() """
    36 a6d8990e - import math, os, sys
    37 83333880 + import math
    38 14d7dac1 + import unittest
    39 83333880 +
    import numpy
    38 14d7dac1 - import unittest
    41 83333880 +
    import lsst.utils.tests as tests import lsst.daf.base as dafBase import lsst.pex.logging as logging
    42 e27b0f1a - import lsst.pex.config as pexConfig
    import lsst.pex.exceptions as pexExcept
    46 83333880 + import lsst.afw.geom as afwGeom
    import lsst.afw.image as afwImage import lsst.afw.image.utils as imageUtils
    49 780e3962 + from lsst.afw.cameraGeom.testUtils import DetectorWrapper
    46 14d7dac1 - import lsst.afw.math as afwMath
    47 14d7dac1 - import lsst.afw.detection as afwDetect
    48 14d7dac1 - import lsst.afw.detection.utils as afwDetectUtils
    49 14d7dac1 - import lsst.afw.display.ds9 as ds9
    try: type(verbose) except NameError: verbose = 0 logging.Debug("afwDetect.Footprint", verbose) try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class CalibTestCase(unittest.TestCase): """A test case for Calib""" def setUp(self): self.calib = afwImage.Calib()
    68 83333880 + self.detector = DetectorWrapper().detector
    def tearDown(self): del self.calib
    72 83333880 + del self.detector
    def testTime(self): """Test the exposure time information""" isoDate = "1995-01-26T07:32:00.000000000Z" self.calib.setMidTime(dafBase.DateTime(isoDate)) self.assertEqual(isoDate, self.calib.getMidTime().toString()) self.assertAlmostEqual(self.calib.getMidTime().get(), 49743.3142245) dt = 123.4 self.calib.setExptime(dt) self.assertEqual(self.calib.getExptime(), dt) def testDetectorTime(self): """Test that we can ask a calib for the MidTime at a point in a detector (ticket #1337)"""
    86 0e95e6dd -
    87 0e95e6dd - import lsst.afw.geom as afwGeom
    88 0e95e6dd - import lsst.afw.cameraGeom as cameraGeom
    89 0e95e6dd -
    90 0e95e6dd - det = cameraGeom.Detector(cameraGeom.Id(1))
    91 0e95e6dd -
    p = afwGeom.PointI(3, 4)
    93 78fe64c4 - self.calib.getMidTime(det, p)
    89 83333880 + self.calib.getMidTime(self.detector, p)
    ? +++++ +++++ def testPhotom(self): """Test the zero-point information""" flux, fluxErr = 1000.0, 10.0 flux0, flux0Err = 1e12, 1e10 self.calib.setFluxMag0(flux0) self.assertEqual(flux0, self.calib.getFluxMag0()[0]) self.assertEqual(0.0, self.calib.getFluxMag0()[1]) self.assertEqual(22.5, self.calib.getMagnitude(flux)) # Error just in flux self.assertAlmostEqual(self.calib.getMagnitude(flux, fluxErr)[1], 2.5/math.log(10)*fluxErr/flux) # Error just in flux0 self.calib.setFluxMag0(flux0, flux0Err) self.assertEqual(flux0Err, self.calib.getFluxMag0()[1]) self.assertAlmostEqual(self.calib.getMagnitude(flux, 0)[1], 2.5/math.log(10)*flux0Err/flux0) self.assertAlmostEqual(flux0, self.calib.getFlux(0)) self.assertAlmostEqual(flux, self.calib.getFlux(22.5)) # I don't know how to test round-trip if fluxMag0 is significant compared to fluxErr self.calib.setFluxMag0(flux0, flux0 / 1e6) for fluxErr in (flux / 1e2, flux / 1e4): mag, magErr = self.calib.getMagnitude(flux, fluxErr) self.assertAlmostEqual(flux, self.calib.getFlux(mag, magErr)[0]) self.assertTrue(abs(fluxErr - self.calib.getFlux(mag, magErr)[1]) < 1.0e-4) # Test context manager; shouldn't raise an exception within the block, should outside with imageUtils.CalibNoThrow(): self.assert_(numpy.isnan(self.calib.getMagnitude(-50.0)))
    125 2d86164e - tests.assertRaisesLsstCpp(self, pexExcept.DomainErrorException, self.calib.getMagnitude, -50.0)
    ? ^ ^^^ ------- ------ ---------
    121 6fc1c3d1 + self.assertRaises(pexExcept.DomainError, self.calib.getMagnitude, -50.0)
    ? ^ ^^ def testPhotomMulti(self): self.calib.setFluxMag0(1e12, 1e10) flux, fluxErr = 1000.0, 10.0 num = 5 mag, magErr = self.calib.getMagnitude(flux, fluxErr) # Result assumed to be true: tested elsewhere fluxList = numpy.array([flux for i in range(num)], dtype=float) fluxErrList = numpy.array([fluxErr for i in range(num)], dtype=float) magList = self.calib.getMagnitude(fluxList) for m in magList: self.assertEqual(m, mag) mags, magErrs = self.calib.getMagnitude(fluxList, fluxErrList) for m, dm in zip(mags, magErrs): self.assertEqual(m, mag) self.assertEqual(dm, magErr) flux, fluxErr = self.calib.getFlux(mag, magErr) # Result assumed to be true: tested elsewhere fluxList = self.calib.getFlux(magList) for f in fluxList: self.assertEqual(f, flux) fluxes = self.calib.getFlux(mags, magErrs) for f, df in zip(fluxes[0], fluxes[1]): self.assertAlmostEqual(f, flux) self.assertAlmostEqual(df, fluxErr) def testCtorFromMetadata(self): """Test building a Calib from metadata""" isoDate = "1995-01-26T07:32:00.000000000Z" exptime = 123.4 flux0, flux0Err = 1e12, 1e10 flux, fluxErr = 1000.0, 10.0 metadata = dafBase.PropertySet() metadata.add("TIME-MID", isoDate) metadata.add("EXPTIME", exptime) metadata.add("FLUXMAG0", flux0) metadata.add("FLUXMAG0ERR", flux0Err) self.calib = afwImage.Calib(metadata) self.assertEqual(isoDate, self.calib.getMidTime().toString()) self.assertAlmostEqual(self.calib.getMidTime().get(), 49743.3142245) self.assertEqual(self.calib.getExptime(), exptime) self.assertEqual(flux0, self.calib.getFluxMag0()[0]) self.assertEqual(flux0Err, self.calib.getFluxMag0()[1]) self.assertEqual(22.5, self.calib.getMagnitude(flux)) # Error just in flux self.calib.setFluxMag0(flux0, 0) self.assertAlmostEqual(self.calib.getMagnitude(flux, fluxErr)[1], 2.5/math.log(10)*fluxErr/flux) # # Check that we can clean up metadata # afwImage.stripCalibKeywords(metadata) self.assertEqual(len(metadata.names()), 0) def testCalibEquality(self): self.assertEqual(self.calib, self.calib) self.assertFalse(self.calib != self.calib) calib2 = afwImage.Calib() calib2.setExptime(12) self.assertNotEqual(calib2, self.calib) def testCalibFromCalibs(self): """Test creating a Calib from an array of Calibs""" exptime = 20 mag0, mag0Sigma = 1.0, 0.01 time0 = dafBase.DateTime.now().get() calibs = afwImage.vectorCalib() ncalib = 3 for i in range(ncalib): calib = afwImage.Calib() calib.setMidTime(dafBase.DateTime(time0 + i)) calib.setExptime(exptime) calib.setFluxMag0(mag0, mag0Sigma) calibs.append(calib) ocalib = afwImage.Calib(calibs) self.assertEqual(ocalib.getExptime(), ncalib*exptime) self.assertAlmostEqual(calibs[ncalib//2].getMidTime().get(), ocalib.getMidTime().get()) # # Check that we can only merge Calibs with the same fluxMag0 values # calibs[0].setFluxMag0(1.001*mag0, mag0Sigma)
    227 e1771d06 - tests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^ ^^^ ------- ------ ^^^^^^ ^
    223 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^ ^^ ^^ ^ lambda : afwImage.Calib(calibs)) def testCalibNegativeFlux(self): """Check that we can control if -ve fluxes raise exceptions""" self.calib.setFluxMag0(1e12) funcs = [lambda : self.calib.getMagnitude(-10), lambda : self.calib.getMagnitude(-10, 1)] for func in funcs:
    237 c86616d3 - tests.assertRaisesLsstCpp(self, pexExcept.DomainErrorException, func)
    ? ^ ^^^ ------- ------ ---------
    233 6fc1c3d1 + self.assertRaises(pexExcept.DomainError, func)
    ? ^ ^^ afwImage.Calib.setThrowOnNegativeFlux(False) for func in funcs: mags = func() try: # deal with returning mag or [mag, magErr] mags[0] except TypeError: mags = [mags, None] for m in mags: if m is not None: self.assertTrue(numpy.isnan(m)) afwImage.Calib.setThrowOnNegativeFlux(True) for func in funcs:
    254 c86616d3 - tests.assertRaisesLsstCpp(self, pexExcept.DomainErrorException, func)
    ? ^ ^^^ ------- ------ ---------
    250 6fc1c3d1 + self.assertRaises(pexExcept.DomainError, func)
    ? ^ ^^ def defineSdssFilters(): # Initialise filters as used for our tests imageUtils.resetFilters() wavelengths = dict() for name, lambdaEff, aliases in (('u', 355.1, []), ('g', 468.6, []), ('r', 616.5, []), ('i', 748.1, []), ('z', 893.1, ['zprime', "z'"]), ): wavelengths[name] = lambdaEff imageUtils.defineFilter(name, lambdaEff, alias=aliases) return wavelengths class ColorTestCase(unittest.TestCase): """A test case for Color""" def setUp(self): defineSdssFilters() def tearDown(self): pass def testCtor(self): c = afwImage.Color() c = afwImage.Color(1.2) def testLambdaEff(self): f = afwImage.Filter("g") g_r = 1.2 c = afwImage.Color(g_r) self.assertEqual(c.getLambdaEff(f), 1000*g_r) # XXX Not a real implementation! def testIsIndeterminate(self): """Test that a default-constructed Color tests True, but ones with a g-r value test False""" self.assertTrue(afwImage.Color().isIndeterminate()) self.assertFalse(afwImage.Color(1.2).isIndeterminate()) class FilterTestCase(unittest.TestCase): """A test case for Filter""" def setUp(self): # Initialise our filters # # Start by forgetting that we may already have defined filters # wavelengths = defineSdssFilters() self.filters = tuple(sorted(wavelengths.keys())) self.g_lambdaEff = [lambdaEff for name, lambdaEff in wavelengths.items() if name == "g"][0] # for tests def defineFilterProperty(self, name, lambdaEff, force=False): return afwImage.FilterProperty(name, lambdaEff, force); def testListFilters(self): self.assertEqual(afwImage.Filter_getNames(), self.filters) def testCtor(self): """Test that we can construct a Filter""" # A filter of type f = afwImage.Filter("g") def testCtorFromMetadata(self): """Test building a Filter from metadata""" metadata = dafBase.PropertySet() metadata.add("FILTER", "g") f = afwImage.Filter(metadata) self.assertEqual(f.getName(), "g") # # Check that we can clean up metadata # afwImage.stripFilterKeywords(metadata) self.assertEqual(len(metadata.names()), 0) badFilter = "rhl" # an undefined filter metadata.add("FILTER", badFilter) # Not defined
    335 eec925ce - tests.assertRaisesLsstCpp(self, pexExcept.NotFoundException,
    ? ^ ^^^ ------- ------ ^^^^^^ ^
    331 6fc1c3d1 + self.assertRaises(pexExcept.NotFoundError,
    ? ^ ^^ ^^ ^ lambda : afwImage.Filter(metadata)) # Force definition f = afwImage.Filter(metadata, True) self.assertEqual(f.getName(), badFilter) # name is correctly defined def testFilterEquality(self): # a "g" filter f = afwImage.Filter("g") g = afwImage.Filter("g") self.assertEqual(f, g) f = afwImage.Filter() # the unknown filter self.assertNotEqual(f, f) # ... doesn't equal itself def testFilterProperty(self): # a "g" filter f = afwImage.Filter("g") # The properties of a g filter g = afwImage.FilterProperty.lookup("g") if False: print "Filter: %s == %d lambda_{eff}=%g" % (f.getName(), f.getId(), f.getFilterProperty().getLambdaEff()) self.assertEqual(f.getName(), "g") self.assertEqual(f.getId(), 1) self.assertEqual(f.getFilterProperty().getLambdaEff(), self.g_lambdaEff) self.assertTrue(f.getFilterProperty() == self.defineFilterProperty("gX", self.g_lambdaEff, True)) self.assertEqual(g.getLambdaEff(), self.g_lambdaEff) def testFilterAliases(self): """Test that we can provide an alias for a Filter""" f0 = afwImage.Filter("z") f1 = afwImage.Filter("zprime") f2 = afwImage.Filter("z'") self.assertEqual(f0.getFilterProperty().getLambdaEff(), f1.getFilterProperty().getLambdaEff()) self.assertEqual(f0.getFilterProperty().getLambdaEff(), f2.getFilterProperty().getLambdaEff()) def testReset(self): """Test that we can reset filter IDs and properties if needs be""" # The properties of a g filter g = afwImage.FilterProperty.lookup("g") # # First FilterProperty # def tst(): gprime = self.defineFilterProperty("g", self.g_lambdaEff + 10)
    388 14d7dac1 - tests.assertRaisesLsstCpp(self, pexExcept.RuntimeErrorException, tst)
    ? ^ ^^^ ------- ------ ---------
    384 6fc1c3d1 + self.assertRaises(pexExcept.RuntimeError, tst)
    ? ^ ^^ gprime = self.defineFilterProperty("g", self.g_lambdaEff + 10, True) # should not raise gprime = self.defineFilterProperty("g", self.g_lambdaEff, True) # # Can redefine # def tst(): self.defineFilterProperty("g", self.g_lambdaEff + 10) # changing definition is not allowed
    396 ce2d5bb8 - tests.assertRaisesLsstCpp(self, pexExcept.RuntimeErrorException, tst)
    ? ^ ^^^ ------- ------ ---------
    392 6fc1c3d1 + self.assertRaises(pexExcept.RuntimeError, tst)
    ? ^ ^^ self.defineFilterProperty("g", self.g_lambdaEff) # identical redefinition is allowed # # Now Filter # afwImage.Filter.define(g, afwImage.Filter("g").getId()) # OK if Id's the same afwImage.Filter.define(g, afwImage.Filter.AUTO) # AUTO will assign the same ID def tst(): afwImage.Filter.define(g, afwImage.Filter("g").getId() + 10) # different ID
    408 14d7dac1 - tests.assertRaisesLsstCpp(self, pexExcept.RuntimeErrorException, tst)
    ? ^ ^^^ ------- ------ ---------
    404 6fc1c3d1 + self.assertRaises(pexExcept.RuntimeError, tst)
    ? ^ ^^ def testUnknownFilter(self): """Test that we can define, but not use, an unknown filter""" badFilter = "rhl" # an undefined filter # Not defined
    414 523afe02 - tests.assertRaisesLsstCpp(self, pexExcept.NotFoundException,
    ? ^ ^^^ ------- ------ ^^^^^^ ^
    410 6fc1c3d1 + self.assertRaises(pexExcept.NotFoundError,
    ? ^ ^^ ^^ ^ lambda : afwImage.Filter(badFilter)) # Force definition f = afwImage.Filter(badFilter, True) self.assertEqual(f.getName(), badFilter) # name is correctly defined
    420 523afe02 - tests.assertRaisesLsstCpp(self, pexExcept.NotFoundException,
    ? ^ ^^^ ------- ------ ^^^^^^ ^
    416 6fc1c3d1 + self.assertRaises(pexExcept.NotFoundError,
    ? ^ ^^ ^^ ^ lambda : f.getFilterProperty().getLambdaEff()) # can't use Filter f # # Now define badFilter # lambdaEff = 666.0; self.defineFilterProperty(badFilter, lambdaEff) self.assertEqual(f.getFilterProperty().getLambdaEff(), lambdaEff) # but now we can # # Check that we didn't accidently define the unknown filter #
    431 523afe02 - tests.assertRaisesLsstCpp(self, pexExcept.NotFoundException,
    ? ^ ^^^ ------- ------ ^^^^^^ ^
    427 6fc1c3d1 + self.assertRaises(pexExcept.NotFoundError,
    ? ^ ^^ ^^ ^ lambda : afwImage.Filter().getFilterProperty().getLambdaEff()) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" tests.init() suites = [] suites += unittest.makeSuite(CalibTestCase) suites += unittest.makeSuite(ColorTestCase) suites += unittest.makeSuite(FilterTestCase) suites += unittest.makeSuite(tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    14d7dac1

    commit 14d7dac1e2c59ddafd0fcabac9f7bb808dedfaae
    Author: rhl 
    Date:   Thu Apr 1 11:37:45 2010 +0000
    
        Added Filter and FilterProperty tests
    

    ce2d5bb8

    commit ce2d5bb8d9aba5006abc067b352d70710ea48a45
    Author: rhl 
    Date:   Thu Mar 24 18:41:51 2011 +0000
    
        Permit redeclaration of filters if they identical to previous definition
    

    eec925ce

    commit eec925ceafd337352af7e90c0c5b31de41b4bb6b
    Author: rhl 
    Date:   Tue Feb 22 04:24:46 2011 +0000
    
        Move knowledge of Filter FITS keywords into ctor-from-PropertySet
    

    a6d8990e

    commit a6d8990e1384850d9c47ca82d9adaec4878e4c05
    Author: rhl 
    Date:   Thu May 20 14:53:13 2010 +0000
    
        Added a Calib object, used in an Exposure
    

    523afe02

    commit 523afe0228eb898987ab8881925146f4e04091e0
    Author: rhl 
    Date:   Wed Apr 28 21:02:15 2010 +0000
    
        Allow a Filter to be created with an unknown name (if you set force=true), but you can't use it for anything but recovering its name; allow filter aliases in the .paf files
    

    78fe64c4

    commit 78fe64c4041ae4327a7f5d863bce631cfbbf39b2
    Author: Robert Lupton the Good 
    Date:   Tue Jan 31 12:06:51 2012 -0500
    
        Move the Calib processing after the cameraGeom import to allow Calib to know about Detector; #1337
    

    0e95e6dd

    commit 0e95e6dd9b034d9fd2b5c5f8bc48f183c1442288
    Author: rhl 
    Date:   Wed Sep 14 16:18:02 2011 +0000
    
        Added a (disabled) test for #1337
    

    2d86164e

    commit 2d86164e58f13f36062b4c1355d42d21e4d66d0b
    Author: Jim Bosch 
    Date:   Thu Feb 14 13:37:47 2013 -0500
    
        Unit test, improved documentation for CalibNoThrow.
    

    e1771d06

    commit e1771d06f69bb5650337e398e4dde4700f1e3d45
    Author: rhl 
    Date:   Tue Sep 20 18:16:34 2011 +0000
    
        Added ability to merge Calibs; #1326
    

    e27b0f1a

    commit e27b0f1aac88aa30d5d647f07db26128272aff4c
    Author: Paul Price 
    Date:   Fri Jan 20 17:47:27 2012 -0500
    
        Convert Filter tests to use pex_config.
    

    c86616d3

    commit c86616d3d5c0100455a0a295c28ed560155d99cd
    Author: Robert Lupton the Good 
    Date:   Thu Jun 7 15:46:25 2012 -0500
    
        Added Calib::setThrowOnNegativeFlux for #2158
    

    Commits in /Users/nate/repos_lsst/afw/

    780e3962

    commit 780e3962f7e3e311cbe9e1d49daf0c9db0478668
    Author: Simon Krughoff 
    Date:   Tue Feb 11 20:06:24 2014 -0600
    
        Added getters to AffineXYTransform to get the AffineTransform.  Fixed tests/testDetector.py.
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    83333880

    commit 83333880b73a52772e68efbcbf5ff3ac871820a0
    Author: Russell Owen 
    Date:   Fri Feb 14 13:22:57 2014 -0800
    
        Fixed exposure and color unit tests. That just leaves two failing tests
        which will be replaced or rewritten once the functionality is available.
    

    14d7dac1

    commit 14d7dac1e2c59ddafd0fcabac9f7bb808dedfaae
    Author: rhl 
    Date:   Thu Apr 1 11:37:45 2010 +0000
    
        Added Filter and FilterProperty tests
    

    Return to list

    python/lsst/afw/table/init.py

    Diff:

                    from .tableLib import *
    
    2 c6452b2d - from tableUtils import *
    ? ^ -- -
    2 7fd7bde6 + from .tableEnumDicts import *
    ? + ^^^^^^^

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    c6452b2d

    commit c6452b2d40e91211a16b38d4ab385e66c97fff13
    Author: Steven Bickerton 
    Date:   Wed Sep 3 10:41:27 2014 +0900
    
        add sourceRecalibrate routine to convert shapes to be wcs based.
    

    Commits in /Users/nate/repos_lsst/afw/

    7fd7bde6

    commit 7fd7bde6c33e04fd062b4709e220f26be48669ed
    Author: Russell Owen 
    Date:   Thu Feb 27 10:29:07 2014 -0800
    
        Added enum dicts for DetectorType and ReadoutCorner
    

    Return to list

    python/lsst/afw/geom/Extent.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    %{
                    #include "lsst/afw/geom/Extent.h"
                    #include "lsst/afw/geom/Point.h"
                    %}
                    
    
    29 747f909d - // This doesn't wrap "scalar OP extent" versions, but that's okay.
    %define %Extent_PREINCLUDE(T,N) %copyctor lsst::afw::geom::Extent; %useValueEquality(lsst::afw::geom::Extent)
    33 25e61ab4 - %rename(__add__) lsst::afw::geom::ExtentBase::operator+;
    ? -------------
    32 4567a4cd + %ignore lsst::afw::geom::ExtentBase::operator+;
    ? ++++
    34 25e61ab4 - %rename(__sub__) lsst::afw::geom::ExtentBase::operator-;
    ? -------------
    33 4567a4cd + %ignore lsst::afw::geom::ExtentBase::operator-;
    ? ++++
    35 25e61ab4 - %rename(__iadd__) lsst::afw::geom::ExtentBase::operator+=;
    ? --------------
    34 4567a4cd + %ignore lsst::afw::geom::ExtentBase::operator+=;
    ? ++++
    36 25e61ab4 - %rename(__isub__) lsst::afw::geom::ExtentBase::operator-=;
    ? --------------
    35 4567a4cd + %ignore lsst::afw::geom::ExtentBase::operator-=;
    ? ++++ %rename(__pos__) lsst::afw::geom::ExtentBase::operator+() const; %rename(__neg__) lsst::afw::geom::ExtentBase::operator-() const;
    39 25e61ab4 - %rename(__mul__) lsst::afw::geom::ExtentBase::operator*;
    ? -------------
    38 4567a4cd + %ignore lsst::afw::geom::ExtentBase::operator*;
    ? ++++
    40 25e61ab4 - %rename(__imul__) lsst::afw::geom::ExtentBase::operator*=;
    ? --------------
    39 4567a4cd + %ignore lsst::afw::geom::ExtentBase::operator*=;
    ? ++++
    41 25e61ab4 - %rename(__div__) lsst::afw::geom::ExtentBase::operator/;
    ? -------------
    40 4567a4cd + %ignore lsst::afw::geom::ExtentBase::operator/;
    ? ++++
    42 25e61ab4 - %rename(__idiv__) lsst::afw::geom::ExtentBase::operator/=;
    ? --------------
    41 4567a4cd + %ignore lsst::afw::geom::ExtentBase::operator/=;
    ? ++++ %enddef %define %Extent_POSTINCLUDE(T,N,SUFFIX) %template(ExtentCoordinateBase ## N ## SUFFIX) lsst::afw::geom::CoordinateBase,T,N>; %template(ExtentBase ## N ## SUFFIX) lsst::afw::geom::ExtentBase; %template(Extent ## N ## SUFFIX) lsst::afw::geom::Extent; %CoordinateBase_POSTINCLUDE(T, N, lsst::afw::geom::Extent);
    49 4567a4cd + %extend lsst::afw::geom::Extent {
    50 4567a4cd + lsst::afw::geom::Point __add__(lsst::afw::geom::Point const & other) const {
    51 4567a4cd + return *self + other;
    52 4567a4cd + }
    53 4567a4cd + lsst::afw::geom::Extent __add__(lsst::afw::geom::Extent const & other) const {
    54 4567a4cd + return *self + other;
    55 4567a4cd + }
    56 4567a4cd + lsst::afw::geom::Extent __sub__(lsst::afw::geom::Extent const & other) const {
    57 4567a4cd + return *self - other;
    58 4567a4cd + }
    59 4567a4cd + PyObject * __iadd__(PyObject** PYTHON_SELF, lsst::afw::geom::Extent const & other) {
    60 4567a4cd + *self += other;
    61 4567a4cd + Py_INCREF(*PYTHON_SELF);
    62 4567a4cd + return *PYTHON_SELF;
    63 4567a4cd + }
    64 4567a4cd + PyObject * __isub__(PyObject** PYTHON_SELF, lsst::afw::geom::Extent const & other) {
    65 4567a4cd + *self -= other;
    66 4567a4cd + Py_INCREF(*PYTHON_SELF);
    67 4567a4cd + return *PYTHON_SELF;
    68 4567a4cd + }
    69 4567a4cd + lsst::afw::geom::Extent __mul__(T scalar) const {
    70 4567a4cd + return *self * scalar;
    71 4567a4cd + }
    72 4567a4cd + PyObject * __imul__(PyObject** PYTHON_SELF, T scalar) {
    73 4567a4cd + *self *= scalar;
    74 4567a4cd + Py_INCREF(*PYTHON_SELF);
    75 4567a4cd + return *PYTHON_SELF;
    76 4567a4cd + }
    77 4567a4cd + lsst::afw::geom::Extent __rmul__(T scalar) const {
    78 4567a4cd + return scalar * (*self);
    79 4567a4cd + }
    80 4567a4cd + }
    %enddef
    82 4567a4cd +
    83 4567a4cd + %define %ExtentD_POSTINCLUDE(N)
    84 4567a4cd + %Extent_POSTINCLUDE(double, N, D)
    85 4567a4cd + %extend lsst::afw::geom::Extent {
    86 4567a4cd + lsst::afw::geom::Extent truncate() const { return truncate(*self); }
    87 4567a4cd + lsst::afw::geom::Extent floor() const { return floor(*self); }
    88 4567a4cd + lsst::afw::geom::Extent ceil() const { return ceil(*self); }
    89 4567a4cd + lsst::afw::geom::Extent __add__(lsst::afw::geom::Extent const & other) const {
    90 4567a4cd + return *self + other;
    91 4567a4cd + }
    92 4567a4cd + lsst::afw::geom::Point __add__(lsst::afw::geom::Point const & other) const {
    93 4567a4cd + return other + *self;
    94 4567a4cd + }
    95 4567a4cd + PyObject * __iadd__(PyObject** PYTHON_SELF, lsst::afw::geom::Extent const & other) {
    96 4567a4cd + *self += other;
    97 4567a4cd + Py_INCREF(*PYTHON_SELF);
    98 4567a4cd + return *PYTHON_SELF;
    99 4567a4cd + }
    100 4567a4cd + lsst::afw::geom::Extent __sub__(lsst::afw::geom::Extent const & other) const {
    101 4567a4cd + return *self - other;
    102 4567a4cd + }
    103 4567a4cd + PyObject * __isub__(PyObject** PYTHON_SELF, lsst::afw::geom::Extent const & other) {
    104 4567a4cd + *self -= other;
    105 4567a4cd + Py_INCREF(*PYTHON_SELF);
    106 4567a4cd + return *PYTHON_SELF;
    107 4567a4cd + }
    108 4567a4cd + // no need for overloads that take int scalars, because int scalars will automatically match the
    109 4567a4cd + // overloads that take double
    110 4567a4cd + lsst::afw::geom::Extent __truediv__(double scalar) const {
    111 4567a4cd + return *self / scalar;
    112 4567a4cd + }
    113 4567a4cd + PyObject * __itruediv__(PyObject** PYTHON_SELF, double scalar) {
    114 4567a4cd + *self /= scalar;
    115 4567a4cd + Py_INCREF(*PYTHON_SELF);
    116 4567a4cd + return *PYTHON_SELF;
    117 4567a4cd + }
    118 81c3bd10 + %pythoncode %{
    119 4567a4cd + # support code not using "__from__ future import division"
    120 81c3bd10 + # warning: this indentation level is required for SWIG 3.0.2, at least
    121 4567a4cd + __div__ = __truediv__
    122 4567a4cd + __idiv__ = __itruediv__
    123 81c3bd10 + %}
    124 b80fe1d3 + }
    125 4567a4cd + %template(truncate) lsst::afw::geom::truncate;
    126 4567a4cd + %template(floor) lsst::afw::geom::floor;
    127 4567a4cd + %template(ceil) lsst::afw::geom::ceil;
    128 4567a4cd + %enddef
    129 4567a4cd +
    130 4567a4cd + %define %ExtentI_POSTINCLUDE(N)
    131 4567a4cd + %Extent_POSTINCLUDE(int, N, I)
    132 4567a4cd + %extend lsst::afw::geom::Extent {
    133 4567a4cd + lsst::afw::geom::Extent __add__(lsst::afw::geom::Extent const & other) const {
    134 4567a4cd + return *self + other;
    135 4567a4cd + }
    136 4567a4cd + lsst::afw::geom::Extent __sub__(lsst::afw::geom::Extent const & other) const {
    137 4567a4cd + return *self - other;
    138 4567a4cd + }
    139 4567a4cd + lsst::afw::geom::Point __add__(lsst::afw::geom::Point const & other) const {
    140 4567a4cd + return *self + other;
    141 4567a4cd + }
    142 4567a4cd + lsst::afw::geom::Extent __mul__(double scalar) const {
    143 4567a4cd + return *self * scalar;
    144 4567a4cd + }
    145 4567a4cd + lsst::afw::geom::Extent __rmul__(double scalar) const {
    146 4567a4cd + return scalar * (*self);
    147 4567a4cd + }
    148 4567a4cd + // __floordiv__ (invoked by //) always takes ints, returns ExtentI.
    149 4567a4cd + lsst::afw::geom::Extent __floordiv__(int scalar) const {
    150 4567a4cd + // Python's integer division works differently that C++'s for negative numbers - Python
    151 4567a4cd + // uses floor (rounds towards more negative), while C++ truncates (rounds towards zero).
    152 4567a4cd + return floor(lsst::afw::geom::Extent(*self) / scalar);
    153 4567a4cd + }
    154 4567a4cd + PyObject * __ifloordiv__(PyObject** PYTHON_SELF, int scalar) {
    155 4567a4cd + *self = floor(lsst::afw::geom::Extent(*self) / scalar);
    156 4567a4cd + Py_INCREF(*PYTHON_SELF);
    157 4567a4cd + return *PYTHON_SELF;
    158 4567a4cd + }
    159 4567a4cd + // __truediv__ (invoked by / with future division) always takes doubles, returns ExtentD
    160 4567a4cd + lsst::afw::geom::Extent __truediv__(double scalar) const {
    161 4567a4cd + return *self / scalar;
    162 4567a4cd + }
    163 4567a4cd + // Don't want __itruediv__; would convert type in-place - but we have to add one that throws,
    164 4567a4cd + // because otherwise Python uses __div__, which is incorrect.
    165 4567a4cd + PyObject * __itruediv__(double scalar) const {
    166 4567a4cd + PyErr_SetString(PyExc_TypeError, "In-place true division not supported for Extent.");
    167 4567a4cd + return NULL;
    168 4567a4cd + }
    169 4567a4cd + // __div__ (invoked by / without future division) mimics __floordiv__ for ints, __truediv__ for floats
    170 4567a4cd + lsst::afw::geom::Extent __div__(int scalar) const {
    171 4567a4cd + return floor(lsst::afw::geom::Extent(*self) / scalar);
    172 4567a4cd + }
    173 4567a4cd + PyObject * __idiv__(PyObject** PYTHON_SELF, int scalar) {
    174 4567a4cd + *self = floor(lsst::afw::geom::Extent(*self) / scalar);
    175 4567a4cd + Py_INCREF(*PYTHON_SELF);
    176 4567a4cd + return *PYTHON_SELF;
    177 4567a4cd + }
    178 4567a4cd + lsst::afw::geom::Extent __div__(double scalar) const {
    179 4567a4cd + return *self / scalar;
    180 4567a4cd + }
    181 4567a4cd + // No __idiv__ taking doubles; would convert type in-place.
    182 4567a4cd + }
    183 25e61ab4 + %enddef

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    747f909d

    commit 747f909d1d90b2597c9daf7151f661639cf63a71
    Author: jbosch 
    Date:   Thu Dec 17 03:45:00 2009 +0000
    
        afw/#892 - swig wrappers for Point and Extent
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    Return to list

    include/lsst/afw/table/fwd.h

    Diff:

                    // -*- lsst-c++ -*-
                    /*
                     * LSST Data Management System
                     * Copyright 2008-2013 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    #ifndef LSST_AFW_TABLE_fwd_h_INCLUDED
                    #define LSST_AFW_TABLE_fwd_h_INCLUDED
                    
                    /**
                     *  @file lsst/afw/table/fwd.h
                     *
                     *  Forward declarations and typedefs for afw::table
                     *
                     *  Because many of the types in afw::table are actually typedefs of template classes,
                     *  manual forward declarations are verbose and fragile.  This file provides forward
                     *  declarations and typedefs (of forward declarations) for all public classes in
                     *  the package.
                     */
                    
                    #include 
                    
                    #include "lsst/afw/table/misc.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    template  class Key;
                    template  struct Field;
                    template  struct SchemaItem;
                    class Schema;
                    class SchemaMapper;
                    
    
    50 cfb9c7f4 + template class OutputFunctorKey;
    51 cfb9c7f4 + template class InputFunctorKey;
    52 cfb9c7f4 +
    template class ColumnViewT; template class CatalogT; template class SortedCatalogT; template class SourceColumnViewT; template class ExposureCatalogT; class BaseRecord; class BaseTable; class BaseColumnView; typedef CatalogT BaseCatalog; typedef CatalogT ConstBaseCatalog; class IdFactory; class SimpleRecord; class SimpleTable; typedef ColumnViewT SimpleColumnView; typedef SortedCatalogT SimpleCatalog; typedef SortedCatalogT ConstSimpleCatalog; class SourceRecord; class SourceTable; typedef SourceColumnViewT SourceColumnView; typedef SortedCatalogT SourceCatalog; typedef SortedCatalogT ConstSourceCatalog; class ExposureRecord; class ExposureTable; typedef ColumnViewT ExposureColumnView; typedef ExposureCatalogT ExposureCatalog; typedef ExposureCatalogT ConstExposureCatalog;
    84 5046e7f3 + class AmpInfoRecord;
    85 5046e7f3 + class AmpInfoTable;
    86 5046e7f3 + typedef ColumnViewT AmpInfoColumnView;
    87 5046e7f3 + typedef CatalogT AmpInfoCatalog;
    88 5046e7f3 + typedef CatalogT ConstAmpInfoCatalog;
    89 5046e7f3 +
    template struct Match; typedef Match SimpleMatch; typedef Match ReferenceMatch; typedef Match SourceMatch; typedef std::vector SimpleMatchVector; typedef std::vector ReferenceMatchVector; typedef std::vector SourceMatchVector; namespace io { class Writer; class Reader; class FitsWriter; class FitsReader; class Persistable; class InputArchive; class OutputArchive; class CatalogVector; } // namespace io }}} // namespace lsst::afw::table #endif // !LSST_AFW_TABLE_fwd_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    5046e7f3

    commit 5046e7f3f0a4f8591e21a396b1e1ee0dd205f659
    Author: Russell Owen 
    Date:   Thu Feb 13 17:35:58 2014 -0800
    
        Got the basics of AmpInfo catalogs working.
        However, I don't know how to SWIG-wrap ConstAmpInfoCatalog, and it looks messy,
        so I will try making Detector's constructor take a non-const catalog
        and copying that internally to a const catalog. (I should then test that
        changing the original catalog does not change the one inside Detector).
    

    cfb9c7f4

    commit cfb9c7f46b1c0486102a1eb7e2caa7032eee2efc
    Author: Jim Bosch 
    Date:   Wed Apr 9 11:41:43 2014 -0400
    
        Started work on FunctorKey
    

    Return to list

    tests/approximate.py

    Diff:

    1 59a4825f - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Approximate Run with: ./approximate.py or python >>> import approximate; approximate.run() """ import unittest import numpy as np import lsst.utils.tests as utilsTests import lsst.afw.display.ds9 as ds9 import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.pex.exceptions as pexExcept try: display except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ApproximateTestCase(unittest.TestCase): """A test case for Approximate""" def setUp(self): pass def tearDown(self): pass def makeRamp(self, binsize=1): # # make a linear ramp # ramp = afwImage.MaskedImageF(20, 40) x = [] for i in range(ramp.getWidth()): x.append((i + 0.5)*binsize - 0.5) y = [] for j in range(ramp.getHeight()): y.append((j + 0.5)*binsize - 0.5) var = 1 rampCoeffs = (1000, 1, 1) for i in range(ramp.getHeight()): for j in range(ramp.getWidth()): ramp.set(j, i, (rampCoeffs[0] + rampCoeffs[1]*x[j] + rampCoeffs[2]*y[i], 0x0, var)) return ramp, rampCoeffs, x, y def testLinearRamp(self): """Fit a ramp""" binsize = 1 ramp, rampCoeffs, xVec, yVec = self.makeRamp(binsize) # # Add a (labelled) bad value # ramp.set(ramp.getWidth()//2, ramp.getHeight()//2, (0, 0x1, np.nan)) if display: ds9.mtv(ramp, title="Input", frame=0) # # Here's the range that the approximation should be valid (and also the # bbox of the image returned by getImage) # bbox = afwGeom.BoxI(afwGeom.PointI(0, 0), afwGeom.PointI(binsize*ramp.getWidth() - 1, binsize*ramp.getHeight() - 1)) order = 3 # 1 would be enough to fit the ramp actrl = afwMath.ApproximateControl(afwMath.ApproximateControl.CHEBYSHEV, order) approx = afwMath.makeApproximate(xVec, yVec, ramp, bbox, actrl) for i, aim in enumerate([approx.getImage(), approx.getMaskedImage().getImage(), ]): if i == 0 and display: ds9.mtv(aim, title="interpolated", frame=1) with ds9.Buffering(): for x in xVec: for y in yVec: ds9.dot('+', x, y, size=0.4, frame=1)
    113 22807ea1 -
    ? ----
    114 b4f73cbf +
    for x, y in aim.getBBox().getCorners(): self.assertEqual(aim.get(x, y), rampCoeffs[0] + rampCoeffs[1]*x + rampCoeffs[1]*y) def testChebyshevEqualOrder(self): """Check that we enforce the condition orderX == orderY"""
    120 9118b4b1 - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    121 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ lambda : afwMath.ApproximateControl(afwMath.ApproximateControl.CHEBYSHEV, 1, 2))
    124 9118b4b1 +
    125 a167c1a0 + def testNoFinitePoints(self):
    126 a167c1a0 + """Check that makeApproximate throws a RuntimeError if grid has no finite points and weights to fit
    127 a167c1a0 + """
    128 a167c1a0 + binsize = 1
    129 a167c1a0 + for badValue in [(3, 0x1, 0), (np.nan, 0x1, 1)]:
    130 a167c1a0 + ramp, rampCoeffs, xVec, yVec = self.makeRamp(binsize)
    131 a167c1a0 + ramp.set(badValue)
    132 a167c1a0 + bbox = afwGeom.BoxI(afwGeom.PointI(0, 0), afwGeom.PointI(binsize*ramp.getWidth() - 1,
    133 a167c1a0 + binsize*ramp.getHeight() - 1))
    134 a167c1a0 + order = 2
    135 a167c1a0 + actrl = afwMath.ApproximateControl(afwMath.ApproximateControl.CHEBYSHEV, order)
    136 03d96365 + self.assertRaises(pexExcept.RuntimeError,
    137 03d96365 + lambda : afwMath.makeApproximate(xVec, yVec, ramp, bbox, actrl))
    def testLinearRampAsBackground(self): """Fit a ramp""" ramp, rampCoeffs = self.makeRamp()[0:2] if display: ds9.mtv(ramp, title="Input", frame=0) # # Here's the range that the approximation should be valid (and also the # bbox of the image returned by getImage) # bkgd = afwMath.makeBackground(ramp, afwMath.BackgroundControl(10, 10)) orderMax = 3 # 1 would be enough to fit the ramp for order in range(orderMax + 1): actrl = afwMath.ApproximateControl(afwMath.ApproximateControl.CHEBYSHEV, order) approx = bkgd.getApproximate(actrl) # # Get the Image, the MaskedImage, and the Image with a truncated expansion # for i, aim in enumerate([approx.getImage(), approx.getMaskedImage().getImage(), approx.getImage(order - 1 if order > 1 else -1), ]): if display and (i == 0 and order == 1): ds9.mtv(aim, title="Interpolated", frame=1) for x, y in aim.getBBox().getCorners(): val = np.mean(aim.getArray()) if order == 0 else \ rampCoeffs[0] + rampCoeffs[1]*x + rampCoeffs[1]*y self.assertEqual(aim.get(x, y), val) # # Check that we can't "truncate" the expansion to a higher order than we requested #
    160 9118b4b1 - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    175 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ lambda : approx.getImage(orderMax + 1, orderMax + 1)) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ApproximateTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9118b4b1

    commit 9118b4b10b049387776b83e24863c0eb025fe568
    Author: Robert Lupton the Good 
    Date:   Sun Oct 21 18:50:32 2012 -0400
    
        Give Background the ability return an Approximate object
        
        N.b. now that we need to auto-generate two sets of methods
        it seemed worth using boost pre-processor magic.  Note that
        we don't generate all possible Approximate pixel types,
        as Background only keeps one type in internal representation
        of its values (at least, BackgroundMI only keeps one type)
    

    22807ea1

    commit 22807ea1c556edece81168730e99a93466db5222
    Author: Robert Lupton the Good 
    Date:   Sun Oct 21 18:42:00 2012 -0400
    
        Split Approximate.getImage, adding Approximate.getMaskedImage
        
        Restructured test case
    

    59a4825f

    commit 59a4825ff5f0baef91416ce52df1679615f035f6
    Author: Robert Lupton the Good 
    Date:   Sat Oct 20 22:59:49 2012 -0400
    
        Added python bindings
    

    Commits in /Users/nate/repos_lsst/afw/

    a167c1a0

    commit a167c1a066b94790b9b40ca5ccca4c26ae934261
    Author: Yusra AlSayyad 
    Date:   Thu Jul 31 02:20:06 2014 -0500
    
        tests/approximate.py: unittest RuntimeError raised if fitting no finite points or weights
    

    03d96365

    commit 03d96365a6bd7cf447b218cdf2c673191b0e9695
    Author: Yusra AlSayyad 
    Date:   Tue Sep 30 16:53:48 2014 -0500
    
        Update exception in tests/approximate.py to reflect changes in DM-827
    

    9118b4b1

    commit 9118b4b10b049387776b83e24863c0eb025fe568
    Author: Robert Lupton the Good 
    Date:   Sun Oct 21 18:50:32 2012 -0400
    
        Give Background the ability return an Approximate object
        
        N.b. now that we need to auto-generate two sets of methods
        it seemed worth using boost pre-processor magic.  Note that
        we don't generate all possible Approximate pixel types,
        as Background only keeps one type in internal representation
        of its values (at least, BackgroundMI only keeps one type)
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    b4f73cbf

    commit b4f73cbf3097165062c02aa04905ab10b06c6bec
    Author: Russell Owen 
    Date:   Mon Sep 8 16:05:52 2014 -0700
    
        First pass at DM-840
        Added UNDEFINED ImageOrigin enum value
        Made UNDEFINED the default for image constructors (which have lots of defaults,
        so I can't just delete the origin default).
        Eliminated the default value for ImageBase.getBBox.
        Modified all code that calls functions that accept an ImageOrigin argument to specify it explicitly.
    

    Return to list

    examples/wcsTest.cc

    Diff:

                    // -*- LSST-C++ -*- // fixed format comment for emacs
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                    * @file
                    * @brief Simple test code for the Wcs Class
                    *        Created on:    23-Jul-2007 12:28:00 PM PDT (by NMS)
                    * @author Nicole M. Silvestri
                    *         Last modified: 20-Aug-2007 (by NMS)
                    */
                    
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/format.hpp"
                    #include "boost/shared_ptr.hpp"
                    
    
    40 b1f3d4be - /************************************************************************************************************/
    40 a9aec7fc + #include "lsst/utils/Utils.h"
    #include "lsst/pex/exceptions.h" #include "lsst/pex/logging/Trace.h" // turn off by recompiling with 'LSST_NO_TRACE 0' #include "lsst/afw/image.h" /**
    46 1192e949 - * @brief This test code incorporates some very simple tests of the Wcs Class
    ? ^
    46 a9aec7fc + * @brief This test code incorporates some very simple tests of the Wcs class and related classes.
    ? ^ +++++++++++++++++++++
    47 61855404 - * and its related classes.
    48 61855404 - *
    */ namespace afwCoord = lsst::afw::coord; namespace afwGeom = lsst::afw::geom; namespace afwImage = lsst::afw::image; using lsst::daf::base::PropertySet; int main(int argc, char **argv) { typedef double Pixel;
    60 8c6c0d93 - std::string mimg;
    ? ^^
    58 a9aec7fc + std::string inImagePath;
    ? +++ ^ +++++ if (argc < 2) {
    62 8c6c0d93 - std::string afwdata = getenv("AFWDATA_DIR");
    63 8c6c0d93 - if (afwdata.empty()) {
    64 8c6c0d93 - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << std::endl;
    60 a9aec7fc + try {
    61 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
    62 a9aec7fc + inImagePath = dataDir + "/data/medexp.fits";
    63 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    64 a9aec7fc + std::cerr << "Usage: wcsTest [fitsFile]" << std::endl;
    65 a9aec7fc + std::cerr << "fitsFile is the path to an exposure" << std::endl;
    65 8c6c0d93 - std::cerr << "Is afwdata set up?\n" << std::endl;
    ? ^ ^^^^
    66 a9aec7fc + std::cerr << "\nError: setup afwdata or specify fitsFile.\n" << std::endl;
    ? ^^^^^^^^^ ++++ +++ + +++++++ ^^^^^^ exit(EXIT_FAILURE);
    67 8c6c0d93 - } else {
    68 5b522953 - mimg = afwdata + "/small_MI.fits";
    69 8c6c0d93 - std::cerr << "Using " << mimg << std::endl;
    } } else {
    72 8c6c0d93 - mimg = std::string(argv[1]);
    ? ^^
    70 a9aec7fc + inImagePath = std::string(argv[1]);
    ? +++ ^ +++++ }
    74 8c6c0d93 -
    75 8c6c0d93 - const std::string inFilename(mimg);
    76 61855404 -
    77 61855404 - std::cout << "Opening file " << inFilename << std::endl;
    ? --- ^^^ ^ ^^
    72 a9aec7fc + std::cout << "Opening exposure " << inImagePath << std::endl;
    ? +++++++ ^^^^ ^ ^^ PropertySet::Ptr miMetadata(new PropertySet);
    80 ded0eb52 - afwImage::MaskedImage mskdImage(inFilename, miMetadata);
    81 b1f3d4be - afwImage::Wcs::Ptr wcs = afwImage::makeWcs(miMetadata);
    75 a9aec7fc + afwImage::Exposure exposure(inImagePath);
    76 a9aec7fc + if (!exposure.hasWcs()) {
    77 a9aec7fc + std::cerr << "Exposure does not have a WCS." << std::endl;
    78 a9aec7fc + exit(EXIT_FAILURE);
    79 a9aec7fc + }
    80 a9aec7fc + PTR(afwImage::Wcs) wcs = exposure.getWcs();
    // Testing input col, row values afwGeom::Point2D minCoord = afwGeom::Point2D(1.0, 1.0);
    86 c9c89e06 - afwGeom::Point2D xy = afwGeom::Point2D(mskdImage.getWidth(), mskdImage.getHeight());
    ? ^ ^^^^^^ ^ ^^^^^^
    85 a9aec7fc + afwGeom::Point2D xy = afwGeom::Point2D(exposure.getWidth(), exposure.getHeight());
    ? ^^^^ ^^ ^^^^ ^^ afwCoord::Coord::ConstPtr sky1 = wcs->pixelToSky(minCoord); afwCoord::Coord::ConstPtr sky2 = wcs->pixelToSky(xy); afwGeom::Angle miRa1 = sky1->getLongitude(); afwGeom::Angle miDecl1 = sky1->getLatitude(); afwGeom::Angle miRa2 = sky2->getLongitude(); afwGeom::Angle miDecl2 = sky2->getLatitude();
    96 5670d090 - std::cout << "ra, decl of " << inFilename << " at ("<< minCoord[0] << " " << minCoord[1] <<") = "
    ? ^^^ ^ ^^
    95 a9aec7fc + std::cout << "ra, decl of " << inImagePath << " at ("<< minCoord[0] << " " << minCoord[1] <<") = "
    ? ^^^^ ^ ^^ << "ra: " << miRa1.asDegrees() << " decl: " << miDecl1.asDegrees() << std::endl << std::endl;
    99 5670d090 - std::cout << "ra, decl of " << inFilename << " at ("<< xy[0] << " " << xy[1]<<") = "
    ? ^^^ ^ ^^
    98 a9aec7fc + std::cout << "ra, decl of " << inImagePath << " at ("<< xy[0] << " " << xy[1]<<") = "
    ? ^^^^ ^ ^^ << "ra: " << miRa2.asDegrees() << " decl: " << miDecl2.asDegrees() << std::endl << std::endl; double pixArea0 = wcs->pixArea(minCoord); double pixArea1 = wcs->pixArea(xy); std::cout << "pixel areas: " << pixArea0 << " " << pixArea1 << std::endl; // Testing input ra, dec values using output from above for now afwGeom::Point2D pix1 = wcs->skyToPixel(miRa1, miDecl1); afwGeom::Point2D pix2 = wcs->skyToPixel(miRa2, miDecl2);
    112 dcfba3df - std::cout << "col, row of " << inFilename << " at ("<< miRa1.asDegrees() << " " << miDecl1.asDegrees() <<") = "
    ? ^^^ ^ ^^
    111 a9aec7fc + std::cout << "col, row of " << inImagePath << " at ("<< miRa1.asDegrees() << " " << miDecl1.asDegrees() <<") = "
    ? ^^^^ ^ ^^ << "col: " << pix1[0] << " row: " << pix1[1] << std::endl << std::endl;
    115 dcfba3df - std::cout << "col, row of " << inFilename << " at ("<< miRa2.asDegrees() << " " << miDecl2.asDegrees() <<") = "
    ? ^^^ ^ ^^
    114 a9aec7fc + std::cout << "col, row of " << inImagePath << " at ("<< miRa2.asDegrees() << " " << miDecl2.asDegrees() <<") = "
    ? ^^^^ ^ ^^ << "col: " << pix2[0] << " row: " << pix2[1] << std::endl << std::endl; afwCoord::Coord::ConstPtr raDecl1 = makeCoord(afwCoord::FK5, miRa1, miDecl1); afwCoord::Coord::ConstPtr raDecl2 = makeCoord(afwCoord::FK5, miRa2, miDecl2); afwGeom::Point2D pix3 = wcs->skyToPixel(*raDecl1); afwGeom::Point2D pix4 = wcs->skyToPixel(*raDecl2);
    124 4b1efc73 - std::cout << "col, row of " << inFilename << " at ("<< (*raDecl1)[0] << " " << (*raDecl1)[1] << ") = "
    ? ^^^ ^ ^^
    123 a9aec7fc + std::cout << "col, row of " << inImagePath << " at ("<< (*raDecl1)[0] << " " << (*raDecl1)[1] << ") = "
    ? ^^^^ ^ ^^ << "col: " << pix3[0] << " row: " << pix3[1] << std::endl << std::endl;
    127 4b1efc73 - std::cout << "col, row of " << inFilename << " at ("<< (*raDecl2)[0] << " " << (*raDecl2)[1] << ") = "
    ? ^^^ ^ ^^
    126 a9aec7fc + std::cout << "col, row of " << inImagePath << " at ("<< (*raDecl2)[0] << " " << (*raDecl2)[1] << ") = "
    ? ^^^^ ^ ^^ << "col: " << pix4[0] << " row: " << pix4[1] << std::endl << std::endl; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    dcfba3df

    commit dcfba3df1cb8ef7d896b021ccb0f19684816742e
    Author: dstn 
    Date:   Thu May 5 14:54:57 2011 +0000
    
        it compiles -- ship it!
    

    8c6c0d93

    commit 8c6c0d93eaf03478cc6379a16055c3ae6119aa35
    Author: bick 
    Date:   Fri Jan 8 21:49:43 2010 +0000
    
        #1113 Changed examples to default to afwdata fits files with no arguments.
    

    5670d090

    commit 5670d090be5c197ab3f3ebecfc23e263fed42ea5
    Author: rowen 
    Date:   Fri Feb 26 21:17:39 2010 +0000
    
        Updated two tests to build with the new WCS API.
        However, there are serious problems; many tests and examples fail with:
        terminate called after throwing an instance of 'lsst::pex::exceptions::NotFoundException'
          what():  0: lsst::pex::exceptions::NotFoundException thrown at src/PropertySet.cc:319 in int lsst::daf::base::PropertySet::getAsInt(const std::string&) const
        0: Message: NAXIS not found
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    ded0eb52

    commit ded0eb52af9b4e28790afe94d115c1d8699fa271
    Author: Jim Bosch 
    Date:   Tue Nov 20 00:46:52 2012 -0500
    
        Overhaul FITS persistence for MaskedImage and Exposure: no more appending or passing HDU to read, no more multi-file support, but we put metadata in primary HDU and use INHERIT keyword (as per discussion on lsst-data list).
    

    1192e949

    commit 1192e9492b9dfbc05ab4c1de8827e39fbecc14a8
    Author: rowen 
    Date:   Tue Jun 24 19:53:51 2008 +0000
    
        Merge in ticket 350.
        (Note: this was done using rsync because I couldn't get
        svnmerge.py to merge any files -- it ran but did nothing).
        
        See ticket 350 for details, but the basics are:
        - Added SeparableKernel, and associated specialized convolution code
        - Modified Kernel::computeImage, Kernel::computeNewImage
          such that doNormalize comes before x, y arguments
          and has no default value (ticket 191).
          Warning: existing code may compile but give wrong answers!
        - Modified convolve such that doNormalize has no default value (ticket 191).
        - Globally modified include paths to use "" instead of <>
          for lsst and 3rd party packages (as per new standard)
        - Added Function::get/setParameter methods
        - Added Kernel::setCtrCol/Row methods
        - Removed radial lanczos from function library;
          only the separable version is now present.
    

    61855404

    commit 618554041c03d30fe370e2c3e69c0fb394c93ccb
    Author: nms 
    Date:   Tue Oct 9 00:00:09 2007 +0000
    
        Merged Exposure class code (.cc/.h and exposure.i) to trunk (from Ticket 167).
        Merged modifications made in Ticket 167 to MaskedImage, Kernel, and WCS class code.
        Added and merged final modifications to Exposure, WCS and Kernel class test code
          (associated examples/*.cc & tests/*.py files)
        Deleted all test images from tests/data.
        Added small_MI_corrupt_img.fits to tests/data for temporary storage of a test file used
        in both the WCS and Exposure test suites.
    

    b1f3d4be

    commit b1f3d4be1d780fcfb6db4e8ed634b2578f17d646
    Author: rhl 
    Date:   Thu Mar 3 05:28:53 2011 +0000
    
        Provide example of setting metadata in a Wcs object
    

    4b1efc73

    commit 4b1efc73cf5101f7b60417f626f9e8525ce30aa3
    Author: rhl 
    Date:   Thu Apr 1 18:05:41 2010 +0000
    
        Change the code to match the new APIs
    

    5b522953

    commit 5b522953c3a80b54c7832793f353c7e00d3b5ea7
    Author: Jim Bosch 
    Date:   Tue Nov 20 14:53:52 2012 -0500
    
        Convert tests to use MEFs (requires afwdata update), remove a worthless one.
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    tests/function.py

    Diff:

    1 f1382d6d - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import itertools import math import unittest import numpy import lsst.afw.geom as afwGeom import lsst.afw.math as afwMath import lsst.utils.tests as utilsTests import lsst.pex.logging as pexLog VERBOSITY = 0 # increase to see trace pexLog.Debug("lsst.afwMath", VERBOSITY) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def nrange(num, start, delta): """Return an array of num floats starting with start and incrementing by delta """ return numpy.arange(start, start + (delta * (num - 0.1)), delta) def sinc(x): """Return the normalized sinc function: sinc(x) = sin(pi * x) / (pi * x) """ if abs(x) < 1.0e-15: return 1.0 return math.sin(math.pi * x) / (math.pi * x) def referenceChebyshev1(x, n): """Reference implementation of Chebyshev polynomials of the first kind f(x) = T_n(x) """ # from Wikipedia if n == 0: return 1.0 if n == 1: return x return (2.0 * x * referenceChebyshev1(x, n-1)) - referenceChebyshev1(x, n-2) def referenceChebyshev1Polynomial1(x, params): """Reference implementation of a 1-D polynomial of Chebyshev polynomials of the first kind f(x) = params[0] T_0(x) + params[1] T_1(x) + params[2] T_2(x) """ retVal = 0.0 for ii in range(len(params)-1, -1, -1): retVal += params[ii] * referenceChebyshev1(x, ii) return retVal def referenceChebyshev1Polynomial2(x, y, params): """Reference implementation of a 2-D polynomial of Chebyshev polynomials of the first kind f(x) = params[0] T_0(x) T_0(y) # order 0 + params[1] T_1(x) T_0(y) + params[2] T_0(x) T_1(y) # order 1 + params[3] T_2(x) T_0(y) + params[4] T_1(x) T_1(y) + params[5] T_0(x) T_2(y) # order 2 + ... Raise RuntimeError if the number of parameters does not match an integer order. """ retVal = 0.0 order = 0 y_order = 0 for ii in range(0, len(params)): x_order = order - y_order retVal += params[ii] * referenceChebyshev1(x, x_order) * referenceChebyshev1(y, y_order) if x_order > 0: y_order += 1 else: order += 1 y_order = 0 if y_order != 0: raise RuntimeError("invalid # of parameters=%d" % (len(params),)) return retVal class FunctionTestCase(unittest.TestCase): def testChebyshev1Function1D(self): """A test for Chebyshev1Function1D""" maxOrder = 6 deltaParam = 0.3
    106 b1de898b - allParams = numpy.arange(deltaParam, deltaParam * (maxOrder + 1) + (deltaParam / 2.0), deltaParam)
    ranges = ((-1, 1), (-1, 0), (0, 1), (-17, -2), (-65.3, 2.132)) rangeIter = itertools.cycle(ranges) nPoints = 9 for order in range(maxOrder + 1): xMin, xMax = rangeIter.next() xMean = (xMin + xMax) / 2.0 xDelta = (xMax - xMin) / float(nPoints - 1) f = afwMath.Chebyshev1Function1D(order, xMin, xMax) numParams = f.getNParameters() params = numpy.arange(deltaParam, deltaParam * numParams + (deltaParam / 2.0), deltaParam) f.setParameters(params) g = afwMath.Chebyshev1Function1D(params, xMin, xMax) h = f.clone() self.assertEqual(f.getNParameters(), g.getNParameters()) self.assertEqual(f.getMinX(), xMin) self.assertEqual(f.getMaxX(), xMax) self.assertEqual(f.getOrder(), order) self.assertEqual(g.getMinX(), xMin) self.assertEqual(g.getMaxX(), xMax) self.assertEqual(g.getOrder(), order)
    132 b0cca861 -
    133 b0cca861 - # self.assertEqual(h.getMinX(), xMin)
    134 b0cca861 - # self.assertEqual(h.getMaxX(), xMax)
    minXNorm = None maxXNorm = None for x in numpy.arange(xMin, xMax + xDelta/2.0, xDelta): xNorm = 2.0 * (x - xMean) / float(xMax - xMin) if minXNorm == None or xNorm < minXNorm: minXNorm = xNorm if maxXNorm == None or xNorm > maxXNorm: maxXNorm = xNorm predVal = referenceChebyshev1Polynomial1(xNorm, params) if not numpy.allclose(predVal, f(x)): self.fail( "%s = %s != %s for x=%s, xMin=%s, xMax=%s, xNorm=%s, params=%s; order constructor" % \ (type(f).__name__, f(x), predVal, x, xMin, xMax, xNorm, params)) if not numpy.allclose(predVal, g(x)): self.fail( "%s = %s != %s for x=%s, xMin=%s, xMax=%s, xNorm=%s, params=%s; params constructor" %\ (type(f).__name__, g(x), predVal, x, xMin, xMax, xNorm, params)) if not numpy.allclose(predVal, h(x)): self.fail( "%s = %s != %s for x=%s, xMin=%s, xMax=%s, xNorm=%s, params=%s; clone" %\ (type(f).__name__, h(x), predVal, x, xMin, xMax, xNorm, params)) if not numpy.allclose((minXNorm, maxXNorm), (-1.0, 1.0)): raise RuntimeError( "Invalid x normalization: xMin=%s, xMax=%s, min/max xNorm=(%s, %s) != (-1, 1)" % (xMin, xMax, minXNorm, maxXNorm)) def testChebyshev1Function2D(self): """A test for Chebyshev1Function2D""" maxOrder = 6 deltaParam = 0.3 ranges = ((-1, 1), (-1, 0), (0, 1), (-17, -2), (-65.3, 2.132)) xRangeIter = itertools.cycle(ranges) yRangeIter = itertools.cycle(ranges) yRangeIter.next() # make x and y ranges off from each other nPoints = 7 # number of points in x and y at which to test the functions for order in range(maxOrder + 1): xMin, xMax = xRangeIter.next() xMean = (xMin + xMax) / 2.0 xDelta = (xMax - xMin) / float(nPoints - 1) yMin, yMax = yRangeIter.next() yMean = (yMin + yMax) / 2.0 yDelta = (yMax - yMin) / float(nPoints - 1) xyRange = afwGeom.Box2D(afwGeom.Point2D(xMin, yMin), afwGeom.Point2D(xMax, yMax)) f = afwMath.Chebyshev1Function2D(order, xyRange) numParams = f.getNParameters() params = nrange(numParams, deltaParam, deltaParam) f.setParameters(params) g = afwMath.Chebyshev1Function2D(params, xyRange) h = f.clone() self.assertEqual(f.getNParameters(), g.getNParameters()) self.assertEqual(f.getNParameters(), h.getNParameters()) self.assertEqual(f.getXYRange(), xyRange) self.assertEqual(f.getOrder(), order) self.assertEqual(g.getXYRange(), xyRange) self.assertEqual(g.getOrder(), order)
    201 b0cca861 - # self.assertEqual(h.getXYRange(), xyRange)
    202 b0cca861 - # self.assertEqual(h.getOrder(), order)
    203 0324b6cf -
    # vary x in the inner loop to exercise the caching minYNorm = None maxYNorm = None for y in numpy.arange(yMin, yMax + yDelta/2.0, yDelta): yNorm = 2.0 * (y - yMean) / float(yMax - yMin) if minYNorm == None or yNorm < minYNorm: minYNorm = yNorm if maxYNorm == None or yNorm > maxYNorm: maxYNorm = yNorm minXNorm = None maxXNorm = None for x in numpy.arange(xMin, xMax + xDelta/2.0, xDelta): xNorm = 2.0 * (x - xMean) / float(xMax - xMin) if minXNorm == None or xNorm < minXNorm: minXNorm = xNorm if maxXNorm == None or xNorm > maxXNorm: maxXNorm = xNorm predVal = referenceChebyshev1Polynomial2(xNorm, yNorm, params) if not numpy.allclose(predVal, f(x, y)): self.fail( "%s = %s != %s for x=%s, xMin=%s, xMax=%s, xNorm=%s, yMin=%s, yMax=%s, yNorm=%s, params=%s; order constructor" % \ (type(f).__name__, f(x, y), predVal, x, xMin, xMax, xNorm, yMin, yMax, yNorm, params)) if not numpy.allclose(predVal, g(x, y)): self.fail( "%s = %s != %s for x=%s, xMin=%s, xMax=%s, xNorm=%s, yMin=%s, yMax=%s, yNorm=%s, params=%s; params constructor" % \ (type(g).__name__, g(x, y), predVal, x, xMin, xMax, xNorm, yMin, yMax, yNorm, params)) if not numpy.allclose(predVal, h(x, y)): self.fail( "%s = %s != %s for x=%s, xMin=%s, xMax=%s, xNorm=%s, yMin=%s, yMax=%s, yNorm=%s, params=%s; clone" % \ (type(h).__name__, h(x, y), predVal, x, xMin, xMax, xNorm, yMin, yMax, yNorm, params)) if not numpy.allclose((minXNorm, maxXNorm), (-1.0, 1.0)): raise RuntimeError( "Invalid x normalization: xMin=%s, xMax=%s, min/max xNorm=(%s, %s) != (-1, 1)" % (xMin, xMax, minXNorm, maxXNorm)) if not numpy.allclose((minYNorm, maxYNorm), (-1.0, 1.0)): raise RuntimeError( "Invalid y normalization: yMin=%s, yMax=%s, min/max yNorm=(%s, %s) != (-1, 1)" % (yMin, yMax, minYNorm, maxYNorm)) # test that the number of parameters is correct for the given order def numParamsFromOrder(order):
    249 0324b6cf - return (order + 1) * (order + 2) / 2
    243 b80fe1d3 + return (order + 1) * (order + 2) // 2
    ? + MaxOrder = 13 for order in range(MaxOrder+1): f = afwMath.Chebyshev1Function2D(order) predNParams = numParamsFromOrder(order) self.assertEqual(f.getNParameters(), predNParams) afwMath.Chebyshev1Function2D(numpy.zeros(predNParams, dtype=float)) # test that the wrong number of parameters raises an exception validNumParams = set() for order in range(MaxOrder+1): validNumParams.add(numParamsFromOrder(order)) for numParams in range(numParamsFromOrder(MaxOrder)): if numParams in validNumParams: continue self.assertRaises(Exception, afwMath.Chebyshev1Function2D, numpy.zeros(numParams, dtype=float)) # test that changing parameters clears the cache # for simplicity use the xyRange that requires no normalization order = 3 numParams = numParamsFromOrder(order) f = afwMath.Chebyshev1Function2D(order) xyRange = afwGeom.Box2D(afwGeom.Point2D(-1.0, -1.0), afwGeom.Point2D(1.0, 1.0)) x = 0.5 y = -0.24 for addValue in (0.0, 0.2): params = nrange(numParams, deltaParam + addValue, deltaParam) f.setParameters(params) predVal = referenceChebyshev1Polynomial2(x, y, params) if not numpy.allclose(predVal, f(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, params=%s" % \ (type(f).__name__, f(x, y), predVal, x, y, params)) def testChebyshev1Function2DTruncate(self): """A test for Chebyshev1Function2D.truncate""" maxOrder = 6 deltaParam = 0.3 ranges = ((-1, 1), (-17, -2), (-65.3, 2.132)) xRangeIter = itertools.cycle(ranges) yRangeIter = itertools.cycle(ranges) yRangeIter.next() # make x and y ranges off from each other nPoints = 7 # number of points in x and y at which to test the functions for order in range(maxOrder + 1): xMin, xMax = xRangeIter.next() xMean = (xMin + xMax) / 2.0 xDelta = (xMax - xMin) / float(nPoints - 1) yMin, yMax = yRangeIter.next() yMean = (yMin + yMax) / 2.0 yDelta = (yMax - yMin) / float(nPoints - 1) xyRange = afwGeom.Box2D(afwGeom.Point2D(xMin, yMin), afwGeom.Point2D(xMax, yMax)) fullNParams = afwMath.Chebyshev1Function2D.nParametersFromOrder(order) fullParams = nrange(fullNParams, deltaParam, deltaParam) fullPoly = afwMath.Chebyshev1Function2D(fullParams, xyRange) for tooBigTruncOrder in range(order + 1, order + 3): self.assertRaises(Exception, fullPoly.truncate, tooBigTruncOrder) for truncOrder in range(order + 1): truncNParams = fullPoly.nParametersFromOrder(truncOrder)
    306 b80fe1d3 + truncParams = fullParams[0:truncNParams]
    f = fullPoly.truncate(truncOrder) self.assertEqual(f.getNParameters(), truncNParams) g = afwMath.Chebyshev1Function2D(fullParams[0:truncNParams], xyRange) self.assertEqual(f.getNParameters(), g.getNParameters()) self.assertEqual(f.getOrder(), truncOrder) self.assertEqual(f.getXYRange(), xyRange) self.assertEqual(g.getOrder(), truncOrder) self.assertEqual(g.getXYRange(), xyRange) minXNorm = None maxXNorm = None for x in numpy.arange(xMin, xMax + xDelta/2.0, xDelta): xNorm = 2.0 * (x - xMean) / float(xMax - xMin) if minXNorm == None or xNorm < minXNorm: minXNorm = xNorm if maxXNorm == None or xNorm > maxXNorm: maxXNorm = xNorm minYNorm = None maxYNorm = None for y in numpy.arange(yMin, yMax + yDelta/2.0, yDelta): yNorm = 2.0 * (y - yMean) / float(yMax - yMin) if minYNorm == None or yNorm < minYNorm: minYNorm = yNorm if maxYNorm == None or yNorm > maxYNorm: maxYNorm = yNorm if not numpy.allclose(f(x, y), g(x, y)): self.fail(
    346 b1de898b - "%s = %s != %s = %s for x=%s, xMin=%s, xMax=%s, xNorm=%s, yMin=%s, yMax=%s, yNorm=%s, params=%s; order constructor" % \
    ? ^
    341 b80fe1d3 + "%s = %s != %s = %s for x=%s, xMin=%s, xMax=%s, xNorm=%s, yMin=%s, yMax=%s, yNorm=%s, truncParams=%s; order constructor" % \
    ? ^^^^^^
    347 b1de898b - (type(f).__name__, f(x, y), g(x, y), type(g).__name__, x, xMin, xMax, xNorm, yMin, yMax, yNorm, params))
    ? ^
    342 b80fe1d3 + (type(f).__name__, f(x, y), g(x, y), type(g).__name__, x, xMin, xMax, xNorm, yMin, yMax, yNorm, truncParams))
    ? ^^^^^^ if not numpy.allclose((minYNorm, maxYNorm), (-1.0, 1.0)): raise RuntimeError( "Invalid y normalization: yMin=%s, yMax=%s, min/max yNorm=(%s, %s) != (-1, 1)" % (yMin, yMax, minYNorm, maxYNorm)) if not numpy.allclose((minXNorm, maxXNorm), (-1.0, 1.0)): raise RuntimeError( "Invalid x normalization: xMin=%s, xMax=%s, min/max xNorm=(%s, %s) != (-1, 1)" % (xMin, xMax, minXNorm, maxXNorm)) def testGaussianFunction1D(self): """A test for GaussianFunction1D""" def basicGaussian(x, sigma): return (1.0 / (sigma * math.sqrt(2 * math.pi))) * math.exp(-x**2 / (2.0 * sigma**2)) f = afwMath.GaussianFunction1D(1.0) for xsigma in (0.1, 1.0, 3.0): f.setParameters((xsigma,)) g = f.clone() xdelta = xsigma / 10.0 fSum = 0.0 for x in numpy.arange(-xsigma * 20, xsigma * 20.01, xdelta): predVal = basicGaussian(x, xsigma) fSum += predVal if not numpy.allclose(predVal, f(x)): self.fail("%s = %s != %s for x=%s, xsigma=%s" % \ (type(f).__name__, f(x), predVal, x, xsigma)) if not numpy.allclose(predVal, g(x)): self.fail("%s = %s != %s for x=%s, xsigma=%s; clone" % \ (type(f).__name__, f(x), predVal, x, xsigma)) approxArea = fSum * xdelta if not numpy.allclose(approxArea, 1.0): self.fail("%s area = %s != 1.0 for xsigma=%s" % \ (type(f).__name__, approxArea, xsigma)) def testGaussianFunction2D(self): """A test for GaussianFunction2D Assumes GaussianFunction1D is correct (tested elsewhere) """ f = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) f1 = afwMath.GaussianFunction1D(1.0) f2 = afwMath.GaussianFunction1D(1.0) for sigma1 in (0.1, 1.0, 3.0): for sigma2 in (0.1, 1.0, 3.0): for angle in (0.0, 0.4, 1.1): sinNegAngle = math.sin(-angle) cosNegAngle = math.cos(-angle) f.setParameters((sigma1, sigma2, angle)) g = f.clone() f1.setParameters((sigma1,)) f2.setParameters((sigma2,)) fSum = 0.0 delta1 = sigma1 / 5.0 delta2 = sigma2 / 5.0 for pos1 in numpy.arange(-sigma1 * 5, sigma1 * 5.01, delta1): for pos2 in numpy.arange(-sigma2 * 5.0, sigma2 * 5.01, delta2): x = ( cosNegAngle * pos1) + (sinNegAngle * pos2) y = (-sinNegAngle * pos1) + (cosNegAngle * pos2) predVal = f1(pos1) * f2(pos2) fSum += predVal if not numpy.allclose(predVal, f(x, y)): self.fail( "%s = %s != %s for pos1=%s, pos2=%s, x=%s, y=%s, sigma1=%s, sigma2=%s, angle=%s" % \ (type(f).__name__, f(x, y), predVal, pos1, pos2, x, y, sigma1, sigma2, angle)) if not numpy.allclose(predVal, g(x, y)): self.fail( "%s = %s != %s for pos1=%s, pos2=%s, x=%s, y=%s, sigma1=%s, sigma2=%s, angle=%s; clone" % \ (type(g).__name__, g(x, y), predVal, pos1, pos2, x, y, sigma1, sigma2, angle)) approxArea = fSum * delta1 * delta2 if not numpy.allclose(approxArea, 1.0): self.fail("%s area = %s != 1.0 for sigma1=%s, sigma2=%s" % \ (type(f).__name__, approxArea, sigma1, sigma2)) def testDoubleGaussianFunction2D(self): """A test for DoubleGaussianFunction2D Assumes GaussianFunction2D is correct (tested elsewhere) """ f = afwMath.DoubleGaussianFunction2D(1.0, 1.0) f1 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) f2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) for sigma1 in (1.0,): for sigma2 in (0.5, 2.0): for b in (0.0, 0.2, 2.0): f.setParameters((sigma1, sigma2, b)) g = f.clone() f1.setParameters((sigma1, sigma1, 0.0)) f2.setParameters((sigma2, sigma2, 0.0)) sigma1Sq = sigma1**2 sigma2Sq = sigma2**2 f1Mult = b * sigma2Sq / sigma1Sq allMult = sigma1Sq / (sigma1Sq + (b * sigma2Sq)) fSum = 0.0 maxsigma = max(sigma1, sigma2) minsigma = min(sigma1, sigma2) delta = minsigma / 5.0 for y in numpy.arange(-maxsigma * 5, maxsigma * 5.01, delta): for x in numpy.arange(-maxsigma * 5.0, maxsigma * 5.01, delta): predVal = (f1(x, y) + (f1Mult * f2(x, y))) * allMult fSum += predVal if not numpy.allclose(predVal, f(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, sigma1=%s, sigma2=%s, b=%s" % \ (type(f).__name__, f(x, y), predVal, x, y, sigma1, sigma2, b)) if not numpy.allclose(predVal, g(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, sigma1=%s, sigma2=%s, b=%s; clone" %\ (type(g).__name__, g(x, y), predVal, x, y, sigma1, sigma2, b)) approxArea = fSum * delta**2 if not numpy.allclose(approxArea, 1.0): self.fail("%s area = %s != 1.0 for sigma1=%s, sigma2=%s" % \ (type(f).__name__, approxArea, sigma1, sigma2)) def testIntegerDeltaFunction2D(self): """A test for IntegerDeltaFunction2D""" def basicDelta(x, xo): return (x == xo) for xo in numpy.arange(-5.0, 5.0, 1.0): for yo in numpy.arange(-5.0, 5.0, 1.0): f = afwMath.IntegerDeltaFunction2D(xo, yo) g = f.clone() for x in numpy.arange(-5.0, 5.0, 1.0): for y in numpy.arange(-5.0, 5.0, 1.0): predVal = basicDelta(x, xo) * basicDelta(y, yo) if predVal != f(x, y): self.fail("%s = %s != %s for x=%s, y=%s, xo=%s, yo=%s" % \ (type(f).__name__, f(x, y), predVal, x, y, xo, yo)) if predVal != g(x, y): self.fail("%s = %s != %s for x=%s, y=%s, xo=%s, yo=%s; clone" % \ (type(g).__name__, g(x, y), predVal, x, y, xo, yo)) def testLanczosFunction1D(self): """A test for LanczosFunction1D""" def basicLanczos1(x, n): return sinc(x) * sinc(x / float(n)) for n in range(1, 5): f = afwMath.LanczosFunction1D(n) self.assertEquals(f.getOrder(), n) for xOffset in (-10.0, 0.0, 0.05): f.setParameters((xOffset,)) g = f.clone() # self.assertEquals(g.getOrder(), n) for x in numpy.arange(-10.0, 10.1, 0.50): xAdj = x - xOffset predVal = basicLanczos1(xAdj, n) if not numpy.allclose(predVal, f(x)): self.fail("%s = %s != %s for n=%s, x=%s, xOffset=%s, xAdj=%s" % \ (type(f).__name__, f(x), predVal, n, x, xOffset, xAdj)) if not numpy.allclose(predVal, g(x)): self.fail("%s = %s != %s for n=%s, x=%s, xOffset=%s, xAdj=%s; clone" % \ (type(g).__name__, g(x), predVal, n, x, xOffset, xAdj)) def testLanczosFunction2D(self): """A test for LanczosFunction2D""" def basicLanczos1(x, n): return sinc(x) * sinc(x / float(n)) for n in range(1, 5): f = afwMath.LanczosFunction2D(n) self.assertEquals(f.getOrder(), n) for xOffset in (-10.0, 0.0, 0.05): for yOffset in (-0.01, 0.0, 7.5): f.setParameters((xOffset, yOffset)) g = f.clone() # self.assertEquals(g.getOrder(), n) for x in numpy.arange(-10.0, 10.1, 2.0): for y in numpy.arange(-10.0, 10.1, 2.0): xAdj = x - xOffset yAdj = y - yOffset predVal = basicLanczos1(xAdj, n) * basicLanczos1(yAdj, n) if not numpy.allclose(predVal, f(x, y)): self.fail("%s = %s != %s for n=%s, x=%s, " + "xOffset=%s, yOffset=%s, xAdj=%s, yAdj=%s" % (type(f).__name__, f(x, y), predVal, n, x, xOffset, yOffset, xAdj, yAdj)) if not numpy.allclose(predVal, g(x, y)): self.fail("%s = %s != %s for n=%s, x=%s, " + "xOffset=%s, yOffset=%s, xAdj=%s, yAdj=%s; clone" % (type(g).__name__, g(x, y), predVal, n, x, xOffset, yOffset, xAdj, yAdj)) def testPolynomialFunction1D(self): """A test for PolynomialFunction1D """ def basic1DPoly(x, params): """1-dimensional polynomial function""" ii = len(params) - 1 retVal = params[ii] while ii > 0: ii -= 1 retVal = retVal * x + params[ii] return retVal maxOrder = 4 deltaParam = 0.3 # test value using order constructor for order in range(maxOrder): numParams = order + 1 params = nrange(numParams, deltaParam, deltaParam) f = afwMath.PolynomialFunction1D(params) g = afwMath.PolynomialFunction1D(order) g.setParameters(params) h = f.clone() self.assertEqual(f.getOrder(), order) self.assertEqual(g.getOrder(), order)
    558 b0cca861 - # self.assertEqual(h.getOrder(), order)
    for x in numpy.arange(-10.0, 10.1, 1.0): predVal = basic1DPoly(x, params) if not numpy.allclose(predVal, f(x)): self.fail("%s = %s != %s for x=%s, params=%s; params constructor" % \ (type(f).__name__, f(x), predVal, x, params)) if not numpy.allclose(predVal, g(x)): self.fail("%s = %s != %s for x=%s, params=%s; order constructor" % \ (type(f).__name__, g(x), predVal, x, params)) if not numpy.allclose(predVal, h(x)): self.fail("%s = %s != %s for x=%s, params=%s; clone" % \ (type(h).__name__, h(x), predVal, x, params)) def testPolynomialFunction2D(self): """A test for PolynomialFunction2D """ def basic2DPoly(x, y, params): """2-dimensional polynomial function""" retVal = 0 numParams = len(params) order = 0 ii = 0 while True: for yOrder in range(order+1): xOrder = order - yOrder retVal += params[ii] * x**xOrder * y**yOrder ii += 1 if ii >= numParams: if xOrder != 0: raise RuntimeError("invalid # params=%d" % (numParams,)) return retVal order += 1 numParamsList = (1, 3, 6, 10)
    593 b1de898b - maxParams = numParamsList[-1]
    deltaParam = 0.3 # test function values for order, numParams in enumerate(numParamsList): params = nrange(numParams, deltaParam, deltaParam) f = afwMath.PolynomialFunction2D(params) g = afwMath.PolynomialFunction2D(order) g.setParameters(params) h = f.clone() self.assertEqual(f.getOrder(), order) self.assertEqual(g.getOrder(), order)
    606 b0cca861 - # self.assertEqual(h.getOrder(), order)
    # vary x in the inner loop to exercise the caching for y in numpy.arange(-10.0, 10.1, 2.5): for x in numpy.arange(-10.0, 10.1, 2.5): predVal = basic2DPoly(x, y, params) if not numpy.allclose(predVal, f(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, params=%s; params constructor" % \ (type(f).__name__, f(x, y), predVal, x, y, params)) if not numpy.allclose(predVal, g(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, params=%s; order constructor" % \ (type(f).__name__, g(x, y), predVal, x, y, params)) if not numpy.allclose(predVal, h(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, params=%s; clone" % \ (type(h).__name__, h(x, y), predVal, x, y, params)) # test that the number of parameters is correct for the given order def numParamsFromOrder(order):
    624 b10ab54c - return (order + 1) * (order + 2) / 2
    616 b80fe1d3 + return (order + 1) * (order + 2) // 2
    ? + MaxOrder = 13 for order in range(MaxOrder+1): f = afwMath.PolynomialFunction2D(order) predNParams = numParamsFromOrder(order) self.assertEqual(f.getNParameters(), predNParams) afwMath.PolynomialFunction2D(numpy.zeros(predNParams, dtype=float)) # test that the wrong number of parameters raises an exception validNumParams = set() for order in range(MaxOrder+1): validNumParams.add(numParamsFromOrder(order)) for numParams in range(numParamsFromOrder(MaxOrder)): if numParams in validNumParams: continue self.assertRaises(Exception, afwMath.PolynomialFunction2D, numpy.zeros(numParams, dtype=float)) # test that changing parameters clears the cache order = 3 numParams = numParamsFromOrder(order) f = afwMath.PolynomialFunction2D(order) x = 0.5 y = -0.24 for addValue in (0.0, 0.2): params = nrange(numParams, deltaParam + addValue, deltaParam) f.setParameters(params) predVal = basic2DPoly(x, y, params) if not numpy.allclose(predVal, f(x, y)): self.fail("%s = %s != %s for x=%s, y=%s, params=%s" % \ (type(f).__name__, f(x, y), predVal, x, y, params)) def testDFuncDParameters(self): """Test that we can differentiate the Function2 with respect to its parameters """ nOrder = 3 params = [] for i in range((nOrder + 1)*(nOrder + 2)//2): params.append(math.sin(1 + i)) # deterministic pretty-random numbers f = afwMath.PolynomialFunction2D(params) for (x, y) in [(2, 1), (1, 2), (2, 2)]: dFdC = f.getDFuncDParameters(x, y) self.assertAlmostEqual(f(x, y), sum([params[i]*dFdC[i] for i in range(len(params))])) def testCast(self): for instance in (afwMath.Chebyshev1Function1F(2), afwMath.GaussianFunction1F(1.0), afwMath.LanczosFunction1F(3), afwMath.NullFunction1F(), afwMath.PolynomialFunction1F(2)): Class = type(instance) base = instance.clone() self.assertEqual(type(base), afwMath.Function1F) derived = Class.cast(base) self.assertEqual(type(derived), Class) for instance in (afwMath.Chebyshev1Function1D(2), afwMath.GaussianFunction1D(1.0), afwMath.LanczosFunction1D(3), afwMath.NullFunction1D(), afwMath.PolynomialFunction1D(2)): Class = type(instance) base = instance.clone() self.assertEqual(type(base), afwMath.Function1D) derived = Class.cast(base) self.assertEqual(type(derived), Class) for instance in (afwMath.Chebyshev1Function2F(2), afwMath.GaussianFunction2F(1.0, 1.0), afwMath.DoubleGaussianFunction2F(1.0), afwMath.LanczosFunction2F(3), afwMath.NullFunction2F(), afwMath.PolynomialFunction2F(2)): Class = type(instance) base = instance.clone() self.assertEqual(type(base), afwMath.Function2F) derived = Class.cast(base) self.assertEqual(type(derived), Class) for instance in (afwMath.Chebyshev1Function2D(2), afwMath.GaussianFunction2D(1.0, 1.0), afwMath.DoubleGaussianFunction2D(1.0), afwMath.LanczosFunction2D(3), afwMath.NullFunction2D(), afwMath.PolynomialFunction2D(2)): Class = type(instance) base = instance.clone() self.assertEqual(type(base), afwMath.Function2D) derived = Class.cast(base) self.assertEqual(type(derived), Class) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(FunctionTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(doExit=False): """Run the tests""" utilsTests.run(suite(), doExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f1382d6d

    commit f1382d6d8aa2f1cd7290edd0a5c0d08f900f3d7a
    Author: rowen 
    Date:   Wed Nov 18 01:39:26 2009 +0000
    
        First cut. Haven't finished testing it.
    

    b0cca861

    commit b0cca861f36cd5f2a58ba9ef853a35efc93d4534
    Author: rowen 
    Date:   Wed May 18 19:56:05 2011 +0000
    
        Added unit tests for Function clone method.
        Fixed Chebyshev1Function2 clone method (this ticket).
        Changed API of Chebyshev1Function2 to use a Box2D to specify the range,
        instead of four doubles (reduces the chance of getting the arguments in the wrong order).
    

    b1de898b

    commit b1de898bac0c622a5dc3615f74f1f95478fba13b
    Author: rowen 
    Date:   Thu Aug 4 21:36:42 2011 +0000
    
        Improve test code to make sure caching is working correctly.
    

    0324b6cf

    commit 0324b6cf27626b7899518af2c010e99027913340
    Author: rowen 
    Date:   Mon May 2 18:52:43 2011 +0000
    
        Include test for nparams
    

    b10ab54c

    commit b10ab54c802578e3cc4158bc33aa212a5cba5bc4
    Author: rallsman 
    Date:   Sun Apr 6 01:43:41 2008 +0000
    
        Mostly replacing the files which were inexplicably zero length on last commit.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    .gitignore

    Diff:

                    *.dylib
                    *.o
                    *.so
                    *.os
                    *.pyc
                    *_wrap.cc
                    *Lib.py
    
    8 a0b9d98c + _build.*
    *~ core.* .sconf_temp .sconsign.dblite config.log memleak.fits bin/filter-gcc doc/*.tag doc/html doc/xml doc/doxygen.conf examples/maskIo2 examples/transform examples/fitsMemLeak include/lsst/afw/image/ImageExceptions.h include/lsst/afw/table/Source.h examples/.tests examples/*.fits examples/analyticKernel examples/ccd examples/rowColumnStats examples/chebyshev1Function examples/convolveLinear examples/deltaFunctionKernels examples/fitsio examples/fixedKernel examples/gaussianFunction examples/generate examples/integerDeltaFunction examples/lanczosFunction examples/lanczosKernel examples/makeExposure examples/maskedImageFitsIo examples/minimize examples/polynomialFunction examples/simpleConvolve examples/spatiallyVaryingConvolve examples/statistics examples/timeConvolve examples/timeImageAddition examples/timeImageIterators examples/timePixelAccess examples/timePixelAccessGil examples/timeSpatiallyVaryingConvolve examples/vwconvert examples/wcsTest examples/image examples/image1 examples/image2 examples/mask examples/maskedImage1 examples/maskedImage2 examples/decoratedImage examples/maskedImage examples/footprintFunctor examples/splineInterpolate examples/imageBackground examples/imageStatistics examples/ticket647 examples/integrateCartesian examples/integrateExample examples/integratePolar examples/forEachPixel examples/spatialCellExample examples/simpleStacker examples/timeConvolveGpu examples/timeWarpGpu examples/Spline lib/libafw.* python/lsst/*.pyc python/lsst/afw/version.py python/lsst/afw/*.pyc python/lsst/afw/cameraGeom/*.pyc python/lsst/afw/cameraGeom/cameraGeomLib_wrap.* python/lsst/afw/cameraGeom/cameraGeomLib.py python/lsst/afw/cameraGeom/_cameraGeomLib.so python/lsst/afw/coord/*.os python/lsst/afw/coord/*.so python/lsst/afw/coord/*.pyc python/lsst/afw/coord/coordLib.py python/lsst/afw/coord/*wrap.cc python/lsst/afw/detection/*.os python/lsst/afw/detection/*.pyc python/lsst/afw/detection/*.so python/lsst/afw/detection/*_wrap.cc python/lsst/afw/detection/detectionLib.py python/lsst/afw/display/*.pyc python/lsst/afw/display/*.os python/lsst/afw/display/*.so python/lsst/afw/display/fwDisplay.py python/lsst/afw/display/xpa.py tests/core.* tests/.tests
    102 4567a4cd + tests/coordinates
    tests/image.boost tests/*.fits tests/source_?????? tests/SourceMatchIo tests/bBox1 tests/background tests/checkTypeConversions tests/convolveGPU tests/coord tests/decoratedImage tests/distort tests/ellipse tests/footprint1 tests/footprintArray tests/fourierCutout tests/image tests/integrate tests/interpolate tests/kernel tests/localKernel tests/maskIo1 tests/maskIo2 tests/maskedImage tests/maskedImage1 tests/maskedImageIo1 tests/maskedImageIo2 tests/peak tests/ramFitsIO tests/rowColumnStats tests/sipterms tests/sourceIo1 tests/sourceIo2 tests/sourceMatch1 tests/stacker tests/statistics tests/statisticsSpeed tests/testLib.py
    138 3f99dca1 - tests/testTrapezoidalPacker
    tests/testWcs tests/testWarpGpu tests/ticket1145 tests/wcsCopy tests/ramFitsIO_fpC-005902-r6-0677_sub.fits_imageInOut.fit tests/ramFitsIO_fpC-005902-r6-0677_sub.fits_imageOut.fit tests/ramFitsIO_fpC-005902-r6-0677_sub.fits_exposureRamOut.fit tests/ramFitsIO_fpC-005902-r6-0677_sub.fits_fitsOut.fit tests/ramFitsIO_fpC-005902-r6-0677_sub.fits_cfitsioInOut.fit tests/testEigenLib.py tests/testTableArchives tests/ramFitsIO_fpC-005902-r6-0677_sub.fits_imageRamOut.fit tests/testSimpleTable tests/testDistortion tests/testSchema tests/testFitsTables
    156 028f751f + tests/testTableAliases
    testTable.fits tests/data/* ups/*.cfgc extensions/ # Output of tests doc/htmlDir im.fits bim.fits tmp-False.fits tmp-True.fits in.fits out.fits matches.fits

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3f99dca1

    commit 3f99dca17c50d3a38e5c5b0a487a347521286dd4
    Author: Jim Bosch 
    Date:   Fri May 23 18:50:20 2014 -0400
    
        Added 2-d Chebyshev class with new API
    

    Commits in /Users/nate/repos_lsst/afw/

    028f751f

    commit 028f751fa3d0fe5101d2467942ea2e5229ba5200
    Author: Jim Bosch 
    Date:   Wed Jul 9 18:13:59 2014 -0400
    
        Notify owning tables when schema aliases are modified.
    

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    a0b9d98c

    commit a0b9d98c33134ce69b177a9b6b6260de9f2bccfd
    Author: Russell Owen 
    Date:   Thu Jan 22 17:41:16 2015 -0800
    
        Added DistortedTanWcs and a unit test.
        
        fixup! Added DistortedTanWcs and a preliminary unit test.
        
        Fixed some incorrect names in DistortedTanWcs and improved argument names accordingly.
        
        Ignore _build files
    

    Return to list

    include/lsst/afw/table/BaseColumnView.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_BaseColumnView_h_INCLUDED
                    #define AFW_TABLE_BaseColumnView_h_INCLUDED
                    
                    #include "lsst/afw/table/BaseTable.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    namespace detail {
                    
                    /// Functor to compute a flag bit, used to create an ndarray expression template for flag columns.
                    struct FlagExtractor {
                        typedef Field::Element argument_type;
                        typedef bool result_type;
                    
                        result_type operator()(argument_type element) const { return element & _mask; }
                    
                        explicit FlagExtractor(Key const & key) : _mask(argument_type(1) << key.getBit()) {}
                    
                    private:
                        argument_type _mask;
                    };
                    
                    } // namespace detail
                    
                    class BaseTable;
                    
                    class BaseColumnView;
                    
                    /**
                     *  @brief A packed representation of a collection of Flag field columns.
                     *
                     *  The packing of bits here is not necessarily the same as the packing using in the actual
                     *  table, as the latter may contain more than 64 bits spread across multiple integers.
                     *
                     *  A BitsColumn can only be constructed by calling BaseColumnView::getBits().
                     */
                    class BitsColumn {
                    public:
                    
                        typedef boost::int64_t IntT;
                    
                        ndarray::Array getArray() const { return _array; }
                    
                        IntT getBit(Key const & key) const;
                        IntT getBit(std::string const & name) const;
                    
                        IntT getMask(Key const & key) const { return IntT(1) << getBit(key); }
                        IntT getMask(std::string const & name) const { return IntT(1) << getBit(name); }
                    
                    #ifndef SWIG
                        std::vector< SchemaItem > const & getSchemaItems() const { return _items; }
                    #endif
                    
                    private:
                    
                        friend class BaseColumnView;
                    
                        explicit BitsColumn(int size);
                    
                        ndarray::Array _array;
                        std::vector< SchemaItem > _items;
                    };
                    
                    /**
                     *  @brief Column-wise view into a sequence of records that have been allocated contiguously.
                     *
                     *  A BaseColumnView can be created from any iterator range that dereferences to records, as long
                     *  as those records' field data is contiguous in memory.  In practice, that means they must
                     *  have been created from the same table, and be in the same order they were created (with
                     *  no deletions).  It also requires that those records be allocated in the same block,
                     *  which can be guaranteed with BaseTable::preallocate().
                     *
                     *  Geometric (point and shape) fields cannot be accessed through a BaseColumnView, but their
                     *  scalar components can be.
                     *
                     *  BaseColumnView and its subclasses are always non-const views into a catalog, and so cannot
                     *  be obtained from a catalog-of-const (trying this results in an exception, not a compilation
                     *  error).  As a result, all its accessors return arrays of non-const elements, even though
                     *  they are themselves const member functions.  This is no different from a shared_ptr's
                     *  get() member function returning a non-const T*, even though get() is a const member function.
                     */
                    class BaseColumnView {
                    public:
                    
                        /// @brief Return the table that owns the records.
                        PTR(BaseTable) getTable() const;
                    
                        /// @brief Return the schema that defines the fields.
                        Schema getSchema() const { return getTable()->getSchema(); }
                    
                        /// @brief Return a 1-d array corresponding to a scalar field (or subfield).
                        template 
                        ndarray::ArrayRef const operator[](Key const & key) const;
                    
                        /// @brief Return a 2-d array corresponding to an array field.
                        template 
                        ndarray::ArrayRef const operator[](Key< Array > const & key) const;
                    
                        /**
                         *  @brief Return a 1-d array expression corresponding to a flag bit.
                         *
                         *  In C++, the return value is a lazy ndarray expression template that performs the bitwise
                         *  & operation on every element when that element is requested.  In Python, the result will
                         *  be copied into a bool NumPy array.
                         */
                        ndarray::result_of::vectorize< detail::FlagExtractor,
                                                       ndarray::Array< Field::Element const,1> >::type
                        operator[](Key const & key) const;
                    
                        /**
                         *  @brief Return an integer array with the given Flag fields repacked into individual bits.
                         *
                         *  The returned object contains both the int64 array and accessors to obtain a mask given
                         *  a Key or field name.
                         *
    
    117 ecd0c5af - * @throw pex::exceptions::LengthErrorException if keys.size() > 64
    ? ---------
    117 21597d88 + * @throw pex::exceptions::LengthError if keys.size() > 64
    */ BitsColumn getBits(std::vector< Key > const & keys) const; /** * @brief Return an integer array with all Flag fields repacked into individual bits. * * The returned object contains both the int64 array and accessors to obtain a mask given * a Key or field name. *
    127 ecd0c5af - * @throw pex::exceptions::LengthErrorException if the schema has more than 64 Flag fields.
    ? ---------
    127 21597d88 + * @throw pex::exceptions::LengthError if the schema has more than 64 Flag fields.
    */ BitsColumn getAllBits() const; /** * @brief Construct a BaseColumnView from an iterator range. * * The iterators must dereference to a reference or const reference to a record.
    135 d6480e01 - * If the record data is not contiguous in memory, throws lsst::pex::exceptions::RuntimeErrorException.
    ? ---------
    135 21597d88 + * If the record data is not contiguous in memory, throws lsst::pex::exceptions::RuntimeError.
    */ template static BaseColumnView make(PTR(BaseTable) const & table, InputIterator first, InputIterator last); /** * @brief Return true if the given record iterator range is continuous and the records all belong * to the given table. * * This tests exactly the same requiremetns needed to construct a column view, so if this test * succeeds, BaseColumnView::make should as well. */ template static bool isRangeContiguous(PTR(BaseTable) const & table, InputIterator first, InputIterator last); ~BaseColumnView(); protected: BaseColumnView( PTR(BaseTable) const & table, int recordCount, void * buf, ndarray::Manager::Ptr const & manager ); private: friend class BaseTable; struct Impl; boost::shared_ptr _impl; }; template class ColumnViewT : public BaseColumnView { public: typedef RecordT Record; typedef typename RecordT::Table Table; /// @brief @copydoc BaseColumnView::getTable PTR(Table) getTable() const { return boost::static_pointer_cast(BaseColumnView::getTable()); } /// @brief @copydoc BaseColumnView::make template static ColumnViewT make(PTR(Table) const & table, InputIterator first, InputIterator last) { return ColumnViewT(BaseColumnView::make(table, first, last)); } protected: explicit ColumnViewT(BaseColumnView const & base) : BaseColumnView(base) {} }; template BaseColumnView BaseColumnView::make(PTR(BaseTable) const & table, InputIterator first, InputIterator last) { if (first == last) { return BaseColumnView(table, 0, 0, ndarray::Manager::Ptr()); } Schema schema = table->getSchema(); std::size_t recordSize = schema.getRecordSize(); std::size_t recordCount = 1; void * buf = first->_data; ndarray::Manager::Ptr manager = first->_manager; char * expected = reinterpret_cast(buf) + recordSize; for (++first; first != last; ++first, ++recordCount, expected += recordSize) { if (first->_data != expected || first->_manager != manager) { throw LSST_EXCEPT(
    203 dbc20e58 - lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    203 21597d88 + lsst::pex::exceptions::RuntimeError,
    "Record data is not contiguous in memory." ); } } return BaseColumnView(table, recordCount, buf, manager); } template bool BaseColumnView::isRangeContiguous( PTR(BaseTable) const & table, InputIterator first, InputIterator last ) { if (first == last) return true; Schema schema = table->getSchema(); std::size_t recordSize = schema.getRecordSize(); std::size_t recordCount = 1; void * buf = first->_data; ndarray::Manager::Ptr manager = first->_manager; char * expected = reinterpret_cast(buf) + recordSize; for (++first; first != last; ++first, ++recordCount, expected += recordSize) { if (first->_data != expected || first->_manager != manager) { return false; } } return true; } }}} // namespace lsst::afw::table #endif // !AFW_TABLE_BaseColumnView_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ecd0c5af

    commit ecd0c5af7cb5b6b33e0d963d6e12d711d4bed447
    Author: Jim Bosch 
    Date:   Tue Mar 13 20:31:29 2012 -0400
    
        added packed bit flag arrays to column views
    

    d6480e01

    commit d6480e01cf98ec6e6ebea9b7f58d2d9dcef6beef
    Author: Jim Bosch 
    Date:   Sun Feb 5 23:11:25 2012 -0500
    
        lots of documentation, and a little refactoring to improve readability
    

    dbc20e58

    commit dbc20e585ec07b70b8c9dc3bbf9707ee3c200480
    Author: Jim Bosch 
    Date:   Wed Jan 25 20:07:49 2012 -0500
    
        lots of shuffling code around.  FITS table support now much better organized
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/image/Mask.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /// \file
                    /// \brief Implementations of Mask class methods
                    
                    /*
                     * There are a number of classes defined here and in Mask.h
                     *
                     * The fundamental type visible to the user is Mask; a 2-d array of pixels.  Each of these pixels should
                     * be thought of as a set of bits, and the names of these bits are given by MaskPlaneDict (which is
                     * implemented as a std::map)
                     *
                     * Internally to this file, we have a MapWithHash which is like a std::map, but maintains a hash of its
                     * contents;  this is used to check equality efficiently.
                     *
                     * We also have a MaskDict which isa MapWithHash, but also maintains a list of MaskDicts (or equivalently
                     * MapWithHash) allowing us to iterate over these maps, updating them as needed.
                     *
                     * The list of MaskDicts is actually kept as a singleton of a helper class, DictState
                     */
                    
                    #include 
                    #include 
                    #include 
                    
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/lambda/lambda.hpp"
                    #pragma clang diagnostic pop
                    #include "boost/format.hpp"
                    #include "boost/filesystem/path.hpp"
                    
                    #include "boost/functional/hash.hpp"
                    
                    #include "boost/bind.hpp"
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/image/Wcs.h"
                    #include "lsst/afw/image/Mask.h"
                    
                    #include "lsst/afw/image/LsstImageTypes.h"
                    
                    /************************************************************************************************************/
                    //
                    // for FITS code
                    //
                    #include "boost/mpl/vector.hpp"
                    #include "boost/gil/gil_all.hpp"
                    #include "lsst/afw/image/fits/fits_io.h"
                    #include "lsst/afw/image/fits/fits_io_mpl.h"
                    
                    namespace afwGeom = lsst::afw::geom;
                    namespace dafBase = lsst::daf::base;
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace pexLog = lsst::pex::logging;
                    
                    /************************************************************************************************************/
                    
                    namespace lsst { namespace afw { namespace image {
                        namespace detail {
                            class MaskDict;
                        }
                    
                    namespace {
                        void setInitMaskBits(PTR(detail::MaskDict) dict);
                        /*
                         * A std::map that maintains a hash value of its contents
                         *
                         * We don't simply inherit from the std::map as we need to force the user to use add and remove;
                         * we could inherit, make operator[] private, and never use MapWithHash via a base-class pointer
                         * but it seemed simpler to only forward the functions we wish to support
                         */
                        struct MapWithHash {
                            typedef detail::MaskPlaneDict::value_type value_type;
                            typedef detail::MaskPlaneDict::const_iterator const_iterator;
                    
                            MapWithHash(detail::MaskPlaneDict const& dict=detail::MaskPlaneDict()) :
                                _dict(dict), _hash(_calcHash()) {
                            }
                            ~MapWithHash() { }
                    
                            bool operator==(MapWithHash const& rhs) const {
                                return _hash == rhs._hash;
                            }
                    
                            const_iterator begin() const { return _dict.begin(); }
                            const_iterator end() const { return _dict.end(); }
                            const_iterator find(detail::MaskPlaneDict::key_type const& name) const { return _dict.find(name); }
                    
                            void add(std::string const& str, int val) {
                                _dict[str] = val;
                                _calcHash();
                            }
                    
                            bool empty() const {
                                return _dict.empty();
                            }
                            
                            void clear() {
                                _dict.clear();
                            }
                            
                            std::size_t size() const {
                                return _dict.size();
                            }
                    
                            void erase(std::string const& str) {
                                if (_dict.find(str) != _dict.end()) {
                                    _dict.erase(str);
                                    _calcHash();
                                }
                            }
                    
                            detail::MaskPlaneDict const& getMaskPlaneDict() const {
                                return _dict;
                            }
                            
                            std::size_t getHash() const {
                                return _hash;
                            }
                        private:
                            detail::MaskPlaneDict _dict;
                            std::size_t _hash;
                    
                            // calculate the hash
                            std::size_t _calcHash() {
                                _hash = 0x0;
                                for (const_iterator ptr = begin(); ptr != end(); ++ptr) {
                                    _hash = (_hash << 1) ^
                                        boost::hash()((*ptr).first + str(boost::format("%d") % ptr->second));
                                }
                    
                                return _hash;
                            }        
                        };
                    
                        bool operator!=(MapWithHash const& lhs, MapWithHash const& rhs) {
                            return !(lhs == rhs);
                        }
                    
                        class DictState;                   // forward declaration
                    }
                    
                    namespace detail {
                    /*
                     * A MaskDict is a MapWithHash, but additionally maintains a list of all live MaskDicts (the list is
                     * actually kept in a singleton instance of DictState)
                     */
                    class MaskDict : public MapWithHash {
                        friend class ::lsst::afw::image::DictState; // actually anonymous within lsst::afw::image; g++ is confused
                    
                        MaskDict() : MapWithHash() {}
                        MaskDict(MapWithHash const* dict) : MapWithHash(*dict) {}
                    public:
                        static PTR(MaskDict) makeMaskDict();
                        static PTR(MaskDict) makeMaskDict(detail::MaskPlaneDict const &dict);
                        static PTR(MaskDict) setDefaultDict(PTR(MaskDict) dict);
                    
                        PTR(MaskDict) clone() const;
                    
                        ~MaskDict();
                    
                        int getUnusedPlane() const;
                        int getMaskPlane(const std::string& name) const;
                    
                        void print() const {
                            for (MapWithHash::const_iterator ptr = begin(); ptr != end(); ++ptr) {
                                std::cout << "Plane " << ptr->second << " -> " << ptr->first << std::endl;
                            }
                        }
                    
                        static PTR(MaskDict) incrDefaultVersion();
                        static void listMaskDicts();
                    };
                    }
                    
                    /************************************************************************************************************/
                    
                    namespace {
                        /*
                         * A struct to hold our global state, and for whose components
                         * we can control the order of creation/destruction
                         */
                        class DictState {
                            friend class detail::MaskDict;
                    
                            typedef std::map HandleList;
                    
                        public:
                            DictState() {
                                _dictCounter = 0;
                                _defaultMaskDict = PTR(detail::MaskDict)(new detail::MaskDict);
                                _dicts[_defaultMaskDict.get()] = _dictCounter++;
                            }
                    
                            ~DictState() {
                                _defaultMaskDict.reset();
                    
                                for (HandleList::iterator ptr = _dicts.begin(); ptr != _dicts.end(); ++ptr) {
                                    delete ptr->first;
                                }
                                _dicts.clear();
                            }
                    
                            template
                            void forEachMaskDict(FunctorT func) {
                                for (HandleList::const_iterator ptr = _dicts.begin(); ptr != _dicts.end(); ++ptr) {
                                    func(ptr->first);
                                }
                            }
                    
                        private:
                            PTR(detail::MaskDict) getDefaultDict() {
                                static bool first = true;
                    
                                if (first) {
                                    setInitMaskBits(_defaultMaskDict);
                                    
                                    first = false;
                                }
                    
                                return _defaultMaskDict;
                            }
                    
                            PTR(detail::MaskDict) setDefaultDict(PTR(detail::MaskDict) newDefaultMaskDict) {
                                _defaultMaskDict = newDefaultMaskDict;
                    
                                return _defaultMaskDict;
                            }
                    
                            void addDict(MapWithHash *dict) {
                                _dicts[dict] = _dictCounter++;
                            }
                                
                            void eraseDict(MapWithHash *dict) {
                                _dicts.erase(dict);
                            }
                            
                            PTR(detail::MaskDict) incrDefaultVersion() {
                                _defaultMaskDict = PTR(detail::MaskDict)(new detail::MaskDict(*_defaultMaskDict.get()));
                                addDict(_defaultMaskDict.get());
                    
                                return _defaultMaskDict;
                            }
                    
                            PTR(detail::MaskDict) _defaultMaskDict; // default MaskDict to use
                            HandleList _dicts;                            // all the live MaskDicts
                            int _dictCounter;
                        };
                    
                        static DictState _state;
                    }
                    
                    /************************************************************************************************************/
                    namespace detail {
                    /*
                     * Implementation of MaskDict
                     */
                    /*
                     * Return the default dictionary, unless you provide mpd in which case you get one of
                     * your very very own
                     */
                    PTR(MaskDict)
                    MaskDict::makeMaskDict()
                    {
                        return _state.getDefaultDict();
                    }
                    
                    PTR(MaskDict)
                    MaskDict::makeMaskDict(detail::MaskPlaneDict const& mpd)
                    {
                        PTR(MaskDict) dict = _state.getDefaultDict();
                    
                        if (!mpd.empty()) {
                            MapWithHash mwh(mpd);
                            dict = PTR(MaskDict)(new MaskDict(&mwh));
                            _state.addDict(dict.get());
                        }
                    
                        return dict;
                    }
                    
                    PTR(MaskDict)
                    MaskDict::setDefaultDict(PTR(MaskDict) dict)
                    {
                        return _state.setDefaultDict(dict);
                    }
                                
                    PTR(MaskDict) MaskDict::clone() const {
                        PTR(MaskDict) dict(new MaskDict(*this));
                        
                        _state.addDict(dict.get());
                    
                        return dict;
                    }
                    
                    MaskDict::~MaskDict() {
                        _state.eraseDict(this);
                    }
                    
                    PTR(MaskDict) MaskDict::incrDefaultVersion() {
                        return _state.incrDefaultVersion();
                    }
                    
                    int
                    MaskDict::getUnusedPlane() const
                    {
                        if (empty()) {
                            return 0;
                        }
                    
                        MapWithHash::const_iterator const it =
                            std::max_element(begin(), end(), boost::bind(std::less(),
                                                                       boost::bind(&MapWithHash::value_type::second, _1),
                                                                       boost::bind(&MapWithHash::value_type::second, _2)
                                                                      )
                                            );
                        assert(it != end());
                        int id = it->second + 1;        // The maskPlane to use if there are no gaps
                            
                        for (int i = 0; i < id; ++i) {
                            MapWithHash::const_iterator const it = // is i already used in this Mask?
                                std::find_if(begin(), end(), boost::bind(std::equal_to(),
                                                                       boost::bind(&MapWithHash::value_type::second, _1), i));
                            if (it == end()) {              // Not used; so we'll use it
                                return i;
                            }
                        }
                    
                        return id;
                    }
                    
                    int
                    detail::MaskDict::getMaskPlane(const std::string& name) const
                    {
                        MapWithHash::const_iterator i = find(name);
                        
                        return (i == end()) ? -1 : i->second;
                    }
                    }
                    
                    namespace {
                        /*
                         * Definition of the default mask bits
                         *
                         * N.b. this function is in an anonymous namespace, and is invisible to doxygen.  ALL mask
                         * planes defined here should be documented with the Mask class in Mask.h
                         */
                        void
                        setInitMaskBits(PTR(detail::MaskDict) dict)
                        {
                            int i = -1;
                            dict->add("BAD", ++i);
                            dict->add("SAT", ++i);           // should be SATURATED
                            dict->add("INTRP", ++i);         // should be INTERPOLATED
                            dict->add("CR", ++i);            // 
                            dict->add("EDGE", ++i);          // 
                            dict->add("DETECTED", ++i);      // 
                            dict->add("DETECTED_NEGATIVE", ++i);
                            dict->add("SUSPECT", ++i);
    
    386 73fb00fd - dict->add("NO_DATA", ++i);
    } } /** * \brief Initialise mask planes; called by constructors */ template void Mask::_initializePlanes(MaskPlaneDict const& planeDefs) { pexLog::Trace("afw.Mask", 5, boost::format("Number of mask planes: %d") % getNumPlanesMax()); _maskDict = detail::MaskDict::makeMaskDict(planeDefs); } /** * \brief Construct a Mask initialized to 0x0 */ template Mask::Mask( unsigned int width, ///< number of columns unsigned int height, ///< number of rows MaskPlaneDict const& planeDefs ///< desired mask planes ) : ImageBase(afwGeom::ExtentI(width, height)) { _initializePlanes(planeDefs); *this = 0x0; } /** * \brief Construct a Mask initialized to a specified value */ template Mask::Mask( unsigned int width, ///< number of columns unsigned int height, ///< number of rows MaskPixelT initialValue, ///< Initial value MaskPlaneDict const& planeDefs ///< desired mask planes ) : ImageBase(afwGeom::ExtentI(width, height)) { _initializePlanes(planeDefs); *this = initialValue; } /** * \brief Construct a Mask initialized to 0x0 */ template Mask::Mask( afwGeom::Extent2I const & dimensions, ///< Number of columns, rows MaskPlaneDict const& planeDefs ///< desired mask planes ) : ImageBase(dimensions) { _initializePlanes(planeDefs); *this = 0x0; } /** * \brief Construct a Mask initialized to a specified value */ template Mask::Mask( afwGeom::Extent2I const & dimensions, ///< Number of columns, rows MaskPixelT initialValue, ///< Initial value MaskPlaneDict const& planeDefs ///< desired mask planes ) : ImageBase(dimensions) { _initializePlanes(planeDefs); *this = initialValue; } /** * \brief Construct a Mask initialized to 0x0 */ template Mask::Mask( afwGeom::Box2I const & bbox, ///< Desired number of columns/rows and origin MaskPlaneDict const& planeDefs ///< desired mask planes ) : ImageBase(bbox) { _initializePlanes(planeDefs); *this = 0x0; } /** * \brief Construct a Mask initialized to a specified value */ template Mask::Mask( afwGeom::Box2I const & bbox, ///< Desired number of columns/rows and origin MaskPixelT initialValue, ///< Initial value MaskPlaneDict const& planeDefs ///< desired mask planes ) : ImageBase(bbox) { _initializePlanes(planeDefs); *this = initialValue; } /** * \brief Construct a Mask from a subregion of another Mask */ template Mask::Mask( Mask const &rhs, ///< mask to copy afwGeom::Box2I const &bbox, ///< subregion to copy ImageOrigin const origin, ///< coordinate system of the bbox bool const deep ///< deep copy? (construct a view with shared pixels if false) ) : ImageBase(rhs, bbox, origin, deep), _maskDict(rhs._maskDict) { } /** * \brief Construct a Mask from another Mask */ template Mask::Mask( Mask const& rhs, ///< mask to copy bool deep ///< deep copy? (construct a view with shared pixels if false) ) : ImageBase(rhs, deep), _maskDict(rhs._maskDict) { } template Mask::Mask(ndarray::Array const & array, bool deep, geom::Point2I const & xy0) : image::ImageBase(array, deep, xy0), _maskDict(detail::MaskDict::makeMaskDict()) { } /************************************************************************************************************/ template void Mask::swap(Mask &rhs) { using std::swap; // See Meyers, Effective C++, Item 25 ImageBase::swap(rhs); swap(_maskDict, rhs._maskDict); } template void swap(Mask& a, Mask& b) { a.swap(b); } template Mask& Mask::operator=(const Mask& rhs) { Mask tmp(rhs); swap(tmp); // See Meyers, Effective C++, Item 11 return *this; } template Mask& Mask::operator=(MaskPixelT const rhs) { fill_pixels(_getRawView(), rhs); return *this; } #ifndef DOXYGEN // doc for this section is already in header template Mask::Mask( std::string const & fileName, int hdu, PTR(daf::base::PropertySet) metadata, afw::geom::Box2I const & bbox, ImageOrigin origin, bool conformMasks ) : ImageBase(), _maskDict(detail::MaskDict::makeMaskDict()) { fits::Fits fitsfile(fileName, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); fitsfile.setHdu(hdu); *this = Mask(fitsfile, metadata, bbox, origin, conformMasks); } template Mask::Mask( fits::MemFileManager & manager, int hdu, PTR(daf::base::PropertySet) metadata, afw::geom::Box2I const & bbox, ImageOrigin origin, bool conformMasks ) : ImageBase(), _maskDict(detail::MaskDict::makeMaskDict()) { fits::Fits fitsfile(manager, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); fitsfile.setHdu(hdu); *this = Mask(fitsfile, metadata, bbox, origin, conformMasks); } template Mask::Mask( fits::Fits & fitsfile, PTR(daf::base::PropertySet) metadata, afw::geom::Box2I const & bbox, ImageOrigin const origin, bool const conformMasks ) : ImageBase(), _maskDict(detail::MaskDict::makeMaskDict()) { // These are the permitted input file types typedef boost::mpl::vector< unsigned char, unsigned short, short >fits_mask_types; if (!metadata) { metadata = PTR(daf::base::PropertySet)(new daf::base::PropertyList); } fits_read_image(fitsfile, *this, *metadata, bbox, origin); // look for mask planes in the file MaskPlaneDict fileMaskDict = parseMaskPlaneMetadata(metadata); PTR(detail::MaskDict) fileMD = detail::MaskDict::makeMaskDict(fileMaskDict); if (*fileMD == *detail::MaskDict::makeMaskDict()) { // file is already consistent with Mask return; } if (conformMasks) { // adopt the definitions in the file _maskDict = detail::MaskDict::setDefaultDict(fileMD); } conformMaskPlanes(fileMaskDict); // convert planes defined by fileMaskDict to the order // defined by Mask::_maskPlaneDict } template void Mask::writeFits( std::string const & fileName, CONST_PTR(lsst::daf::base::PropertySet) metadata_i, std::string const & mode ) const { fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); writeFits(fitsfile, metadata_i); } template void Mask::writeFits( fits::MemFileManager & manager, CONST_PTR(lsst::daf::base::PropertySet) metadata_i, std::string const & mode ) const { fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); writeFits(fitsfile, metadata_i); } template void Mask::writeFits( fits::Fits & fitsfile, CONST_PTR(lsst::daf::base::PropertySet) metadata_i ) const { PTR(dafBase::PropertySet) metadata; if (metadata_i) { metadata = metadata_i->deepCopy(); } else { metadata = PTR(dafBase::PropertySet)(new dafBase::PropertyList()); } addMaskPlanesToMetadata(metadata); // // Add WCS with (X0, Y0) information // PTR(dafBase::PropertySet) wcsAMetadata = detail::createTrivialWcsAsPropertySet( detail::wcsNameForXY0, this->getX0(), this->getY0() ); metadata->combine(wcsAMetadata); fits_write_image(fitsfile, *this, metadata); } #endif // !DOXYGEN namespace { struct addPlaneFunctor { addPlaneFunctor(std::string const& name, int id) : _name(name), _id(id) {} void operator()(MapWithHash *dict) { detail::MaskPlaneDict::const_iterator const it = // is id already used in this Mask? std::find_if(dict->begin(), dict->end(), boost::bind(std::equal_to(), boost::bind(&detail::MaskPlaneDict::value_type::second, _1), _id)); if (it != dict->end()) { // mask plane is already in use return; } if (dict->find(_name) == dict->end()) { // not already set dict->add(_name, _id); } } std::string const& _name; int _id; }; } template std::string Mask::interpret(MaskPixelT value) { std::string result = ""; MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict(); for (MaskPlaneDict::const_iterator iter = mpd.begin(); iter != mpd.end(); ++iter) { if (value & getBitMask(iter->second)) { if (result.size() > 0) { result += ","; } result += iter->first; } } return result; } template int Mask::addMaskPlane(const std::string& name) { int id = getMaskPlaneNoThrow(name); // see if the plane is already available if (id < 0) { // doesn't exist id = _maskPlaneDict()->getUnusedPlane(); } // build new entry, adding the plane to all Masks where this is no contradiction if (id >= getNumPlanesMax()) { // Max number of planes is already allocated
    711 1f972da5 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException,
    ? ---------
    710 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError,
    str(boost::format("Max number of planes (%1%) already used") % getNumPlanesMax())); } _state.forEachMaskDict(addPlaneFunctor(name, id)); return id; } /** * \brief set the name of a mask plane, with minimal checking. * * This is a private function and is mainly used by setMaskPlaneMetadata */ template int Mask::addMaskPlane( std::string name, ///< new name of mask plane int planeId ///< ID of mask plane to be (re)named ) { if (planeId < 0 || planeId >= getNumPlanesMax()) {
    731 1f972da5 - throw LSST_EXCEPT(pexExcept::RangeErrorException,
    ? ---------
    730 21597d88 + throw LSST_EXCEPT(pexExcept::RangeError,
    str(boost::format("mask plane ID must be between 0 and %1%") % (getNumPlanesMax() - 1))); } _maskPlaneDict()->add(name, planeId); return planeId; } /** * Return the Mask's maskPlaneDict */ template detail::MaskPlaneDict const& Mask::getMaskPlaneDict() const { return _maskDict->getMaskPlaneDict(); } template void Mask::removeMaskPlane(const std::string& name) { if (detail::MaskDict::makeMaskDict()->getMaskPlane(name) < 0) {
    754 1805122f - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    753 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ str(boost::format("Plane %s doesn't exist in the default Mask") % name)); } detail::MaskDict::incrDefaultVersion(); // leave current Masks alone _maskPlaneDict()->erase(name); } /** * \brief Clear all pixels of the specified mask and remove the plane from the mask plane dictionary; * optionally remove the plane from the default dictionary too *
    766 0db2729c - * @throw lsst::pex::exceptions::InvalidParameterException if plane is invalid
    ? ^^^^^^ ^
    765 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if plane is invalid
    ? ^^ ^ */ template void Mask::removeAndClearMaskPlane(const std::string& name, ///< name of maskplane bool const removeFromDefault ///< remove from default ///< mask plane dictionary too ) { clearMaskPlane(getMaskPlane(name)); // clear this bits in this Mask if (_maskDict == detail::MaskDict::makeMaskDict() && removeFromDefault) { // we are the default ; } else { _maskDict = _maskDict->clone(); } _maskDict->erase(name); if (removeFromDefault && detail::MaskDict::makeMaskDict()->getMaskPlane(name) >= 0) { removeMaskPlane(name); } } /** * \brief Return the bitmask corresponding to a plane ID, or 0 if invalid */ template MaskPixelT Mask::getBitMaskNoThrow(int planeId) { return (planeId >= 0 && planeId < getNumPlanesMax()) ? (1 << planeId) : 0; } /** * \brief Return the bitmask corresponding to plane ID *
    800 1f972da5 - * @throw lsst::pex::exceptions::InvalidParameterException if plane is invalid
    ? ^^^^^^ ^
    799 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if plane is invalid
    ? ^^ ^ */ template MaskPixelT Mask::getBitMask(int planeId) { MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict(); for (MaskPlaneDict::const_iterator i = mpd.begin(); i != mpd.end(); ++i) { if (planeId == i->second) { MaskPixelT const bitmask = getBitMaskNoThrow(planeId); if (bitmask == 0) { // failed break; } return bitmask; } }
    815 1f972da5 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    814 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ str(boost::format("Invalid mask plane ID: %d") % planeId)); } /** * \brief Return the mask plane number corresponding to a plane name *
    822 1f972da5 - * @throw lsst::pex::exceptions::InvalidParameterException if plane is invalid
    ? ^^^^^^ ^
    821 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if plane is invalid
    ? ^^ ^ */ template int Mask::getMaskPlane(const std::string& name) { int const plane = getMaskPlaneNoThrow(name); if (plane < 0) {
    829 1f972da5 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    828 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ str(boost::format("Invalid mask plane name: %s") % name)); } else { return plane; } } /** * \brief Return the mask plane number corresponding to a plane name, or -1 if not found */ template int Mask::getMaskPlaneNoThrow(const std::string& name) { return _maskPlaneDict()->getMaskPlane(name); } /** * \brief Return the bitmask corresponding to a plane name *
    847 1f972da5 - * @throw lsst::pex::exceptions::InvalidParameterException if plane is invalid
    ? ^^^^^^ ^
    846 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if plane is invalid
    ? ^^ ^ */ template MaskPixelT Mask::getPlaneBitMask(const std::string& name) { return getBitMask(getMaskPlane(name)); } /** * \brief Return the bitmask corresponding to a vector of plane names OR'd together *
    857 c2f6c2df - * @throw lsst::pex::exceptions::InvalidParameterException if plane is invalid
    ? ^^^^^^ ^
    856 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if plane is invalid
    ? ^^ ^ */ template MaskPixelT Mask::getPlaneBitMask(const std::vector &name) { MaskPixelT mpix = 0x0; for (std::vector::const_iterator it = name.begin(); it != name.end(); ++it) { mpix |= getBitMask(getMaskPlane(*it)); } return mpix; } /** * \brief Reset the maskPlane dictionary */ template int Mask::getNumPlanesUsed() { return _maskPlaneDict()->size(); } /** * \brief Reset the maskPlane dictionary */ template void Mask::clearMaskPlaneDict() { _maskPlaneDict()->clear(); } /** * \brief Clear all the pixels */ template void Mask::clearAllMaskPlanes() { *this = 0; } /** * \brief Clear the specified bit in all pixels */ template void Mask::clearMaskPlane(int planeId) { *this &= ~getBitMask(planeId); } /** * \brief Adjust this mask to conform to the standard Mask class's mask plane dictionary, * adding any new mask planes to the standard. * * Ensures that this mask (presumably from some external source) has the same plane assignments * as the Mask class. If a change in plane assignments is needed, the bits within each pixel * are permuted as required. The provided currentPlaneDict describes the true state of the bits * in this Mask's pixels and overrides its current MaskDict * * Any new mask planes found in this mask are added to unused slots in the Mask class's mask plane dictionary. */ template void Mask::conformMaskPlanes( MaskPlaneDict const ¤tPlaneDict ///< mask plane dictionary currently in use for this mask ) { PTR(detail::MaskDict) currentMD = detail::MaskDict::makeMaskDict(currentPlaneDict); if (*_maskDict == *currentMD) { if (*detail::MaskDict::makeMaskDict() == *_maskDict) { return; // nothing to do } } else { // // Find out which planes need to be permuted // MaskPixelT keepBitmask = 0; // mask of bits to keep MaskPixelT canonicalMask[sizeof(MaskPixelT)*8]; // bits in lsst::afw::image::Mask that should be MaskPixelT currentMask[sizeof(MaskPixelT)*8]; // mapped to these bits int numReMap = 0; for (MaskPlaneDict::const_iterator i = currentPlaneDict.begin(); i != currentPlaneDict.end() ; i++) { std::string const name = i->first; // name of mask plane int const currentPlaneNumber = i->second; // plane number currently in use int canonicalPlaneNumber = getMaskPlaneNoThrow(name); // plane number in lsst::afw::image::Mask if (canonicalPlaneNumber < 0) { // no such plane; add it canonicalPlaneNumber = addMaskPlane(name); } if (canonicalPlaneNumber == currentPlaneNumber) { keepBitmask |= getBitMask(canonicalPlaneNumber); // bit is unchanged, so preserve it } else { canonicalMask[numReMap] = getBitMask(canonicalPlaneNumber); currentMask[numReMap] = getBitMaskNoThrow(currentPlaneNumber); numReMap++; } } // Now loop over all pixels in Mask if (numReMap > 0) { for (int r = 0; r != this->getHeight(); ++r) { // "this->": Meyers, Effective C++, Item 43 for (typename Mask::x_iterator ptr = this->row_begin(r), end = this->row_end(r); ptr != end; ++ptr) { MaskPixelT const pixel = *ptr; MaskPixelT newPixel = pixel & keepBitmask; // value of invariant mask bits for (int i = 0; i < numReMap; i++) { if (pixel & currentMask[i]) newPixel |= canonicalMask[i]; } *ptr = newPixel; } } } } // We've made the planes match the current mask dictionary _maskDict = detail::MaskDict::makeMaskDict(); } /************************************************************************************************************/ /** * \brief get a reference to the specified pixel */ template typename ImageBase::PixelReference Mask::operator()( int x, ///< x index int y ///< y index ) { return this->ImageBase::operator()(x, y); } /** * \brief get a reference to the specified pixel checking array bounds */ template typename ImageBase::PixelReference Mask::operator()( int x, ///< x index int y, ///< y index CheckIndices const& check ///< Check array bounds? ) { return this->ImageBase::operator()(x, y, check); } /** * \brief get the specified pixel (const version) */ template typename ImageBase::PixelConstReference Mask::operator()( int x, ///< x index int y ///< y index ) const { return this->ImageBase::operator()(x, y); } /** * \brief get the specified pixel with array checking (const version) */ template typename ImageBase::PixelConstReference Mask::operator()( int x, ///< x index int y, ///< y index CheckIndices const& check ///< Check array bounds? ) const { return this->ImageBase::operator()(x, y, check); } /** * \brief is the specified mask plane set in the specified pixel? */ template bool Mask::operator()( int x, ///< x index int y, ///< y index int planeId ///< plane ID ) const { // !! converts an int to a bool return !!(this->ImageBase::operator()(x, y) & getBitMask(planeId)); } /** * \brief is the specified mask plane set in the specified pixel, checking array bounds? */ template bool Mask::operator()( int x, ///< x index int y, ///< y index int planeId, ///< plane ID CheckIndices const& check ///< Check array bounds? ) const { // !! converts an int to a bool return !!(this->ImageBase::operator()(x, y, check) & getBitMask(planeId)); } /************************************************************************************************************/ // // Check that masks have the same dictionary version //
    1050 73f9fedf - // @throw lsst::pex::exceptions::RuntimeErrorException
    ? ---------
    1049 21597d88 + // @throw lsst::pex::exceptions::RuntimeError
    // template void Mask::checkMaskDictionaries(Mask const &other) { if (*_maskDict != *other._maskDict) {
    1055 220a43b0 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Mask dictionaries do not match");
    ? ---------
    1054 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Mask dictionaries do not match");
    } } /************************************************************************************************************/ // // N.b. We could use the STL, but I find boost::lambda clearer, and more easily extended // to e.g. setting random numbers // transform_pixels(_getRawView(), _getRawView(), lambda::ret(lambda::_1 + val)); // is equivalent to // transform_pixels(_getRawView(), _getRawView(), std::bind2nd(std::plus(), val)); // namespace bl = boost::lambda; /** * \brief OR a bitmask into a Mask */ template void Mask::operator|=(MaskPixelT const val) { transform_pixels(_getRawView(), _getRawView(), bl::ret(bl::_1 | val)); } /** * \brief OR a Mask into a Mask */ template void Mask::operator|=(Mask const &rhs) { checkMaskDictionaries(rhs); if (this->getDimensions() != rhs.getDimensions()) {
    1085 73f9fedf - throw LSST_EXCEPT(pexExcept::LengthErrorException,
    ? ---------
    1084 21597d88 + throw LSST_EXCEPT(pexExcept::LengthError,
    str(boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight())); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 | bl::_2)); } /** * \brief AND a bitmask into a Mask */ template void Mask::operator&=(MaskPixelT const val) { transform_pixels(_getRawView(), _getRawView(), bl::ret(bl::_1 & val)); } /** * \brief AND a Mask into a Mask */ template void Mask::operator&=(Mask const &rhs) { checkMaskDictionaries(rhs); if (this->getDimensions() != rhs.getDimensions()) {
    1108 73f9fedf - throw LSST_EXCEPT(pexExcept::LengthErrorException,
    ? ---------
    1107 21597d88 + throw LSST_EXCEPT(pexExcept::LengthError,
    str(boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight())); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 & bl::_2)); } /** * \brief XOR a bitmask into a Mask */ template void Mask::operator^=(MaskPixelT const val) { transform_pixels(_getRawView(), _getRawView(), bl::ret(bl::_1 ^ val)); } /** * \brief XOR a Mask into a Mask */ template void Mask::operator^=(Mask const &rhs) { checkMaskDictionaries(rhs); if (this->getDimensions() != rhs.getDimensions()) {
    1131 73f9fedf - throw LSST_EXCEPT(pexExcept::LengthErrorException,
    ? ---------
    1130 21597d88 + throw LSST_EXCEPT(pexExcept::LengthError,
    str(boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight())); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 ^ bl::_2)); } /** * \brief Set the bit specified by "planeId" for pixels (x0, y) ... (x1, y) */ template void Mask::setMaskPlaneValues(int const planeId, int const x0, int const x1, int const y) { MaskPixelT const bitMask = getBitMask(planeId); for (int x = x0; x <= x1; x++) { operator()(x, y) = operator()(x, y) | bitMask; } } /** * \brief Given a PropertySet, replace any existing MaskPlane assignments with the current ones. */ template void Mask::addMaskPlanesToMetadata(PTR(dafBase::PropertySet) metadata) { if (!metadata) {
    1157 73f9fedf - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "Null PTR(PropertySet)");
    ? ^^^^^^ ^
    1156 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "Null PTR(PropertySet)");
    ? ^^ ^ } // First, clear existing MaskPlane metadata typedef std::vector NameList; NameList paramNames = metadata->paramNames(false); for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) { if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) { metadata->remove(*i); } } MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict(); // Add new MaskPlane metadata for (MaskPlaneDict::const_iterator i = mpd.begin(); i != mpd.end() ; ++i) { std::string const& planeName = i->first; int const planeNumber = i->second; if (planeName != "") { metadata->add(maskPlanePrefix + planeName, planeNumber); } } } /** * \brief Given a PropertySet that contains the MaskPlane assignments, setup the MaskPlanes. * * @returns a dictionary of mask plane name: plane ID */ template typename Mask::MaskPlaneDict Mask::parseMaskPlaneMetadata( CONST_PTR(dafBase::PropertySet) metadata ///< metadata from a Mask ) { MaskPlaneDict newDict; // First, clear existing MaskPlane metadata typedef std::vector NameList; NameList paramNames = metadata->paramNames(false); int numPlanesUsed = 0; // number of planes used // Iterate over childless properties with names starting with maskPlanePrefix for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) { if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) { // split off maskPlanePrefix to obtain plane name std::string planeName = i->substr(maskPlanePrefix.size()); int const planeId = metadata->getAsInt(*i); MaskPlaneDict::const_iterator plane = newDict.find(planeName); if (plane != newDict.end() && planeId != plane->second) {
    1207 f71e754e - throw LSST_EXCEPT(pexExcept::RuntimeErrorException,
    ? ---------
    1206 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError,
    "File specifies plane " + planeName + " twice"); } for (MaskPlaneDict::const_iterator j = newDict.begin(); j != newDict.end(); ++j) { if (planeId == j->second) {
    1212 1f972da5 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException,
    ? ---------
    1211 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError,
    str(boost::format("File specifies plane %s has same value (%d) as %s") % planeName % planeId % j->first)); } } // build new entry if (numPlanesUsed >= getNumPlanesMax()) { // Max number of planes already allocated
    1220 1f972da5 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException,
    ? ---------
    1219 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError,
    str(boost::format("Max number of planes (%1%) already used") % getNumPlanesMax())); } newDict[planeName] = planeId; } } return newDict; } /** * \brief print the mask plane dictionary to std::cout */ template void Mask::printMaskPlanes() const { _maskDict->print(); } /* * Static members of Mask */ template std::string const Mask::maskPlanePrefix("MP_"); template PTR(detail::MaskDict) Mask::_maskPlaneDict() { return detail::MaskDict::makeMaskDict(); } // // Explicit instantiations // template class Mask; }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    73f9fedf

    commit 73f9fedfafe2d92cb38544ce44d702502c954e93
    Author: Robert Lupton the Good 
    Date:   Wed Jan 4 17:42:39 2012 -0500
    
        Reopen afw::image namespace
        Misc namespace cleanup
    

    0db2729c

    commit 0db2729c943e400b3d741354fd8399f7fdde3431
    Author: Robert Lupton the Good 
    Date:   Thu Dec 22 15:06:34 2011 -0500
    
        Initial version that compiles with MaskDict implementation of private Mask dictionaries
    

    1805122f

    commit 1805122ff4ab1ee6379f9052d8941e99c02c9c41
    Author: Robert Lupton the Good 
    Date:   Wed Jan 4 18:03:29 2012 -0500
    
        Throw an exception if you try to remove a non-existent mask plane
    

    f71e754e

    commit f71e754e94ef1255adfb894a6e268f021e1b1051
    Merge: 89fc0ab 8c6c0d9
    Author: bick 
    Date:   Sat Jan 9 21:32:23 2010 +0000
    
        #1113 Merging afw clean-up onto afw trunk
    

    1f972da5

    commit 1f972da547164cdb29162286ebe0df8f7bf5f752
    Author: rowen 
    Date:   Thu Jan 7 19:01:43 2010 +0000
    
        Added many missing Doxygen comments and converted some existing non-Doxygen comments.
        Shortened too-long lines and generally cleaned up the code.
    

    73fb00fd

    commit 73fb00fd8b3533247dad52e9a46e2470b77fe48f
    Author: Paul Price 
    Date:   Thu May 22 11:08:42 2014 -0400
    
        add NO_DATA mask plane, and use in warping/convolution
        
        The EDGE mask plane was originally intended to mean "pixel near the
        edge of the detector, so we haven't been able to properly convolve to
        search for sources", but it was hijacked to mean "pixels in a warped
        image that are off the edge of the original".  It has since had both
        meanings, which should be distinct.
        
        We introduce the NO_DATA mask plane to mean "pixels off the edge of
        the original", and reserve "EDGE" to mean "pixels near the edge".
        afw::math::edgePixel (used for pixels with no good inputs when
        warping) now returns a value for pixels *off* the edge (should it
        be renamed? but that's changing a public API).  Convolution now
        masks pixels near the edge as EDGE if copying edge pixels, and
        NO_DATA otherwise.
    

    220a43b0

    commit 220a43b0b7c46f6f3d427ec173aa6e69cc22ecbe
    Author: Robert Lupton the Good 
    Date:   Mon Apr 9 22:09:18 2012 -0400
    
        Serge/KT point out that we don't need Id numbers for Dicts.
        They were used for debugging once upon a time, but are no longer needed
    

    c2f6c2df

    commit c2f6c2df70fb91614e9055cf576318f10e5803e1
    Author: bick 
    Date:   Wed Feb 16 20:28:16 2011 +0000
    
        #1570 made changes to Shape to accommodate new outputs from HSM code.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/math/detail/ConvolveWithInterpolation.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file
                     *
                     * @brief Definition of convolveWithInterpolation and helper functions declared in detail/ConvolveImage.h
                     *
                     * @author Russell Owen
                     *
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/cstdint.hpp" 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/math/detail/Convolve.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace pexLog = lsst::pex::logging;
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwImage = lsst::afw::image;
                    namespace afwMath = lsst::afw::math;
                    namespace mathDetail = lsst::afw::math::detail;
                    
                    /**
                     * @brief Convolve an Image or MaskedImage with a spatially varying Kernel using linear interpolation.
                     *
                     * This is a low-level convolution function that does not set edge pixels.
                     *
                     * The algorithm is as follows:
                     * - divide the image into regions whose size is no larger than maxInterpolationDistance
                     * - for each region:
                     *   - convolve it using convolveRegionWithInterpolation (which see)
                     *
                     * Note that this routine will also work with spatially invariant kernels, but not efficiently.
                     *
    
    68 d7d666c2 - * @throw lsst::pex::exceptions::InvalidParameterException if outImage is not the same size as inImage
    ? ^^^^^^ ^
    68 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if outImage is not the same size as inImage
    ? ^^ ^ */ template void mathDetail::convolveWithInterpolation( OutImageT &outImage, ///< convolved image = inImage convolved with kernel InImageT const &inImage, ///< input image lsst::afw::math::Kernel const &kernel, ///< convolution kernel lsst::afw::math::ConvolutionControl const &convolutionControl) ///< convolution control parameters { if (outImage.getDimensions() != inImage.getDimensions()) { std::ostringstream os; os << "outImage dimensions = ( " << outImage.getWidth() << ", " << outImage.getHeight() << ") != (" << inImage.getWidth() << ", " << inImage.getHeight() << ") = inImage dimensions";
    82 d7d666c2 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    82 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } // compute region covering good area of output image afwGeom::Box2I fullBBox = afwGeom::Box2I( afwGeom::Point2I(0, 0), afwGeom::Extent2I(outImage.getWidth(), outImage.getHeight())); afwGeom::Box2I goodBBox = kernel.shrinkBBox(fullBBox); KernelImagesForRegion goodRegion(KernelImagesForRegion( kernel.clone(), goodBBox, inImage.getXY0(), convolutionControl.getDoNormalize())); pexLog::TTrace<6>("lsst.afw.math.convolve", "convolveWithInterpolation: full bbox minimum=(%d, %d), extent=(%d, %d)", fullBBox.getMinX(), fullBBox.getMinY(), fullBBox.getWidth(), fullBBox.getHeight()); pexLog::TTrace<6>("lsst.afw.math.convolve", "convolveWithInterpolation: goodRegion bbox minimum=(%d, %d), extent=(%d, %d)", goodRegion.getBBox().getMinX(), goodRegion.getBBox().getMinY(), goodRegion.getBBox().getWidth(), goodRegion.getBBox().getHeight()); // divide good region into subregions small enough to interpolate over int nx = 1 + (goodBBox.getWidth() / convolutionControl.getMaxInterpolationDistance()); int ny = 1 + (goodBBox.getHeight() / convolutionControl.getMaxInterpolationDistance()); pexLog::TTrace<4>("lsst.afw.math.convolve", "convolveWithInterpolation: divide into %d x %d subregions", nx, ny); ConvolveWithInterpolationWorkingImages workingImages(kernel.getDimensions()); RowOfKernelImagesForRegion regionRow(nx, ny); while (goodRegion.computeNextRow(regionRow)) { for (RowOfKernelImagesForRegion::ConstIterator rgnIter = regionRow.begin(), rgnEnd = regionRow.end(); rgnIter != rgnEnd; ++rgnIter) { pexLog::TTrace<6>("lsst.afw.math.convolve", "convolveWithInterpolation: bbox minimum=(%d, %d), extent=(%d, %d)", (*rgnIter)->getBBox().getMinX(), (*rgnIter)->getBBox().getMinY(), (*rgnIter)->getBBox().getWidth(), (*rgnIter)->getBBox().getHeight()); convolveRegionWithInterpolation(outImage, inImage, **rgnIter, workingImages); } } } /** * @brief Convolve a region of an Image or MaskedImage with a spatially varying Kernel using interpolation. * * This is a low-level convolution function that does not set edge pixels. * * @warning: this is a low-level routine that performs no bounds checking. */ template void mathDetail::convolveRegionWithInterpolation( OutImageT &outImage, ///< convolved image = inImage convolved with kernel InImageT const &inImage, ///< input image KernelImagesForRegion const ®ion, ///< kernel image region over which to convolve ConvolveWithInterpolationWorkingImages &workingImages) ///< working kernel images { typedef typename OutImageT::xy_locator OutLocator; typedef typename InImageT::const_xy_locator InConstLocator; typedef KernelImagesForRegion::Image KernelImage; typedef KernelImage::const_xy_locator KernelConstLocator; CONST_PTR(afwMath::Kernel) kernelPtr = region.getKernel(); geom::Extent2I const kernelDimensions(kernelPtr->getDimensions()); workingImages.leftImage <<= *region.getImage(KernelImagesForRegion::BOTTOM_LEFT); workingImages.rightImage <<= *region.getImage(KernelImagesForRegion::BOTTOM_RIGHT); workingImages.kernelImage <<= workingImages.leftImage; afwGeom::Box2I const goodBBox = region.getBBox(); afwGeom::Box2I const fullBBox = kernelPtr->growBBox(goodBBox); // top and right images are computed one beyond bbox boundary, // so the distance between edge images is bbox width/height pixels double xfrac = 1.0 / static_cast(goodBBox.getWidth()); double yfrac = 1.0 / static_cast(goodBBox.getHeight()); afwMath::scaledPlus(workingImages.leftDeltaImage, yfrac, *region.getImage(KernelImagesForRegion::TOP_LEFT), -yfrac, workingImages.leftImage); afwMath::scaledPlus(workingImages.rightDeltaImage, yfrac, *region.getImage(KernelImagesForRegion::TOP_RIGHT), -yfrac, workingImages.rightImage); KernelConstLocator const kernelLocator = workingImages.kernelImage.xy_at(0, 0); // The loop is a bit odd for efficiency: the initial value of workingImages.kernelImage // and related kernel images are set when they are allocated, // so they are not computed in the loop until after the convolution; to save cpu cycles // they are not computed at all for the last iteration. InConstLocator inLocator = inImage.xy_at(fullBBox.getMinX(), fullBBox.getMinY()); OutLocator outLocator = outImage.xy_at(goodBBox.getMinX(), goodBBox.getMinY()); for (int j = 0; ; ) { afwMath::scaledPlus( workingImages.deltaImage, xfrac, workingImages.rightImage, -xfrac, workingImages.leftImage); for (int i = 0; ; ) { *outLocator = afwMath::convolveAtAPoint( inLocator, kernelLocator, kernelDimensions.getX(), kernelDimensions.getY()); ++outLocator.x(); ++inLocator.x(); ++i; if (i >= goodBBox.getWidth()) { break; } workingImages.kernelImage += workingImages.deltaImage; } ++j; if (j >= goodBBox.getHeight()) { break; } workingImages.leftImage += workingImages.leftDeltaImage; workingImages.rightImage += workingImages.rightDeltaImage; workingImages.kernelImage <<= workingImages.leftImage; inLocator += lsst::afw::image::detail::difference_type(-goodBBox.getWidth(), 1); outLocator += lsst::afw::image::detail::difference_type(-goodBBox.getWidth(), 1); } } /* * Explicit instantiation */ /// \cond #define IMAGE(PIXTYPE) afwImage::Image #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage #define NL /* */ // Instantiate Image or MaskedImage versions #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \ template void mathDetail::convolveWithInterpolation( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::Kernel const&, \ afwMath::ConvolutionControl const&); NL \ template void mathDetail::convolveRegionWithInterpolation( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, KernelImagesForRegion const&, \ ConvolveWithInterpolationWorkingImages&); // Instantiate both Image and MaskedImage versions #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE) INSTANTIATE(double, double) INSTANTIATE(double, float) INSTANTIATE(double, int) INSTANTIATE(double, boost::uint16_t) INSTANTIATE(float, float) INSTANTIATE(float, int) INSTANTIATE(float, boost::uint16_t) INSTANTIATE(int, int) INSTANTIATE(boost::uint16_t, boost::uint16_t) /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d7d666c2

    commit d7d666c2df0fb12062dc69c1390aa702949f8908
    Author: rowen 
    Date:   Wed Apr 21 22:11:17 2010 +0000
    
        Mostly implemented. Still to do:
        - wire the new code up to the convolve or basicConvolve functions
        - implement brute force convolution case in convolveRegionWithRecursiveInterpolation
        - swig the new code
        - unit tests
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/footprintEllipse.py

    Diff:

    1 adb291a2 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import math import unittest import lsst.utils.tests as tests import lsst.afw.geom as afwGeom
    30 adb291a2 - import lsst.afw.geom.ellipses as afwGeomEllipses
    31 adb291a2 - import lsst.afw.image as afwImage
    32 adb291a2 - import lsst.afw.math as afwMath
    import lsst.afw.detection as afwDet class FootprintTestCase(unittest.TestCase): def testCircle(self): xc, yc = 30, 50 radius = 10 test = afwDet.Footprint(afwGeom.Point2I(xc, yc), radius) # Here's how it used to be done using circles, before #1556 r2 = int(radius**2 + 0.5) r = int(math.sqrt(r2)) control = afwDet.Footprint() for i in range(-r, r+1): hlen = int(math.sqrt(r2 - i**2)) control.addSpan(yc + i, xc - hlen, xc + hlen) self.assertEqual(len(test.getSpans()), len(control.getSpans())) for s0, s1 in zip(test.getSpans(), control.getSpans()): print s0.getY(), s0.getX0(), s0.getX1(), s1.getY(), s1.getX0(), s1.getX1() self.assertEqual(s0.getX0(), s1.getX0()) self.assertEqual(s0.getX1(), s1.getX1()) self.assertEqual(s0.getY(), s1.getY()) self.assertEqual(test.getNpix(), control.getNpix()) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" tests.init() suites = [] suites += unittest.makeSuite(FootprintTestCase) suites += unittest.makeSuite(tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    adb291a2

    commit adb291a2d231ba8c9898cf961fb50b43042c6d9f
    Author: price 
    Date:   Wed Apr 13 21:06:26 2011 +0000
    
        Adding test to catch change in behaviour of Footprint generation from an Ellipse.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    tests/spline.py

    Diff:

    1 66ed4513 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Splines Run with: ./spline.py or python >>> import spline; spline.run() """
    35 66ed4513 - import math, os, sys
    36 b80fe1d3 + import math
    import unittest import lsst.utils.tests as utilsTests
    39 66ed4513 - import lsst.pex.exceptions
    40 66ed4513 - import lsst.daf.base
    41 66ed4513 - import lsst.afw.image as afwImage
    import lsst.afw.math as afwMath
    43 66ed4513 - import eups
    44 66ed4513 - import lsst.afw.display.ds9 as ds9
    try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class SplineTestCase(unittest.TestCase): """A test case for Image""" def smooth(self, x, differentiate=False): if differentiate: return math.cos(x) else: return math.sin(x) def noDerivative(self, x): if False: return math.sin(x) else: if x < 1: return 1 - x else: return 0 def setUp(self): x, x2, ySin, yND = [], [], [], [] for i in range(0,40): x.append(0.1*i) for j in range(4): x2.append(0.1*(i + 0.25*j)) ySin.append(self.smooth(x[i])) yND.append(self.noDerivative(x[i])) self.x = x self.x2 = x2 self.yND = yND self.ySin = ySin def tearDown(self): del self.x del self.x2 del self.ySin del self.yND def testNaturalSpline1(self): """Test fitting a natural spline to a smooth function""" gamma = 0 sp = afwMath.TautSpline(self.x, self.ySin, gamma) y2 = afwMath.vectorD() sp.interpolate(self.x2, y2) for x, y in zip(self.x2, y2): self.assertAlmostEqual(y, self.smooth(x), 1) # fails at 2 places! def testNaturalSplineDerivative1(self): """Test fitting a natural spline to a smooth function and finding its derivative""" sp = afwMath.TautSpline(self.x, self.ySin) y2 = afwMath.vectorD() sp.derivative(self.x2, y2) for x, y in zip(self.x2, y2): self.assertTrue(abs(y - self.smooth(x, True)) < 1.5e-3) def testNaturalSpline2(self): """Test fitting a natural spline to a non-differentiable function (we basically fail)""" gamma = 0 sp = afwMath.TautSpline(self.x, self.yND, gamma) y2 = afwMath.vectorD() sp.interpolate(self.x2, y2) for x, y in zip(self.x2, y2): self.assertAlmostEqual(y, self.noDerivative(x), 1) # fails at 2 places! def testTautSpline1(self): """Test fitting a taut spline to a smooth function""" gamma = 2.5 sp = afwMath.TautSpline(self.x, self.ySin, gamma) y2 = afwMath.vectorD() sp.interpolate(self.x2, y2) for x, y in zip(self.x2, y2): self.assertAlmostEqual(y, self.smooth(x), 4) def testTautSpline2(self): """Test fitting a taut spline to a non-differentiable function""" gamma = 2.5 sp = afwMath.TautSpline(self.x, self.yND, gamma) y2 = afwMath.vectorD() sp.interpolate(self.x2, y2) for x, y in zip(self.x2, y2): self.assertAlmostEqual(y, self.noDerivative(x)) def testRootFinding(self): """Test finding roots of Spline = value""" gamma = 2.5 sp = afwMath.TautSpline(self.x, self.yND, gamma) for value in (0.1, 0.5): self.assertEqual(sp.roots(value, self.x[0], self.x[-1])[0], 1 - value) if False: y = afwMath.vectorD() sp.interpolate(self.x, y) for x, y in zip(self.x, y): print x, y # # Solve sin(x) = 0.5 # sp = afwMath.TautSpline(self.x, self.ySin) roots = [math.degrees(x) for x in sp.roots(0.5, self.x[0], self.x[-1])] self.assertAlmostEqual(roots[0], 30, 5) self.assertAlmostEqual(roots[1], 150, 5) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(SplineTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    66ed4513

    commit 66ed4513d2f8b9dd0faec6fedfa3403b844786b5
    Author: rhl 
    Date:   Thu Feb 17 22:52:59 2011 +0000
    
        Added Spline code from SDSS.  Needs to be integrated into Interpolate, but this is currently too explicitly gsl-based
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    tests/warpExposure.py

    Diff:

    1 db7df6ad - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """Test warpExposure """ import math import os import unittest import numpy
    33 db7df6ad - import eups
    34 7cbb2bb9 + import lsst.utils
    import lsst.daf.base as dafBase import lsst.afw.coord as afwCoord import lsst.afw.geom as afwGeom import lsst.afw.gpu as afwGpu import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.image.utils as imageUtils import lsst.afw.image.testUtils as imageTestUtils import lsst.utils.tests as utilsTests import lsst.pex.logging as pexLog import lsst.pex.policy as pexPolicy import lsst.pex.exceptions as pexExcept import lsst.afw.display.ds9 as ds9 try: display except: display = False VERBOSITY = 0 # increase to see trace # set True to save afw-warped images as FITS files SAVE_FITS_FILES = False # set True to save failed afw-warped images as FITS files even if SAVE_FITS_FILES is False #SAVE_FAILED_FITS_FILES = False SAVE_FAILED_FITS_FILES = True pexLog.Debug("lsst.afw.math", VERBOSITY)
    61 7cbb2bb9 + afwDataDir = lsst.utils.getPackageDir("afwdata")
    60 f594298d - afwDataDir = eups.productDir("afwdata")
    61 f594298d - if not afwDataDir:
    62 db7df6ad - raise RuntimeError("Must set up afwdata to run these tests")
    dataDir = os.path.join(afwDataDir, "data") originalExposureName = "medexp.fits" originalExposurePath = os.path.join(dataDir, originalExposureName) subExposureName = "medsub.fits" subExposurePath = os.path.join(dataDir, originalExposureName) originalFullExposureName = os.path.join("CFHT", "D4", "cal-53535-i-797722_1.fits") originalFullExposurePath = os.path.join(dataDir, originalFullExposureName) def makeWcs(pixelScale, crPixPos, crValCoord, posAng=afwGeom.Angle(0.0), doFlipX=False, projection="TAN"): """Make a Wcs @param[in] pixelScale: desired scale, as sky/pixel, an afwGeom.Angle @param[in] crPixPos: crPix for WCS, using the LSST standard; a pair of floats @param[in] crValCoord: crVal for WCS (afwCoord.Coord) @param[in] posAng: position angle (afwGeom.Angle) @param[in] doFlipX: flip X axis? @param[in] projection: WCS projection (e.g. "TAN" or "STG") """ if len(projection) != 3: raise RuntimeError("projection=%r; must have length 3" % (projection,)) ctypeList = [("%-5s%3s" % (("RA", "DEC")[i], projection)).replace(" ", "-") for i in range(2)] ps = dafBase.PropertySet() crPixFits = [ind + 1.0 for ind in crPixPos] # convert pix position to FITS standard crValDeg = crValCoord.getPosition(afwGeom.degrees) posAngRad = posAng.asRadians() pixelScaleDeg = pixelScale.asDegrees() cdMat = numpy.array([[ math.cos(posAngRad), math.sin(posAngRad)], [-math.sin(posAngRad), math.cos(posAngRad)]], dtype=float) * pixelScaleDeg if doFlipX: cdMat[:,0] = -cdMat[:,0] for i in range(2): ip1 = i + 1 ps.add("CTYPE%1d" % (ip1,), ctypeList[i]) ps.add("CRPIX%1d" % (ip1,), crPixFits[i]) ps.add("CRVAL%1d" % (ip1,), crValDeg[i]) ps.add("RADECSYS", "ICRS") ps.add("EQUINOX", 2000) ps.add("CD1_1", cdMat[0, 0]) ps.add("CD2_1", cdMat[1, 0]) ps.add("CD1_2", cdMat[0, 1]) ps.add("CD2_2", cdMat[1, 1]) return afwImage.makeWcs(ps) class WarpExposureTestCase(unittest.TestCase): """Test case for warpExposure """ def testNullWarpExposure(self, interpLength=10): """Test that warpExposure maps an image onto itself. Note: - edge pixels must be ignored - bad mask pixels get smeared out so we have to excluded all bad mask pixels from the output image when comparing masks. """ filterPolicyFile = pexPolicy.DefaultPolicyFile("afw", "SdssFilters.paf", "tests") filterPolicy = pexPolicy.Policy.createPolicy(filterPolicyFile, filterPolicyFile.getRepositoryPath(), True) imageUtils.defineFiltersFromPolicy(filterPolicy, reset=True) originalExposure = afwImage.ExposureF(originalExposurePath) originalFilter = afwImage.Filter("i") originalCalib = afwImage.Calib() originalCalib.setFluxMag0(1.0e5, 1.0e3) originalExposure.setFilter(originalFilter) originalExposure.setCalib(originalCalib) afwWarpedExposure = afwImage.ExposureF(
    131 1751cb91 - originalExposure.getBBox(afwImage.PARENT),
    ? ---------------
    130 93994d54 + originalExposure.getBBox(),
    originalExposure.getWcs()) warpingControl = afwMath.WarpingControl("lanczos4", "", 0, interpLength) afwMath.warpExposure(afwWarpedExposure, originalExposure, warpingControl) if SAVE_FITS_FILES: afwWarpedExposure.writeFits("afwWarpedExposureNull.fits") self.assertEquals(afwWarpedExposure.getFilter().getName(), originalFilter.getName()) self.assertEquals(afwWarpedExposure.getCalib().getFluxMag0(), originalCalib.getFluxMag0()) afwWarpedMaskedImage = afwWarpedExposure.getMaskedImage() afwWarpedMask = afwWarpedMaskedImage.getMask()
    143 f76e1b8b - edgeBitMask = afwWarpedMask.getPlaneBitMask("NO_DATA")
    ? ^^^ ^^^
    142 84d4fa7d + edgeBitMask = afwWarpedMask.getPlaneBitMask("EDGE")
    ? ^ ^^ if edgeBitMask == 0:
    145 f76e1b8b - self.fail("warped mask has no NO_DATA bit")
    ? ^^^ ^^^
    144 84d4fa7d + self.fail("warped mask has no EDGE bit")
    ? ^ ^^ afwWarpedMaskedImageArrSet = afwWarpedMaskedImage.getArrays() afwWarpedMaskArr = afwWarpedMaskedImageArrSet[1] # compare all non-edge pixels of image and variance, but relax specs a bit # because of minor noise introduced by bad pixels edgeMaskArr = afwWarpedMaskArr & edgeBitMask originalMaskedImageArrSet = originalExposure.getMaskedImage().getArrays() errStr = imageTestUtils.maskedImagesDiffer(afwWarpedMaskedImageArrSet, originalMaskedImageArrSet, doMask=False, skipMaskArr=edgeMaskArr, atol=1e-5) if errStr: self.fail("afw null-warped MaskedImage (all pixels, relaxed tolerance): %s" % (errStr,)) # compare good pixels of image, mask and variance using full tolerance errStr = imageTestUtils.maskedImagesDiffer(afwWarpedMaskedImageArrSet, originalMaskedImageArrSet, doImage=False, doVariance=False, skipMaskArr=afwWarpedMaskArr) if errStr: self.fail("afw null-warped MaskedImage (good pixels, max tolerance): %s" % (errStr,)) def testNullWarpImage(self, interpLength=10): """Test that warpImage maps an image onto itself. """ originalExposure = afwImage.ExposureF(originalExposurePath) afwWarpedExposure = afwImage.ExposureF(originalExposurePath) originalImage = originalExposure.getMaskedImage().getImage() afwWarpedImage = afwWarpedExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() afwWarpedWcs = afwWarpedExposure.getWcs() warpingControl = afwMath.WarpingControl("lanczos4", "", 0, interpLength) afwMath.warpImage(afwWarpedImage, afwWarpedWcs, originalImage, originalWcs, warpingControl) if SAVE_FITS_FILES: afwWarpedImage.writeFits("afwWarpedImageNull.fits") afwWarpedImageArr = afwWarpedImage.getArray() edgeMaskArr = numpy.isnan(afwWarpedImageArr) originalImageArr = originalImage.getArray() # relax specs a bit because of minor noise introduced by bad pixels errStr = imageTestUtils.imagesDiffer(originalImageArr, originalImageArr, skipMaskArr=edgeMaskArr) if errStr: self.fail("afw null-warped Image: %s" % (errStr,)) def testNullWcs(self, interpLength=10): """Cannot warp from or into an exposure without a Wcs. """ exposureWithWcs = afwImage.ExposureF(originalExposurePath) mi = exposureWithWcs.getMaskedImage() exposureWithoutWcs = afwImage.ExposureF(mi.getDimensions()) warpingControl = afwMath.WarpingControl("bilinear", "", 0, interpLength) try: afwMath.warpExposure(exposureWithWcs, exposureWithoutWcs, warpingControl) self.fail("warping from a source Exception with no Wcs should fail") except Exception: pass try: afwMath.warpExposure(exposureWithoutWcs, exposureWithWcs, warpingControl) self.fail("warping into a destination Exception with no Wcs should fail") except Exception: pass def testWarpIntoSelf(self, interpLength=10): """Cannot warp in-place """ originalExposure = afwImage.ExposureF(afwGeom.Extent2I(100, 100)) warpingControl = afwMath.WarpingControl("bilinear", "", 0, interpLength) try: afwMath.warpExposure(originalExposure, originalExposure, warpingControl) self.fail("warpExposure in place (dest is src) should fail") except Exception: pass try: afwMath.warpImage(originalExposure.getMaskedImage(), originalExposure.getWcs(), originalExposure.getMaskedImage(), originalExposure.getWcs(), warpingControl) self.fail("warpImage in place (dest is src) should fail") except Exception: pass try: afwMath.warpImage(originalExposure.getImage(), originalExposure.getWcs(), originalExposure.getImage(), originalExposure.getWcs(), warpingControl) self.fail("warpImage in place (dest is src) should fail") except Exception: pass def testWarpingControl(self): """Test the basic mechanics of WarpingControl """ for interpLength in (0, 1, 52): wc = afwMath.WarpingControl("lanczos3", "", 0, interpLength) self.assertFalse(wc.hasMaskWarpingKernel()) self.assertEqual(wc.getInterpLength(), interpLength) for newInterpLength in (3, 7, 9): wc.setInterpLength(newInterpLength) self.assertEqual(wc.getInterpLength(), newInterpLength) for cacheSize in (0, 100): wc = afwMath.WarpingControl("lanczos3", "bilinear", cacheSize) self.assertTrue(wc.hasMaskWarpingKernel()) self.assertEqual(wc.getCacheSize(), cacheSize) self.assertEqual(wc.getWarpingKernel().getCacheSize(), cacheSize) self.assertEqual(wc.getMaskWarpingKernel().getCacheSize(), cacheSize) for newCacheSize in (1, 50): wc.setCacheSize(newCacheSize) self.assertEqual(wc.getCacheSize(), newCacheSize) self.assertEqual(wc.getWarpingKernel().getCacheSize(), newCacheSize) self.assertEqual(wc.getMaskWarpingKernel().getCacheSize(), newCacheSize) def testWarpingControlError(self): """Test error handling of WarpingControl """ # error: mask kernel smaller than main kernel for kernelName, maskKernelName in ( ("bilinear", "lanczos3"), ("bilinear", "lanczos4"), ("lanczos3", "lanczos4"), ):
    259 fba55aa3 - self.assertRaises(pexExcept.LsstCppException,
    ? -------
    258 6fc1c3d1 + self.assertRaises(pexExcept.Exception,
    afwMath.WarpingControl, kernelName, maskKernelName) # error: new mask kernel larger than main kernel warpingControl = afwMath.WarpingControl("bilinear") for maskKernelName in ("lanczos3", "lanczos4"):
    265 2db43632 - self.assertRaises(pexExcept.LsstCppException,
    ? -------
    264 6fc1c3d1 + self.assertRaises(pexExcept.Exception,
    warpingControl.setMaskWarpingKernelName, maskKernelName) # error: new kernel smaller than mask kernel warpingControl = afwMath.WarpingControl("lanczos4", "lanczos4") for kernelName in ("bilinear", "lanczos3"):
    271 2db43632 - self.assertRaises(pexExcept.LsstCppException,
    ? -------
    270 6fc1c3d1 + self.assertRaises(pexExcept.Exception,
    warpingControl.setWarpingKernelName, kernelName) # error: GPU only works with Lanczos kernels
    275 2db43632 - self.assertRaises(pexExcept.LsstCppException,
    ? -------
    274 6fc1c3d1 + self.assertRaises(pexExcept.Exception,
    afwMath.WarpingControl, "bilinear", "", 0, 0, afwGpu.USE_GPU) warpingControl = afwMath.WarpingControl("bilinear")
    278 2db43632 - self.assertRaises(pexExcept.LsstCppException,
    ? -------
    277 6fc1c3d1 + self.assertRaises(pexExcept.Exception,
    warpingControl.setDevicePreference, afwGpu.USE_GPU) # OK: GPU works with Lanczos kernels for kernelName in ("lanczos3", "lanczos4"): afwMath.WarpingControl(kernelName, "", 0, 0, afwGpu.USE_GPU) warpingControl = afwMath.WarpingControl(kernelName) warpingControl.setDevicePreference(afwGpu.USE_GPU) # OK: main kernel at least as big as mask kernel for kernelName, maskKernelName in ( ("bilinear", "bilinear"), ("lanczos3", "lanczos3"), ("lanczos3", "bilinear"), ("lanczos4", "lanczos3"), ): # this should not raise any exception afwMath.WarpingControl(kernelName, maskKernelName) # invalid kernel names for kernelName, maskKernelName in ( ("badname", ""), ("lanczos", ""), # no digit after lanczos ("lanczos3", "badname"), ("lanczos3", "lanczos"), ):
    304 fba55aa3 - self.assertRaises(pexExcept.LsstCppException,
    ? -------
    303 6fc1c3d1 + self.assertRaises(pexExcept.Exception,
    afwMath.WarpingControl, kernelName, maskKernelName) def testWarpMask(self): """Test that warping the mask plane with a different kernel does the right thing """ for kernelName, maskKernelName in ( ("bilinear", "bilinear"), ("lanczos3", "lanczos3"), ("lanczos3", "bilinear"), ("lanczos4", "lanczos3"), ): for growFullMask in (0, 1, 3, 0xFFFF): self.verifyMaskWarp( kernelName=kernelName, maskKernelName=maskKernelName, growFullMask=growFullMask, ) def testMatchSwarpBilinearImage(self): """Test that warpExposure matches swarp using a bilinear warping kernel """ self.compareToSwarp("bilinear", useWarpExposure=False, atol=0.15) def testMatchSwarpBilinearExposure(self): """Test that warpExposure matches swarp using a bilinear warping kernel """ self.compareToSwarp("bilinear", useWarpExposure=True, useSubregion=False, useDeepCopy=True) def testMatchSwarpLanczos2Image(self): """Test that warpExposure matches swarp using a lanczos2 warping kernel """ self.compareToSwarp("lanczos2", useWarpExposure=False) def testMatchSwarpLanczos2Exposure(self): """Test that warpExposure matches swarp using a lanczos2 warping kernel. """ self.compareToSwarp("lanczos2", useWarpExposure=True) def testMatchSwarpLanczos2SubExposure(self): """Test that warpExposure matches swarp using a lanczos2 warping kernel with a subexposure """ for useDeepCopy in (False, True): self.compareToSwarp("lanczos2", useWarpExposure=True, useSubregion=True, useDeepCopy=useDeepCopy) def testMatchSwarpLanczos3Image(self): """Test that warpExposure matches swarp using a lanczos2 warping kernel """ self.compareToSwarp("lanczos3", useWarpExposure=False) def testMatchSwarpLanczos3(self): """Test that warpExposure matches swarp using a lanczos4 warping kernel. """ self.compareToSwarp("lanczos3", useWarpExposure=True) def testMatchSwarpLanczos4Image(self): """Test that warpExposure matches swarp using a lanczos2 warping kernel """ self.compareToSwarp("lanczos4", useWarpExposure=False) def testMatchSwarpLanczos4(self): """Test that warpExposure matches swarp using a lanczos4 warping kernel. """ self.compareToSwarp("lanczos4", useWarpExposure=True) def testMatchSwarpNearestExposure(self): """Test that warpExposure matches swarp using a nearest neighbor warping kernel """ self.compareToSwarp("nearest", useWarpExposure=True, atol=60) def testTicket2441(self): """Test ticket 2441: warpExposure sometimes mishandles zero-extent dest exposures""" fromWcs = makeWcs( pixelScale = afwGeom.Angle(1.0e-8, afwGeom.degrees), projection = "TAN", crPixPos = (0, 0), crValCoord = afwCoord.IcrsCoord(afwGeom.Point2D(359, 0), afwGeom.degrees), ) fromExp = afwImage.ExposureF(afwImage.MaskedImageF(10, 10), fromWcs) toWcs = makeWcs( pixelScale = afwGeom.Angle(0.00011, afwGeom.degrees), projection = "CEA", crPixPos = (410000.0, 11441.0), crValCoord = afwCoord.IcrsCoord(afwGeom.Point2D(45, 0), afwGeom.degrees), doFlipX = True, ) toExp = afwImage.ExposureF(afwImage.MaskedImageF(0,0), toWcs) warpControl = afwMath.WarpingControl("lanczos3") # if a bug described in ticket #2441 is present, this will raise an exception: numGoodPix = afwMath.warpExposure(toExp, fromExp, warpControl) self.assertEqual(numGoodPix, 0) def testSmallSrc(self): """Verify that a source image that is too small will not raise an exception This tests another bug that was fixed in ticket #2441 """ fromWcs = makeWcs( pixelScale = afwGeom.Angle(1.0e-8, afwGeom.degrees), projection = "TAN", crPixPos = (0, 0), crValCoord = afwCoord.IcrsCoord(afwGeom.Point2D(359, 0), afwGeom.degrees), ) fromExp = afwImage.ExposureF(afwImage.MaskedImageF(1, 1), fromWcs) toWcs = makeWcs( pixelScale = afwGeom.Angle(1.1e-8, afwGeom.degrees), projection = "TAN", crPixPos = (0, 0), crValCoord = afwCoord.IcrsCoord(afwGeom.Point2D(358, 0), afwGeom.degrees), ) toExp = afwImage.ExposureF(afwImage.MaskedImageF(10,10), toWcs) warpControl = afwMath.WarpingControl("lanczos3") # if a bug described in ticket #2441 is present, this will raise an exception: numGoodPix = afwMath.warpExposure(toExp, fromExp, warpControl) self.assertEqual(numGoodPix, 0) imArr, maskArr, varArr = toExp.getMaskedImage().getArrays() self.assertTrue(numpy.alltrue(numpy.isnan(imArr))) self.assertTrue(numpy.alltrue(numpy.isinf(varArr)))
    426 f76e1b8b - edgeMask = afwImage.MaskU.getPlaneBitMask("NO_DATA")
    ? ^^^ ^^^
    425 18371877 + edgeMask = afwImage.MaskU.getPlaneBitMask("EDGE")
    ? ^ ^^ self.assertTrue(numpy.alltrue(maskArr == edgeMask)) def verifyMaskWarp(self, kernelName, maskKernelName, growFullMask, interpLength=10, cacheSize=100000, rtol=4e-05, atol=1e-2): """Verify that using a separate mask warping kernel produces the correct results Inputs: - kernelName: name of warping kernel in the form used by afwImage.makeKernel - maskKernelName: name of mask warping kernel in the form used by afwImage.makeKernel - interpLength: interpLength argument for lsst.afw.math.WarpingControl - cacheSize: cacheSize argument for lsst.afw.math.WarpingControl; 0 disables the cache 10000 gives some speed improvement but less accurate results (atol must be increased) 100000 gives better accuracy but no speed improvement in this test - rtol: relative tolerance as used by numpy.allclose - atol: absolute tolerance as used by numpy.allclose """ srcWcs = makeWcs( pixelScale = afwGeom.Angle(0.2, afwGeom.degrees), crPixPos = (10.0, 11.0), crValCoord = afwCoord.IcrsCoord(afwGeom.Point2D(41.7, 32.9), afwGeom.degrees), ) destWcs = makeWcs( pixelScale = afwGeom.Angle(0.17, afwGeom.degrees), crPixPos = (9.0, 10.0), crValCoord = afwCoord.IcrsCoord(afwGeom.Point2D(41.65, 32.95), afwGeom.degrees), posAng = afwGeom.Angle(31, afwGeom.degrees), ) srcMaskedImage = afwImage.MaskedImageF(100, 101) srcExposure = afwImage.ExposureF(srcMaskedImage, srcWcs) destMaskedImage = afwImage.MaskedImageF(110, 121) destExposure = afwImage.ExposureF(destMaskedImage, destWcs) srcArrays = srcMaskedImage.getArrays() shape = srcArrays[0].shape numpy.random.seed(0) srcArrays[0][:] = numpy.random.normal(10000, 1000, size=shape) srcArrays[2][:] = numpy.random.normal( 9000, 900, size=shape) srcArrays[1][:] = numpy.reshape(numpy.arange(0, shape[0] * shape[1], 1, dtype=numpy.uint16), shape) warpControl = afwMath.WarpingControl( kernelName, maskKernelName, cacheSize, interpLength, afwGpu.DEFAULT_DEVICE_PREFERENCE, growFullMask ) afwMath.warpExposure(destExposure, srcExposure, warpControl) afwArrays = [numpy.copy(arr) for arr in destExposure.getMaskedImage().getArrays()] # now compute with two separate mask planes warpControl.setGrowFullMask(0) afwMath.warpExposure(destExposure, srcExposure, warpControl) narrowArrays = [numpy.copy(arr) for arr in destExposure.getMaskedImage().getArrays()] warpControl.setMaskWarpingKernelName("") afwMath.warpExposure(destExposure, srcExposure, warpControl) broadArrays = [numpy.copy(arr) for arr in destExposure.getMaskedImage().getArrays()] if (kernelName != maskKernelName) and (growFullMask != 0xFFFF): # we expect the mask planes to differ if numpy.allclose(broadArrays[1], narrowArrays[1]): self.fail("No difference between broad and narrow mask") predMask = (broadArrays[1] & growFullMask) | (narrowArrays[1] & ~growFullMask) predArraySet = (broadArrays[0], predMask, broadArrays[2]) errStr = imageTestUtils.maskedImagesDiffer(afwArrays, predArraySet, doImage=True, doMask=True, doVariance=True, rtol=rtol, atol=atol) if errStr:
    502 fba55aa3 - if SAVE_FAILED_FITS_FILES:
    503 211140a5 - computedExposure.writeFits(computedExposurePath)
    504 211140a5 - expectedExposure.writeFits(expectedExposurePath)
    505 211140a5 - print "Saved failed afw-warped exposures as: %s and %s" % \
    506 211140a5 - (computedExposurePath, expectedExposure)
    self.fail("Separate mask warping failed; warpingKernel=%s; maskWarpingKernel=%s; error=%s" % \ (kernelName, maskKernelName, errStr)) def compareToSwarp(self, kernelName, useWarpExposure=True, useSubregion=False, useDeepCopy=False, interpLength=10, cacheSize=100000, rtol=4e-05, atol=1e-2): """Compare warpExposure to swarp for given warping kernel. Note that swarp only warps the image plane, so only test that plane. Inputs: - kernelName: name of kernel in the form used by afwImage.makeKernel - useWarpExposure: if True, call warpExposure to warp an ExposureF, else call warpImage to warp an ImageF - useSubregion: if True then the original source exposure (from which the usual test exposure was extracted) is read and the correct subregion extracted - useDeepCopy: if True then the copy of the subimage is a deep copy, else it is a shallow copy; ignored if useSubregion is False - interpLength: interpLength argument for lsst.afw.math.WarpingControl - cacheSize: cacheSize argument for lsst.afw.math.WarpingControl; 0 disables the cache 10000 gives some speed improvement but less accurate results (atol must be increased) 100000 gives better accuracy but no speed improvement in this test - rtol: relative tolerance as used by numpy.allclose - atol: absolute tolerance as used by numpy.allclose """ warpingControl = afwMath.WarpingControl( kernelName, "", # there is no point to a separate mask kernel since we aren't testing the mask plane cacheSize, interpLength, ) if useSubregion: originalFullExposure = afwImage.ExposureF(originalExposurePath) # "medsub" is a subregion of med starting at 0-indexed pixel (40, 150) of size 145 x 200 bbox = afwGeom.Box2I(afwGeom.Point2I(40, 150), afwGeom.Extent2I(145, 200)) originalExposure = afwImage.ExposureF(originalFullExposure, bbox, afwImage.LOCAL, useDeepCopy) swarpedImageName = "medsubswarp1%s.fits" % (kernelName,) else: originalExposure = afwImage.ExposureF(originalExposurePath) swarpedImageName = "medswarp1%s.fits" % (kernelName,) swarpedImagePath = os.path.join(dataDir, swarpedImageName) swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath) swarpedImage = swarpedDecoratedImage.getImage() swarpedMetadata = swarpedDecoratedImage.getMetadata() warpedWcs = afwImage.makeWcs(swarpedMetadata) if useWarpExposure: # path for saved afw-warped image afwWarpedImagePath = "afwWarpedExposure1%s" % (kernelName,) afwWarpedMaskedImage = afwImage.MaskedImageF(swarpedImage.getDimensions()) afwWarpedExposure = afwImage.ExposureF(afwWarpedMaskedImage, warpedWcs) afwMath.warpExposure(afwWarpedExposure, originalExposure, warpingControl) if SAVE_FITS_FILES: afwWarpedExposure.writeFits(afwWarpedImagePath) if display: ds9.mtv(afwWarpedExposure, frame=1, title="Warped") afwWarpedMask = afwWarpedMaskedImage.getMask()
    569 f76e1b8b - edgeBitMask = afwWarpedMask.getPlaneBitMask("NO_DATA")
    ? ^^^ ^^^
    563 5d775212 + edgeBitMask = afwWarpedMask.getPlaneBitMask("EDGE")
    ? ^ ^^ if edgeBitMask == 0:
    571 f76e1b8b - self.fail("warped mask has no NO_DATA bit")
    ? ^^^ ^^^
    565 5d775212 + self.fail("warped mask has no EDGE bit")
    ? ^ ^^ afwWarpedMaskedImageArrSet = afwWarpedMaskedImage.getArrays() afwWarpedMaskArr = afwWarpedMaskedImageArrSet[1] swarpedMaskedImage = afwImage.MaskedImageF(swarpedImage) swarpedMaskedImageArrSet = swarpedMaskedImage.getArrays() if display: ds9.mtv(swarpedMaskedImage, frame=2, title="SWarped") errStr = imageTestUtils.maskedImagesDiffer(afwWarpedMaskedImageArrSet, swarpedMaskedImageArrSet, doImage=True, doMask=False, doVariance=False, skipMaskArr=afwWarpedMaskArr, rtol=rtol, atol=atol) if errStr: if SAVE_FAILED_FITS_FILES: afwWarpedExposure.writeFits(afwWarpedImagePath) print "Saved failed afw-warped exposure as: %s" % (afwWarpedImagePath,) self.fail("afw and swarp %s-warped %s (ignoring bad pixels)" % (kernelName, errStr)) else: # path for saved afw-warped image afwWarpedImagePath = "afwWarpedImage1%s.fits" % (kernelName,) afwWarpedImage = afwImage.ImageF(swarpedImage.getDimensions()) originalImage = originalExposure.getMaskedImage().getImage() originalWcs = originalExposure.getWcs() afwMath.warpImage(afwWarpedImage, warpedWcs, originalImage, originalWcs, warpingControl) if display: ds9.mtv(afwWarpedImage, frame=1, title="Warped") ds9.mtv(swarpedImage, frame=2, title="SWarped") diff = swarpedImage.Factory(swarpedImage, True) diff -= afwWarpedImage ds9.mtv(diff, frame=3, title="swarp - afw") if SAVE_FITS_FILES: afwWarpedImage.writeFits(afwWarpedImagePath) afwWarpedImageArr = afwWarpedImage.getArray() swarpedImageArr = swarpedImage.getArray() edgeMaskArr = numpy.isnan(afwWarpedImageArr) errStr = imageTestUtils.imagesDiffer(afwWarpedImageArr, swarpedImageArr, skipMaskArr=edgeMaskArr, rtol=rtol, atol=atol) if errStr: if SAVE_FAILED_FITS_FILES: # save the image anyway afwWarpedImage.writeFits(afwWarpedImagePath) print "Saved failed afw-warped image as: %s" % (afwWarpedImagePath,) self.fail("afw and swarp %s-warped images do not match (ignoring NaN pixels): %s" % \ (kernelName, errStr)) def compareMaskedImages(self, maskedImage1, maskedImage2, descr="", doImage=True, doMask=True, doVariance=True, skipMaskArr=None, rtol=1.0e-05, atol=1e-08): """Compare pixels from two masked images Inputs: - maskedImage1: first masked image to compare - maskedImage2: second masked image to compare - descr: a short description of the inputs - doImage: compare image planes if True - doMask: compare mask planes if True - doVariance: compare variance planes if True - skipMaskArr: pixels to ingore on the image, mask and variance arrays; nonzero values are skipped Returns None if all is well, or an error string if any plane did not match. The error string is one of: plane does not match (, ,...) planes do not match """ badPlanes = [] for (doPlane, planeName) in ((doImage, "image"), (doMask, "mask"), (doVariance, "variance")): if not doPlane: continue funcName = "get%s" % (planeName.title(),) imageDescr = "%s: %s plane" % (descr, planeName) image1 = getattr(maskedImage1, funcName)() image2 = getattr(maskedImage2, funcName)() imageOK = self.compareImages(image1, image2, descr=imageDescr, skipMaskArr=skipMaskArr, rtol=rtol, atol=atol) if not imageOK: badPlanes.append(planeName) if not badPlanes: return None if len(badPlanes) > 1: return "%s planes do not match" % (badPlanes,) return "%s plane does not match" % (badPlanes[0],) def compareImages(self, image1, image2, descr="", skipMaskArr=None, rtol=1.0e-05, atol=1e-08): """Return True if two images are nearly equal, False otherwise """ arr1 = image1.getArray() arr2 = image2.getArray() if skipMaskArr != None: maskedArr1 = numpy.ma.array(arr1, copy=False, mask = skipMaskArr) maskedArr2 = numpy.ma.array(arr2, copy=False, mask = skipMaskArr) filledArr1 = maskedArr1.filled(0.0) filledArr2 = maskedArr2.filled(0.0) else: filledArr1 = arr1 filledArr2 = arr2 if not numpy.allclose(filledArr1, filledArr2, rtol=rtol, atol=atol): errArr = numpy.abs(filledArr1 - filledArr2) - (filledArr2 * rtol) + atol maxErr = errArr.max() maxPosInd = numpy.where(errArr==maxErr) maxPosTuple = (maxPosInd[0][0], maxPosInd[1][0]) relErr = numpy.abs(filledArr1 - filledArr2) / (filledArr1 + filledArr2) print "%s: maxErr=%s at position %s; value=%s vs. %s; relErr=%s" % \ (descr, maxErr, maxPosTuple, filledArr1[maxPosInd][0], filledArr2[maxPosInd][0], relErr) return False return True #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """ Returns a suite containing all the test cases in this module. """ utilsTests.init() suites = [] suites += unittest.makeSuite(WarpExposureTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(doExit=False): """Run the tests""" utilsTests.run(suite(), doExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f594298d

    commit f594298dccf21ccffce66e1a3c36c927389f7632
    Author: Russell Owen 
    Date:   Sun Nov 11 13:54:29 2012 -0800
    
        Make the unit tests for #2441 slightly simpler.
    

    f76e1b8b

    commit f76e1b8b233d1ae63f78ed29d2ad01b9b4b9be59
    Author: Paul Price 
    Date:   Thu May 22 15:03:31 2014 -0400
    
        tests: update warping to check new NO_DATA mask bit
        
        NO_DATA is now used in warping instead of EDGE.
    

    db7df6ad

    commit db7df6ad5b0daac202dab50aea9805dc151e400f
    Author: rowen 
    Date:   Wed Feb 18 00:37:48 2009 +0000
    
        Merge afw ticket 532
    

    211140a5

    commit 211140a53f1ceb08c462a70d1c887f4c54d31906
    Author: Russell Owen 
    Date:   Fri Jun 29 15:35:07 2012 -0700
    
        Disable GPU if maskWarpingKernel specified (for now, until the GPU supports this case);
        raise an exception if the user requires the GPU and specifies a mask warping kernel.
        Replace NULL == ptr with !ptr at Jim's sensible request
        Fix error in tests/warpExposure.py: if verifyMaskWarp failed had problems in the error reporting.
    

    fba55aa3

    commit fba55aa3cbd26df56f7ddba6b55bc69e7dae2d77
    Author: Russell Owen 
    Date:   Fri Jun 29 13:08:53 2012 -0700
    
        Finished. Unit tests pass. The images look good.
    

    2db43632

    commit 2db4363243604745c62157ea5012ed24cd5f7f28
    Author: Russell Owen 
    Date:   Mon Oct 8 17:04:19 2012 -0700
    
        Add a few more tests to WarpingControl
    

    1751cb91

    commit 1751cb91d22c3785489279819cff92e6a03ea212
    Author: rowen 
    Date:   Thu May 26 22:29:34 2011 +0000
    
        First cut at a fix. I also added getFlux to Calib and that needs verification.
    

    Commits in /Users/nate/repos_lsst/afw/

    18371877

    commit 18371877a3f741772201b3fc8456a7c8203f5cf1
    Author: Russell Owen 
    Date:   Sun Nov 11 19:55:53 2012 -0800
    
        Fix warping bug: when src image too small was setting source, not dest, to all edge pixels.
        Improve unit test to confirm this.
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    84d4fa7d

    commit 84d4fa7def01e40f6674bb7ebd2eca93cd7b2741
    Merge: 19ed381 846aff9
    Author: rowen 
    Date:   Thu May 14 00:07:00 2009 +0000
    
        Implemented warpImage, including unit tests.
        Note:
        - The new unit tests show some disagreement with swarp around bad columns;
          this was masked by bad pixels in the MaskedImage tests.
        - Edge pixels have value (NaN, EDGE, infinity), based on ticket #806 and as implemented by new
          edgePixel function. This is a change from the trunk, so I prefer to hold off merging
          this ticket to the trunk until after DC3a. (If necessary we can hack the edgePixel method
          to match the old behavior, but I would prefer to wait if we can.)
          Hence it is probably not safe to merge to the trunk until after DC3a.
        - The convolve functions have not yet been modified to use the new edge pixel function;
          (ticket #806); this will involve removing the edge bit mask argument.
    

    5d775212

    commit 5d77521225bfa3df2ba187dba22441381aa38268
    Merge: c0ed8f4 a69dce0
    Author: rowen 
    Date:   Wed Jun 2 21:33:58 2010 +0000
    
        Merged the trunk.
        Updated the warpExposure unit tests (the subExposure tests fails due to ticket #1302;
        once that's fixed we'll see if there are further issues).
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/image/makeWcs.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include "boost/make_shared.hpp"
                    #include "Eigen/Core"
    
    27 3a4b1467 + #include "lsst/pex/logging.h"
    #include "lsst/afw/image/Wcs.h" #include "lsst/afw/image/TanWcs.h" namespace except = lsst::pex::exceptions; namespace afwImg = lsst::afw::image; /** * Create a Wcs object from a fits header. * It examines the header and determines the * most suitable object to return, either a general Wcs object, or a more specific object specialised to a * given coordinate system (e.g TanWcs) */ afwImg::Wcs::Ptr afwImg::makeWcs(
    40 f1301348 - PTR(lsst::daf::base::PropertySet) const& metadata, ///< input metadata
    41 3a4b1467 + PTR(lsst::daf::base::PropertySet) const& _metadata, ///< input metadata
    ? + bool stripMetadata ///< Remove FITS keywords from metadata? ) {
    45 3a4b1467 + //
    46 3a4b1467 + // _metadata is not const (it is probably meant to be), but we don't want to modify it.
    47 3a4b1467 + //
    48 3a4b1467 + auto metadata = _metadata; // we'll make a copy and modify metadata if needs be
    49 3a4b1467 + auto modifyable = false; // ... and set this variable to say that we did
    50 3a4b1467 +
    44 981cdb34 - std::string ctype1;
    51 3a4b1467 + std::string ctype1, ctype2;
    ? ++++++++
    45 8f1e759b - if (metadata->exists("CTYPE1")) {
    52 3a4b1467 + if (metadata->exists("CTYPE1") && metadata->exists("CTYPE2")) {
    ctype1 = metadata->getAsString("CTYPE1");
    54 3a4b1467 + ctype2 = metadata->getAsString("CTYPE2");
    } else { return PTR(Wcs)();
    57 981cdb34 + }
    58 3a4b1467 + //
    59 3a4b1467 + // SCAMP used to use PVi_j keys with a CTYPE of TAN to specify a "TPV" projection
    60 3a4b1467 + // (cf. https://github.com/astropy/astropy/issues/299
    61 3a4b1467 + // and the discussion from Dave Berry in https://jira.lsstcorp.org/browse/DM-2883)
    62 3a4b1467 + //
    63 3a4b1467 + // Follow Dave's AST and switch TAN to TPV
    64 3a4b1467 + //
    65 3a4b1467 + using pex::logging::Log;
    66 3a4b1467 + auto log = Log(Log::getDefaultLog(), "makeWcs");
    67 3a4b1467 +
    68 3a4b1467 + if (ctype1.substr(5, 3) == "TAN" &&
    69 3a4b1467 + (metadata->exists("PV1_5") || metadata->exists("PV2_1"))) {
    70 3a4b1467 + log.log(Log::INFO, str(boost::format("Interpreting %s/%s + PVi_j as TPV") % ctype1 % ctype2));
    71 3a4b1467 +
    72 3a4b1467 + if (!modifyable) {
    73 3a4b1467 + metadata = _metadata->deepCopy();
    74 3a4b1467 + modifyable = true;
    75 3a4b1467 + }
    76 3a4b1467 +
    77 3a4b1467 + ctype1.replace(5, 3, "TPV");
    78 3a4b1467 + metadata->set("CTYPE1", ctype1);
    79 3a4b1467 +
    80 3a4b1467 + ctype2.replace(5, 3, "TPV");
    81 3a4b1467 + metadata->set("CTYPE2", ctype2);
    } afwImg::Wcs::Ptr wcs; // we can't use make_shared as ctor is private if (ctype1.substr(5, 3) == "TAN") { wcs = afwImg::Wcs::Ptr(new afwImg::TanWcs(metadata));
    54 cacd0ad6 - } else if (ctype1.substr(5, 3) == "TPV") {
    55 cacd0ad6 - PTR(daf::base::PropertySet) _metadata = metadata->deepCopy();
    56 cacd0ad6 - _metadata->set("CTYPE1", "RA---TAN");
    57 cacd0ad6 - _metadata->set("CTYPE2", "DEC--TAN");
    58 cacd0ad6 - _metadata->set("TPV_WCS", true);
    87 3a4b1467 + } else if (ctype1.substr(5, 3) == "TPV") { // unfortunately we don't support TPV
    88 3a4b1467 + if (!modifyable) {
    89 3a4b1467 + metadata = _metadata->deepCopy();
    90 3a4b1467 + modifyable = true;
    91 3a4b1467 + }
    92 3a4b1467 +
    93 3a4b1467 + log.log(Log::WARN, str(boost::format("Stripping PVi_j keys from projection %s/%s") % ctype1 % ctype2));
    95 3a4b1467 + metadata->set("CTYPE1", "RA---TAN");
    96 3a4b1467 + metadata->set("CTYPE2", "DEC--TAN");
    97 3a4b1467 + metadata->set("TPV_WCS", true);
    98 cacd0ad6 +
    99 3a4b1467 + for (int i = 1; i <= 3; ++i) {
    100 3a4b1467 + for (int j = (i == 1 ? 5 : 1); j <= 16; ++j) { // note that PV1_{1..4} are legal
    101 3a4b1467 + char pvName[8];
    102 3a4b1467 + sprintf(pvName, "PV%d_%d", i, j);
    103 3a4b1467 + if (metadata->exists(pvName)) {
    104 3a4b1467 + metadata->remove(pvName);
    105 3a4b1467 + }
    106 3a4b1467 + }
    107 3a4b1467 + }
    108 3a4b1467 +
    60 cacd0ad6 - wcs = afwImg::Wcs::Ptr(new afwImg::TanWcs(_metadata));
    ? -
    109 3a4b1467 + wcs = afwImg::Wcs::Ptr(new afwImg::TanWcs(metadata));
    } else { wcs = afwImg::Wcs::Ptr(new afwImg::Wcs(metadata)); } //If keywords LTV[1,2] are present, the image on disk is already a subimage, so //we should shift the wcs to allow for this. std::string key = "LTV1"; if (metadata->exists(key)) { wcs->shiftReferencePixel(-metadata->getAsDouble(key), 0); } key = "LTV2"; if (metadata->exists(key) ) { wcs->shiftReferencePixel(0, -metadata->getAsDouble(key)); } if (stripMetadata) { afwImg::detail::stripWcsKeywords(metadata, wcs); } return wcs; } /** * @brief Create a Wcs object from crval, crpix, CD, using CD elements (useful from python) */ afwImg::Wcs::Ptr afwImg::makeWcs( lsst::afw::coord::Coord const & crval, ///< CRVAL1,2 (ie. the sky origin) lsst::afw::geom::Point2D const & crpix, ///< CRPIX1,2 (ie. the pixel origin) in pixels double CD11, ///< CD matrix element 1,1 double CD12, ///< CD matrix element 1,2 double CD21, ///< CD matrix element 2,1 double CD22 ///< CD matrix element 2,2 ) { Eigen::Matrix2d CD; CD << CD11, CD12, CD21, CD22; lsst::afw::geom::Point2D crvalTmp; crvalTmp[0] = crval.toIcrs().getLongitude().asDegrees(); crvalTmp[1] = crval.toIcrs().getLatitude().asDegrees(); return afwImg::Wcs::Ptr(new lsst::afw::image::Wcs(crvalTmp, crpix, CD)); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    981cdb34

    commit 981cdb34a94ca7bd5e1d880f79c4874a8454b896
    Author: fergal 
    Date:   Fri Feb 19 21:30:33 2010 +0000
    
        Code to allow Formatters to work. Constructors from fits headers made private, only accessed by friend function makeWcs in makeWcs.cc.
        
        This commit covers source files, previous was just for headers
    

    cacd0ad6

    commit cacd0ad6ad2858e4d723d5eff955b9c8d926bceb
    Author: Robert Lupton the Good 
    Date:   Wed Nov 20 13:54:31 2013 -0500
    
        Hack in support for treating RA---TPV headers as RA---TAN (ignoring the distortions)
        
        This allows us to read DECam files;  #3064
    

    8f1e759b

    commit 8f1e759b046da772cc48d71bd2a8632186676f9c
    Author: rhl 
    Date:   Mon Aug 30 13:43:12 2010 +0000
    
        Changes to resolve #1423
    

    f1301348

    commit f1301348ed7ce9bc72f9550f0858e52363469f33
    Author: Paul Price 
    Date:   Tue Jun 12 11:54:35 2012 -0400
    
        Squashed merge of tickets/2162: input header was being hacked (remove SIP) so wcslib could parse it, but this was user-visible.  Updated many APIs used by WCS code (and in related files) to take CONST_PTR instead of ::Ptr, as being more rigorous with const would have revealed this problem.  Added a test demonstrating the bug, which now passes.
    

    Commits in /Users/nate/repos_lsst/afw/

    981cdb34

    commit 981cdb34a94ca7bd5e1d880f79c4874a8454b896
    Author: fergal 
    Date:   Fri Feb 19 21:30:33 2010 +0000
    
        Code to allow Formatters to work. Constructors from fits headers made private, only accessed by friend function makeWcs in makeWcs.cc.
        
        This commit covers source files, previous was just for headers
    

    3a4b1467

    commit 3a4b1467bc5bd4b0262ac23f79e71c06c0fb66f3
    Author: Robert Lupton the Good 
    Date:   Wed Jun 3 22:06:01 2015 -0600
    
        Interpret TAN headers with PVi_j cards as TPV
        
        We've never supported TPV, but we need to remove the PVi_j cards as well as
        change CTYPE[12].  See notes in https://jira.lsstcorp.org/browse/DM-2883
        
        We convert incorrectly-named TAN projections to TPV, and then proceed to dump
        the distortions pending support for TPV.
        
        With this change we can also read (illegal!) PTF headers that provide both
        SIP and TPV coefficients.
    

    cacd0ad6

    commit cacd0ad6ad2858e4d723d5eff955b9c8d926bceb
    Author: Robert Lupton the Good 
    Date:   Wed Nov 20 13:54:31 2013 -0500
    
        Hack in support for treating RA---TPV headers as RA---TAN (ignoring the distortions)
        
        This allows us to read DECam files;  #3064
    

    Return to list

    python/lsst/afw/image/imageSlice.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    //
                    
                    %{
                    #include "lsst/afw/image/ImageSlice.h"
                    %}
                    
                    %include "lsst/afw/image/ImageSlice.h"
                    
                    %define %slice(NAME, TYPE, PIXEL_TYPE...)
                    
                    %shared_ptr(lsst::afw::image::ImageSlice);
                    %template(NAME##TYPE) lsst::afw::image::ImageSlice;
                    %template(NAME##TYPE##___add__) lsst::afw::image::operator+;
                    %template(NAME##TYPE##___sub__) lsst::afw::image::operator-;
                    %template(NAME##TYPE##___mul__) lsst::afw::image::operator*;
                    %template(NAME##TYPE##___div__) lsst::afw::image::operator/;
                    
                    %extend lsst::afw::image::ImageSlice {
                    
                    
    
    45 62dea1f7 - %pythoncode {
    45 81c3bd10 + %pythoncode %{
    ? +
    47 62dea1f7 - #
    47 81c3bd10 + #
    48 62dea1f7 - # Deal with incorrect swig wrappers for C++ "void operator op=()"
    ? ----
    48 81c3bd10 + # Deal with incorrect swig wrappers for C++ "void operator op=()"
    49 62dea1f7 - #
    49 81c3bd10 + #
    50 62dea1f7 - def __add__(*args):
    ? ----
    50 81c3bd10 + def __add__(*args):
    51 62dea1f7 - """
    ? ----
    51 81c3bd10 + """
    52 62dea1f7 - __add__(self, float scalar) -> self
    ? ----
    52 81c3bd10 + __add__(self, float scalar) -> self
    53 62dea1f7 - __add__(self, NAME inputImage) -> self
    ? ----
    53 81c3bd10 + __add__(self, NAME inputImage) -> self
    54 62dea1f7 - """
    ? ----
    54 81c3bd10 + """
    55 62dea1f7 - return _imageLib.__add__(*args)
    ? ----
    55 81c3bd10 + return _imageLib.__add__(*args)
    57 62dea1f7 - def __sub__(*args):
    ? ----
    57 81c3bd10 + def __sub__(*args):
    58 62dea1f7 - """
    ? ----
    58 81c3bd10 + """
    59 62dea1f7 - __sub__(self, float scalar)
    ? ----
    59 81c3bd10 + __sub__(self, float scalar)
    60 62dea1f7 - __sub__(self, NAME inputImage)
    ? ----
    60 81c3bd10 + __sub__(self, NAME inputImage)
    61 62dea1f7 - """
    ? ----
    61 81c3bd10 + """
    62 62dea1f7 - return _imageLib.__sub__(*args)
    ? ----
    62 81c3bd10 + return _imageLib.__sub__(*args)
    64 62dea1f7 - def __mul__(*args):
    ? ----
    64 81c3bd10 + def __mul__(*args):
    65 62dea1f7 - """
    ? ----
    65 81c3bd10 + """
    66 62dea1f7 - __mul__(self, float scalar)
    ? ----
    66 81c3bd10 + __mul__(self, float scalar)
    67 62dea1f7 - __mul__(self, NAME inputImage)
    ? ----
    67 81c3bd10 + __mul__(self, NAME inputImage)
    68 62dea1f7 - """
    ? ----
    68 81c3bd10 + """
    69 62dea1f7 - return _imageLib.__mul__(*args)
    ? ----
    69 81c3bd10 + return _imageLib.__mul__(*args)
    71 62dea1f7 - def __div__(*args):
    ? ----
    71 81c3bd10 + def __div__(*args):
    72 62dea1f7 - """
    ? ----
    72 81c3bd10 + """
    73 62dea1f7 - __div__(self, float scalar)
    ? ----
    73 81c3bd10 + __div__(self, float scalar)
    74 62dea1f7 - __div__(self, NAME inputImage)
    ? ----
    74 81c3bd10 + __div__(self, NAME inputImage)
    75 62dea1f7 - """
    ? ----
    75 81c3bd10 + """
    76 62dea1f7 - return _imageLib.__div__(*args)
    ? ----
    76 81c3bd10 + return _imageLib.__div__(*args)
    77 81c3bd10 +
    78 81c3bd10 + # support "__from__ future import division" in Python 2 (not needed for Python 3)
    79 81c3bd10 + __truediv__ = __div__
    77 62dea1f7 - }
    80 81c3bd10 + %}
    ? + } %extend lsst::afw::image::Image {
    85 62dea1f7 - %pythoncode {
    88 81c3bd10 + %pythoncode %{
    ? +
    87 62dea1f7 - #
    90 81c3bd10 + #
    88 62dea1f7 - # Deal with incorrect swig wrappers for C++ "void operator op=()"
    ? ----
    91 81c3bd10 + # Deal with incorrect swig wrappers for C++ "void operator op=()"
    89 62dea1f7 - #
    92 81c3bd10 + #
    90 62dea1f7 - def __add__(*args):
    ? ----
    93 81c3bd10 + def __add__(*args):
    91 62dea1f7 - """
    ? ----
    94 81c3bd10 + """
    92 62dea1f7 - __add__(self, float scalar) -> self
    ? ----
    95 81c3bd10 + __add__(self, float scalar) -> self
    93 62dea1f7 - __add__(self, NAME inputImage) -> self
    ? ----
    96 81c3bd10 + __add__(self, NAME inputImage) -> self
    94 62dea1f7 - """
    ? ----
    97 81c3bd10 + """
    95 62dea1f7 - return _imageLib.__add__(*args)
    ? ----
    98 81c3bd10 + return _imageLib.__add__(*args)
    97 62dea1f7 - def __sub__(*args):
    ? ----
    100 81c3bd10 + def __sub__(*args):
    98 62dea1f7 - """
    ? ----
    101 81c3bd10 + """
    99 62dea1f7 - __sub__(self, float scalar)
    ? ----
    102 81c3bd10 + __sub__(self, float scalar)
    100 62dea1f7 - __sub__(self, NAME inputImage)
    ? ----
    103 81c3bd10 + __sub__(self, NAME inputImage)
    101 62dea1f7 - """
    ? ----
    104 81c3bd10 + """
    102 62dea1f7 - return _imageLib.__sub__(*args)
    ? ----
    105 81c3bd10 + return _imageLib.__sub__(*args)
    104 62dea1f7 - def __mul__(*args):
    ? ----
    107 81c3bd10 + def __mul__(*args):
    105 62dea1f7 - """
    ? ----
    108 81c3bd10 + """
    106 62dea1f7 - __mul__(self, float scalar)
    ? ----
    109 81c3bd10 + __mul__(self, float scalar)
    107 62dea1f7 - __mul__(self, NAME inputImage)
    ? ----
    110 81c3bd10 + __mul__(self, NAME inputImage)
    108 62dea1f7 - """
    ? ----
    111 81c3bd10 + """
    109 62dea1f7 - return _imageLib.__mul__(*args)
    ? ----
    112 81c3bd10 + return _imageLib.__mul__(*args)
    111 62dea1f7 - def __div__(*args):
    ? ----
    114 81c3bd10 + def __div__(*args):
    112 62dea1f7 - """
    ? ----
    115 81c3bd10 + """
    113 62dea1f7 - __div__(self, float scalar)
    ? ----
    116 81c3bd10 + __div__(self, float scalar)
    114 62dea1f7 - __div__(self, NAME inputImage)
    ? ----
    117 81c3bd10 + __div__(self, NAME inputImage)
    115 62dea1f7 - """
    ? ----
    118 81c3bd10 + """
    116 62dea1f7 - return _imageLib.__div__(*args)
    ? ----
    119 81c3bd10 + return _imageLib.__div__(*args)
    120 81c3bd10 +
    121 81c3bd10 + # support "__from__ future import division" in Python 2 (not needed for Python 3)
    122 81c3bd10 + __truediv__ = __div__
    117 62dea1f7 - }
    123 81c3bd10 + %}
    ? + } %enddef //%slice(ImageSlice, U, boost::uint16_t); //%slice(ImageSlice, I, int); %slice(ImageSlice, F, float); %slice(ImageSlice, D, double);

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    62dea1f7

    commit 62dea1f7d81b5bdfca8ca70706131e6bc6133116
    Author: bick 
    Date:   Fri Apr 2 00:49:39 2010 +0000
    
        #1135 all basic functionality now working.  Needs cleanup and comments.
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    src/formatters/MaskFormatter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    /** @file
                     * @brief Implementation of MaskFormatter class
                     *
                     * @author $Author: ktlim $
                     * @version $Revision: 2151 $
                     * @date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * @ingroup afw
                     */
                    
                    #ifndef __GNUC__
                    #  define __attribute__(x) /*NOTHING*/
                    #endif
                    static char const* SVNid __attribute__((unused)) = "$Id$";
                    
                    #include "boost/serialization/shared_ptr.hpp"
                    #include "boost/serialization/binary_object.hpp"
                    #include 
                    #include 
                    
                    #include "lsst/afw/formatters/MaskFormatter.h"
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/image/Mask.h"
                    
                    #include "lsst/afw/image/LsstImageTypes.h"
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.MaskFormatter", level, s);
                    }
                    
                    using lsst::daf::base::Persistable;
                    using lsst::daf::persistence::BoostStorage;
                    using lsst::daf::persistence::FitsStorage;
                    using lsst::daf::persistence::Storage;
                    using lsst::afw::image::Mask;
                    using lsst::afw::image::MaskPixel;
                    
                    namespace lsst {
                    namespace afw {
                    namespace formatters {
                    
                    template 
                    class MaskFormatterTraits {
                    public:
                        static std::string name();
                    };
                    
                    template<> std::string MaskFormatterTraits::name() {
                        static std::string name = "Mask";
                        return name;
                    }
                    
                    template 
                    lsst::daf::persistence::FormatterRegistration MaskFormatter::registration(
                        MaskFormatterTraits::name(),
                        typeid(Mask),
                        createInstance);
                    
                    template 
                    MaskFormatter::MaskFormatter(
                        lsst::pex::policy::Policy::Ptr) :
                        lsst::daf::persistence::Formatter(typeid(this)) {
                    }
                    
                    template 
                    MaskFormatter::~MaskFormatter(void) {
                    }
                    
                    template 
                    void MaskFormatter::write(
                        Persistable const* persistable,
                        Storage::Ptr storage,
                        lsst::daf::base::PropertySet::Ptr) {
                        execTrace("MaskFormatter write start");
                        Mask const* ip =
                            dynamic_cast const*>(persistable);
                        if (ip == 0) {
    
    109 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Persisting non-Mask");
    ? ---------
    109 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Persisting non-Mask");
    } if (typeid(*storage) == typeid(BoostStorage)) { execTrace("MaskFormatter write BoostStorage"); BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & *ip; execTrace("MaskFormatter write end"); return; } else if (typeid(*storage) == typeid(FitsStorage)) { execTrace("MaskFormatter write FitsStorage"); FitsStorage* fits = dynamic_cast(storage.get()); // Need to cast away const because writeFits modifies the metadata. Mask* vip = const_cast*>(ip); vip->writeFits(fits->getPath()); execTrace("MaskFormatter write end"); return; }
    127 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Mask");
    ? ---------
    127 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Mask");
    } template Persistable* MaskFormatter::read( Storage::Ptr storage, lsst::daf::base::PropertySet::Ptr) { execTrace("MaskFormatter read start"); if (typeid(*storage) == typeid(BoostStorage)) { execTrace("MaskFormatter read BoostStorage"); BoostStorage* boost = dynamic_cast(storage.get()); Mask* ip = new Mask; boost->getIArchive() & *ip; execTrace("MaskFormatter read end"); return ip; } else if (typeid(*storage) == typeid(FitsStorage)) { execTrace("MaskFormatter read FitsStorage"); FitsStorage* fits = dynamic_cast(storage.get()); Mask* ip = new Mask(fits->getPath(), fits->getHdu()); execTrace("MaskFormatter read end"); return ip; }
    150 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Mask");
    ? ---------
    150 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Mask");
    } template void MaskFormatter::update( Persistable*, Storage::Ptr, lsst::daf::base::PropertySet::Ptr) {
    158 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unexpected call to update for Mask");
    ? ---------
    158 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unexpected call to update for Mask");
    } template template void MaskFormatter::delegateSerialize( Archive& ar, int const version, Persistable* persistable) { execTrace("MaskFormatter delegateSerialize start"); Mask* ip = dynamic_cast*>(persistable); if (ip == 0) {
    167 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Serializing non-Mask");
    ? ---------
    167 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Serializing non-Mask");
    } ar & ip->_offsetRows & ip->_offsetCols; ar & ip->_maskPlaneDict; unsigned int cols; unsigned int rows; unsigned int planes; if (Archive::is_saving::value) { cols = ip->_vwImagePtr->cols(); rows = ip->_vwImagePtr->rows(); planes = ip->_vwImagePtr->planes(); } ar & cols & rows & planes; if (Archive::is_loading::value) { ip->_vwImagePtr->set_size(cols, rows, planes); } unsigned int pixels = cols * rows * planes; MaskPixelT* data = ip->_vwImagePtr->data(); ar & boost::serialization::make_array(data, pixels); execTrace("MaskFormatter delegateSerialize end"); } template lsst::daf::persistence::Formatter::Ptr MaskFormatter::createInstance( lsst::pex::policy::Policy::Ptr policy) { return lsst::daf::persistence::Formatter::Ptr(new MaskFormatter(policy)); } template class MaskFormatter; //// The followings fails //// because the function template `delegateSerialize' is obsolete(?) //template void MaskFormatter::delegateSerialize( // boost::archive::binary_oarchive&, int const, Persistable*); //template void MaskFormatter::delegateSerialize( // boost::archive::binary_iarchive&, int const, Persistable*); }}} // namespace lsst::afw::formatters

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/table/Key.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_Key_h_INCLUDED
                    #define AFW_TABLE_Key_h_INCLUDED
                    
                    #include "lsst/afw/table/FieldBase.h"
    
    6 158773f8 + #include "lsst/afw/table/Flag.h"
    #include "lsst/afw/table/KeyBase.h" namespace lsst { namespace afw { namespace table { namespace detail { class Access; } // namespace detail /** * @brief A class used as a handle to a particular field in a table. * * All access to table data ultimately goes through Key objects, which * know (via an internal offset) how to address and cast the internal * data buffer of a record or table. * * Keys can be obtained from a Schema by name: * @code * schema.find("myfield").key * @endcode * and are also returned when a new field is added. Compound and array keys also provide * accessors to retrieve scalar keys to their elements (see the * documentation for the KeyBase specializations), even though these * element keys do not correspond to a field that exists in any Schema. * For example: * @code * Schema schema; * Key< Array > arrayKey = schema.addField< Array >("array", "docs for array", 5); * Key< Point > pointKey = schema.addField< Point >("point", "docs for point"); * Key elementKey = arrayKey[3]; * Key xKey = pointKey.getX(); * PTR(BaseTable) table = BaseTable::make(schema); * PTR(BaseRecord) record = table.makeRecord(); * assert(&record[arrayKey][3] == &record[elementKey3]); * assert(record.get(pointKey).getX() == record[xKey]); * @endcode * * Key inherits from FieldBase to allow a key for a dynamically-sized field * to know its size without needing to specialize Key itself or hold a full * Field object. */ template class Key : public KeyBase, public FieldBase { public: //@{ /** * @brief Equality comparison. * * Two keys with different types are never equal. Keys with the same type * are equal if they point to the same location in a table, regardless of * what Schema they were constructed from (for instance, if a field has a * different name in one Schema than another, but is otherwise the same, * the two keys will be equal). */ template bool operator==(Key const & other) const { return false; } template bool operator!=(Key const & other) const { return true; } bool operator==(Key const & other) const { return _offset == other._offset && this->getElementCount() == other.getElementCount(); } bool operator!=(Key const & other) const { return !this->operator==(other); } //@} /// @brief Return the offset (in bytes) of this field within a record. int getOffset() const { return _offset; } /** * @brief Return true if the key was initialized to valid offset. * * This does not guarantee that a key is valid with any particular schema, or even * that any schemas still exist in which this key is valid. * * A key that is default constructed will always be invalid. */ bool isValid() const { return _offset >= 0; } /** * @brief Default construct a field. * * The new field will be invalid until a valid Key is assigned to it. */ Key() : FieldBase(FieldBase::makeDefault()), _offset(-1) {} /// Stringification. inline friend std::ostream & operator<<(std::ostream & os, Key const & key) { return os << "Key<" << Key::getTypeString() << ">(offset=" << key.getOffset() << ", nElements=" << key.getElementCount() << ")"; } private: friend class detail::Access; friend class BaseRecord; explicit Key(int offset, FieldBase const & fb = FieldBase()) : FieldBase(fb), _offset(offset) {} int _offset; }; }}} // namespace lsst::afw::table #endif // !AFW_TABLE_Key_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    158773f8

    commit 158773f8a5cd273d136955a2ce00b54d4aa98758
    Author: Russell Owen 
    Date:   Mon Oct 6 11:10:12 2014 -0700
    
        Fix a compiler error by including Flag.h
    

    Return to list

    examples/spatiallyVaryingConvolve.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    
    
    26 a9aec7fc + #include "lsst/utils/Utils.h"
    27 a9aec7fc + #include "lsst/pex/exceptions.h"
    26 1192e949 - #include "lsst/afw/math/FunctionLibrary.h"
    27 1192e949 - #include "lsst/afw/image/Image.h"
    28 1192e949 - #include "lsst/afw/image/MaskedImage.h"
    #include "lsst/pex/logging/Trace.h"
    30 1192e949 - #include "lsst/afw/math/Kernel.h"
    ? -------
    29 a9aec7fc + #include "lsst/afw/math.h"
    31 1192e949 - #include "lsst/afw/math/KernelFunctions.h"
    30 a9aec7fc + #include "lsst/afw/image.h"
    33 52012c0a - using namespace std;
    namespace pexLog = lsst::pex::logging; namespace afwImage = lsst::afw::image; namespace afwMath = lsst::afw::math;
    38 52012c0a - const std::string outFile("svcOut");
    ? ^^^
    36 a9aec7fc + const std::string outImagePath("svcOut.fits");
    ? ^^^^ ++++ +++++ /** * Demonstrate convolution with a spatially varying kernel * * The kernel is a Gaussian that varies as follows: * xSigma varies linearly from minSigma to maxSigma as image col goes from 0 to max * ySigma varies linearly from minSigma to maxSigma as image row goes from 0 to max */ int main(int argc, char **argv) { typedef afwMath::Kernel::Pixel Pixel; pexLog::Trace::setDestination(std::cout); pexLog::Trace::setVerbosity("lsst.afw.kernel", 5); double minSigma = 0.1; double maxSigma = 3.0; unsigned int kernelCols = 5; unsigned int kernelRows = 5;
    58 8c6c0d93 - std::string mimg;
    ? ^^
    56 a9aec7fc + std::string inImagePath;
    ? +++ ^ +++++ if (argc < 2) {
    60 8c6c0d93 - std::string afwdata = getenv("AFWDATA_DIR");
    61 8c6c0d93 - if (afwdata.empty()) {
    58 a9aec7fc + try {
    59 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
    60 a9aec7fc + inImagePath = dataDir + "/data/small.fits";
    61 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    62 8c6c0d93 - std::cerr << "Usage: simpleConvolve fitsFile" << std::endl;
    ? ^^ ^
    62 a9aec7fc + std::cerr << "Usage: spatiallyVaryingConvolve [fitsFile]" << std::endl;
    ? +++ ^ ^^^^^^^^^ + +
    63 a9aec7fc + std::cerr << "fitsFile is the path to a masked image" << std::endl;
    63 8c6c0d93 - std::cerr << "fitsFile excludes the \"_img.fits\" suffix" << std::endl;
    64 8c6c0d93 - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << std::endl;
    65 8c6c0d93 - std::cerr << "Is afwdata set up?\n" << std::endl;
    ? ^ ^^^^
    64 a9aec7fc + std::cerr << "\nError: setup afwdata or specify fitsFile.\n" << std::endl;
    ? ^^^^^^^^^ ++++ +++ + +++++++ ^^^^^^ exit(EXIT_FAILURE);
    67 8c6c0d93 - } else {
    68 8c6c0d93 - mimg = afwdata + "/small_MI";
    69 8c6c0d93 - std::cerr << "Using " << mimg << std::endl;
    } } else {
    72 8c6c0d93 - mimg = std::string(argv[1]);
    ? ^^
    68 a9aec7fc + inImagePath = std::string(argv[1]);
    ? +++ ^ +++++ }
    70 a9aec7fc + std::cerr << "Convolving masked image " << inImagePath << std::endl;
    // read in fits file
    76 8c6c0d93 - afwImage::MaskedImage mImage(mimg);
    ? ^^
    73 a9aec7fc + afwImage::MaskedImage mImage(inImagePath);
    ? +++ ^ +++++ // construct kernel afwMath::GaussianFunction2 gaussFunc(1, 1, 0); unsigned int polyOrder = 1; afwMath::PolynomialFunction2 polyFunc(polyOrder); afwMath::AnalyticKernel gaussSpVarKernel(kernelCols, kernelRows, gaussFunc, polyFunc); // Get copy of spatial parameters (all zeros), set and feed back to the kernel
    85 52012c0a - vector > polyParams = gaussSpVarKernel.getSpatialParameters();
    82 a9aec7fc + std::vector > polyParams = gaussSpVarKernel.getSpatialParameters();
    ? +++++ +++++ // Set spatial parameters for kernel parameter 0 polyParams[0][0] = minSigma; polyParams[0][1] = (maxSigma - minSigma)/static_cast(mImage.getWidth()); polyParams[0][2] = 0.0; // Set spatial function parameters for kernel parameter 1 polyParams[1][0] = minSigma; polyParams[1][1] = 0.0; polyParams[1][2] = (maxSigma - minSigma)/static_cast(mImage.getHeight()); gaussSpVarKernel.setSpatialParameters(polyParams);
    96 52012c0a - cout << "Spatial Parameters:" << endl;
    93 a9aec7fc + std::cout << "Spatial Parameters:" << std::endl;
    ? +++++ +++++ for (unsigned int row = 0; row < polyParams.size(); ++row) { if (row == 0) {
    99 52012c0a - cout << "xSigma";
    96 a9aec7fc + std::cout << "xSigma";
    ? +++++ } else {
    101 52012c0a - cout << "ySigma";
    98 a9aec7fc + std::cout << "ySigma";
    ? +++++ } for (unsigned int col = 0; col < polyParams[row].size(); ++col) {
    104 52012c0a - cout << boost::format("%7.1f") % polyParams[row][col];
    101 a9aec7fc + std::cout << boost::format("%7.1f") % polyParams[row][col];
    ? +++++ }
    106 52012c0a - cout << endl;
    103 a9aec7fc + std::cout << std::endl;
    ? +++++ +++++ }
    108 52012c0a - cout << endl;
    105 a9aec7fc + std::cout << std::endl;
    ? +++++ +++++ // convolve afwImage::MaskedImage resMaskedImage(mImage.getDimensions()); afwMath::convolve(resMaskedImage, mImage, gaussSpVarKernel, true); // write results
    115 52012c0a - resMaskedImage.writeFits(outFile);
    ? ^^^
    112 a9aec7fc + resMaskedImage.writeFits(outImagePath);
    ? ^^^^ ++++
    113 a9aec7fc + std::cerr << "Wrote convolved image " << outImagePath << std::endl;
    }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    52012c0a

    commit 52012c0a4be0641b9758c479a033b2ca7a6b5f86
    Author: rowen 
    Date:   Wed Jul 25 00:17:53 2007 +0000
    
        Merge ticket25 to the trunk
    

    1192e949

    commit 1192e9492b9dfbc05ab4c1de8827e39fbecc14a8
    Author: rowen 
    Date:   Tue Jun 24 19:53:51 2008 +0000
    
        Merge in ticket 350.
        (Note: this was done using rsync because I couldn't get
        svnmerge.py to merge any files -- it ran but did nothing).
        
        See ticket 350 for details, but the basics are:
        - Added SeparableKernel, and associated specialized convolution code
        - Modified Kernel::computeImage, Kernel::computeNewImage
          such that doNormalize comes before x, y arguments
          and has no default value (ticket 191).
          Warning: existing code may compile but give wrong answers!
        - Modified convolve such that doNormalize has no default value (ticket 191).
        - Globally modified include paths to use "" instead of <>
          for lsst and 3rd party packages (as per new standard)
        - Added Function::get/setParameter methods
        - Added Kernel::setCtrCol/Row methods
        - Removed radial lanczos from function library;
          only the separable version is now present.
    

    8c6c0d93

    commit 8c6c0d93eaf03478cc6379a16055c3ae6119aa35
    Author: bick 
    Date:   Fri Jan 8 21:49:43 2010 +0000
    
        #1113 Changed examples to default to afwdata fits files with no arguments.
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    include/lsst/afw/geom/XYTransform.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    /**
                     * \file
    
    27 d95640da - * @brief Class representing an invertible transform of a pixelized image
    ? ----------------------
    27 0a8d9c69 + * @brief Class representing an invertible 2D transform
    ? +++ */ #ifndef LSST_AFW_GEOM_XYTRANSFORM_H #define LSST_AFW_GEOM_XYTRANSFORM_H #include #include "boost/shared_ptr.hpp" #include "lsst/pex/exceptions.h" #include "lsst/daf/base.h" #include "lsst/afw/geom/AffineTransform.h" #include "lsst/afw/geom/ellipses.h" namespace lsst { namespace afw { namespace geom { /**
    46 30733e1d + * @brief Virtual base class for 2D transforms
    46 835d6946 - * @brief XYTransform: virtual base class which represents a "pixel domain to pixel domain" transform
    47 835d6946 - *
    48 835d6946 - * An example would be a camera distortion.
    49 835d6946 - * By comparison, class Wcs represents a "pixel domain to celestial" transform.
    50 835d6946 - *
    51 835d6946 - * We allow XYTransforms to operate either in the pixel coordinate system of an individual
    52 835d6946 - * detector, or in the global focal plane coordinate system (with units mm rather than pixel
    53 835d6946 - * counts). The flag XYTransform::_inFpCoordinateSystem distinguishes these two cases, so that
    54 9d9eb8af - * we can throw an exception if the transform is applied in the wrong coordinate system. This
    55 9d9eb8af - * way of keeping track of the coordinate system is sort of clunky and will be improved later.
    */ class XYTransform : public daf::base::Citizen { public: typedef afw::geom::Point2D Point2D;
    61 18e8b2c4 - typedef afw::geom::ellipses::Quadrupole Quadrupole;
    typedef afw::geom::AffineTransform AffineTransform;
    64 a6e8955c - XYTransform(bool inFpCoordinateSystem);
    54 30733e1d + explicit XYTransform();
    virtual ~XYTransform() { } /// returns a deep copy virtual PTR(XYTransform) clone() const = 0; /// returns a "deep inverse" in this sense that the forward+inverse transforms do not share state virtual PTR(XYTransform) invert() const; /** * @brief virtuals for forward and reverse transforms *
    76 955fdb87 - * Both the pixel argument and the return value of these routines:
    77 835d6946 - * - are in pixel units
    78 955fdb87 - * - have XY0 offsets included (i.e. caller may need to add XY0 to pixel
    79 835d6946 - * and subtract XY0 from return value if necessary)
    80 835d6946 - *
    81 835d6946 - * These routines are responsible for throwing exceptions if the 'pixel' arg
    ? ^^^
    66 0a8d9c69 + * These routines are responsible for throwing exceptions if the 'point' arg
    ? + ^^ * is outside the domain of the transform. */
    84 e1996ce6 - virtual Point2D forwardTransform(Point2D const &pixel) const = 0;
    ? ^^^
    69 0a8d9c69 + virtual Point2D forwardTransform(Point2D const &point) const = 0;
    ? + ^^
    85 e1996ce6 - virtual Point2D reverseTransform(Point2D const &pixel) const = 0;
    ? ^^^
    70 0a8d9c69 + virtual Point2D reverseTransform(Point2D const &point) const = 0;
    ? + ^^ /** * @brief linearized forward and reversed transforms *
    90 835d6946 - * These guys are virtual but not pure virtual; there is a default implementation which
    ? -----
    75 0a8d9c69 + * These are virtual but not pure virtual; there is a default implementation which
    * calls forwardTransform() or reverseTransform() and takes finite differences with step
    92 835d6946 - * size equal to one pixel.
    ? ------
    77 0a8d9c69 + * size equal to one.
    * * The following should always be satisfied for an arbitrary Point2D p * (and analogously for the reverse transform) * this->forwardTransform(p) == this->linearizeForwardTransform(p)(p); */
    98 a6e8955c - virtual AffineTransform linearizeForwardTransform(Point2D const &pixel) const;
    ? ^^^
    83 0a8d9c69 + virtual AffineTransform linearizeForwardTransform(Point2D const &point) const;
    ? + ^^
    99 a6e8955c - virtual AffineTransform linearizeReverseTransform(Point2D const &pixel) const;
    ? ^^^
    84 0a8d9c69 + virtual AffineTransform linearizeReverseTransform(Point2D const &point) const;
    ? + ^^
    100 e1996ce6 -
    101 835d6946 - /// apply distortion to an (infinitesimal) quadrupole
    102 f521567c - Quadrupole forwardTransform(Point2D const &pixel, Quadrupole const &q) const;
    103 f521567c - Quadrupole reverseTransform(Point2D const &pixel, Quadrupole const &q) const;
    104 f521567c -
    105 a6e8955c - bool inFpCoordinateSystem() const { return _inFpCoordinateSystem; }
    106 0a5ba669 -
    107 0a5ba669 - protected:
    108 a6e8955c - bool _inFpCoordinateSystem;
    }; /**
    113 835d6946 - * @brief IdentityXYTransform: Represents a trivial XYTransform satisfying f(x)=x.
    89 30733e1d + * @brief A trivial XYTransform satisfying f(x)=x.
    */ class IdentityXYTransform : public XYTransform { public:
    118 a6e8955c - IdentityXYTransform(bool inFpCoordinateSystem);
    119 e701b280 - virtual ~IdentityXYTransform() { }
    ? --------- ^^^^
    94 0a8d9c69 + IdentityXYTransform();
    ? ^ virtual PTR(XYTransform) clone() const;
    122 e701b280 - virtual Point2D forwardTransform(Point2D const &pixel) const;
    ? ^^^
    97 0a8d9c69 + virtual Point2D forwardTransform(Point2D const &point) const;
    ? + ^^
    123 e701b280 - virtual Point2D reverseTransform(Point2D const &pixel) const;
    ? ^^^
    98 0a8d9c69 + virtual Point2D reverseTransform(Point2D const &point) const;
    ? + ^^
    124 a6e8955c - virtual AffineTransform linearizeForwardTransform(Point2D const &pixel) const;
    ? ^^^
    99 0a8d9c69 + virtual AffineTransform linearizeForwardTransform(Point2D const &point) const;
    ? + ^^
    125 a6e8955c - virtual AffineTransform linearizeReverseTransform(Point2D const &pixel) const;
    ? ^^^
    100 0a8d9c69 + virtual AffineTransform linearizeReverseTransform(Point2D const &point) const;
    ? + ^^ }; /**
    105 30733e1d + * @brief Wrap an XYTransform, swapping forward and reverse transforms.
    130 835d6946 - * @brief This class supplies a default ->invert() method which works for any XYTransform
    131 835d6946 - * (but can be overridden if something more efficient exists)
    */ class InvertedXYTransform : public XYTransform { public: InvertedXYTransform(CONST_PTR(XYTransform) base);
    137 48ac4e21 - virtual ~InvertedXYTransform() { }
    virtual PTR(XYTransform) clone() const;
    113 0a8d9c69 + /** @brief Return the wrapped XYTransform */
    virtual PTR(XYTransform) invert() const;
    141 48ac4e21 - virtual Point2D forwardTransform(Point2D const &pixel) const;
    ? ^^^
    115 0a8d9c69 + virtual Point2D forwardTransform(Point2D const &point) const;
    ? + ^^
    142 48ac4e21 - virtual Point2D reverseTransform(Point2D const &pixel) const;
    ? ^^^
    116 0a8d9c69 + virtual Point2D reverseTransform(Point2D const &point) const;
    ? + ^^
    143 a6e8955c - virtual AffineTransform linearizeForwardTransform(Point2D const &pixel) const;
    ? ^^^
    117 0a8d9c69 + virtual AffineTransform linearizeForwardTransform(Point2D const &point) const;
    ? + ^^
    144 a6e8955c - virtual AffineTransform linearizeReverseTransform(Point2D const &pixel) const;
    ? ^^^
    118 0a8d9c69 + virtual AffineTransform linearizeReverseTransform(Point2D const &point) const;
    ? + ^^ protected: CONST_PTR(XYTransform) _base; }; /**
    152 835d6946 - * @brief RadialXYTransform: represents a purely radial polynomial distortion, up to 6th order.
    126 a8afb4cc + * @brief Wrap a sequence of multiple XYTransforms
    127 a8afb4cc + *
    128 a8afb4cc + * forwardTransform executes transformList[i].forwardTransform in order 0, 1, 2..., e.g.
    129 a8afb4cc + *
    130 a8afb4cc + * MultiXYTransform.forwardTransform(p) =
    131 a8afb4cc + * transformList[n].forwardTransform(...(transformList[1].forwardTransform(transformList[0].forwardTransform(p))...)
    153 835d6946 - *
    132 a8afb4cc + */
    ? +
    154 835d6946 - * Note: this transform is always in the focal plane coordinate system but can be
    155 835d6946 - * combined with DetectorXYTransform below to get the distortion for an individual detector.
    133 a8afb4cc + class MultiXYTransform : public XYTransform
    134 a8afb4cc + {
    135 a8afb4cc + public:
    136 a8afb4cc + typedef std::vector TransformList;
    137 a8afb4cc + MultiXYTransform(TransformList const &transformList);
    138 a8afb4cc + virtual PTR(XYTransform) clone() const;
    139 a8afb4cc + virtual Point2D forwardTransform(Point2D const &point) const;
    140 a8afb4cc + virtual Point2D reverseTransform(Point2D const &point) const;
    141 a8afb4cc + virtual AffineTransform linearizeForwardTransform(Point2D const &point) const;
    142 a8afb4cc + virtual AffineTransform linearizeReverseTransform(Point2D const &point) const;
    143 a8afb4cc + TransformList getTransformList() const { return _transformList; }
    144 a8afb4cc + private:
    145 a8afb4cc + TransformList _transformList;
    146 a8afb4cc + };
    147 a8afb4cc +
    148 a8afb4cc + /**
    149 30733e1d + * @brief Wrap an AffineTransform
    150 0ac8b7e8 + *
    151 0ac8b7e8 + */
    152 0ac8b7e8 + class AffineXYTransform : public XYTransform
    153 0ac8b7e8 + {
    154 0ac8b7e8 + public:
    155 0ac8b7e8 + AffineXYTransform(AffineTransform const &affineTransform);
    156 0ac8b7e8 +
    157 0ac8b7e8 + virtual PTR(XYTransform) clone() const;
    158 0ac8b7e8 + virtual Point2D forwardTransform(Point2D const &position) const;
    159 0ac8b7e8 + virtual Point2D reverseTransform(Point2D const &position) const;
    160 0ac8b7e8 + virtual AffineTransform linearizeForwardTransform(Point2D const &position) const;
    161 0ac8b7e8 + virtual AffineTransform linearizeReverseTransform(Point2D const &position) const;
    162 30733e1d + /// get underlying forward AffineTransform
    163 30733e1d + AffineTransform getForwardTransform() const;
    164 30733e1d + /// get underlying reverse AffineTransform
    165 30733e1d + AffineTransform getReverseTransform() const;
    166 0ac8b7e8 +
    167 0ac8b7e8 + protected:
    168 0ac8b7e8 + AffineTransform _forwardAffineTransform;
    169 0ac8b7e8 + AffineTransform _reverseAffineTransform;
    170 0ac8b7e8 + };
    171 0ac8b7e8 +
    172 0ac8b7e8 +
    173 0ac8b7e8 + /**
    174 30733e1d + * @brief A purely radial polynomial distortion, up to 6th order.
    175 835d6946 + *
    176 30733e1d + * forwardTransform(pt) = pt * scale
    177 30733e1d + * where:
    178 30733e1d + * - scale = (coeffs[1] r + coeffs[2] r^2 + ...) / r
    179 30733e1d + * - r = magnitude of pt
    180 0a8d9c69 + *
    181 30733e1d + * @warning reverseTransform will fail if the polynomial is too far from linear (ticket #3152)
    182 0a8d9c69 + *
    183 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if coeffs.size() > 0 and any of
    184 0a8d9c69 + * the following are true: coeffs.size() == 1, coeffs[0] != 0 or coeffs[1] == 0
    */ class RadialXYTransform : public XYTransform { public:
    160 dd97c30a - RadialXYTransform(std::vector const &coeffs, bool coefficientsDistort=true);
    161 dd97c30a - virtual ~RadialXYTransform() { }
    ? --------- -----
    189 0a8d9c69 + RadialXYTransform(
    190 30733e1d + std::vector const &coeffs ///< radial polynomial coefficients;
    191 0a8d9c69 + ///< if size == 0 then gives the identity transformation;
    192 0a8d9c69 + ///< otherwise must satisfy: size > 1, coeffs[0] == 0, and coeffs[1] != 0
    193 0a8d9c69 + );
    virtual PTR(XYTransform) clone() const; virtual PTR(XYTransform) invert() const;
    165 dd97c30a - virtual Point2D forwardTransform(Point2D const &pixel) const;
    ? ^^^
    197 0a8d9c69 + virtual Point2D forwardTransform(Point2D const &point) const;
    ? + ^^
    166 dd97c30a - virtual Point2D reverseTransform(Point2D const &pixel) const;
    ? ^^^
    198 0a8d9c69 + virtual Point2D reverseTransform(Point2D const &point) const;
    ? + ^^
    167 dd97c30a - virtual AffineTransform linearizeForwardTransform(Point2D const &pixel) const;
    ? ^^^
    199 0a8d9c69 + virtual AffineTransform linearizeForwardTransform(Point2D const &point) const;
    ? + ^^
    168 dd97c30a - virtual AffineTransform linearizeReverseTransform(Point2D const &pixel) const;
    ? ^^^
    200 0a8d9c69 + virtual AffineTransform linearizeReverseTransform(Point2D const &point) const;
    ? + ^^
    201 e72c7130 + std::vector getCoeffs() const { return _coeffs; }
    /** * @brief These static member functions operate on polynomials represented by vector. * * They are intended mainly as helpers for the virtual member functions above, but are declared * public since there are also some unit tests which call them. */ static std::vector polyInvert(std::vector const &coeffs); static double polyEval(std::vector const &coeffs, double x); static Point2D polyEval(std::vector const &coeffs, Point2D const &p); static double polyEvalDeriv(std::vector const &coeffs, double x); static AffineTransform polyEvalJacobian(std::vector const &coeffs, Point2D const &p); static double polyEvalInverse(std::vector const &coeffs, std::vector const &icoeffs, double x); static Point2D polyEvalInverse(std::vector const &coeffs, std::vector const &icoeffs, Point2D const &p); static AffineTransform polyEvalInverseJacobian(std::vector const &coeffs, std::vector const &icoeffs, Point2D const &p); static AffineTransform makeAffineTransform(double x, double y, double f, double g); protected: std::vector _coeffs; std::vector _icoeffs;
    200 dd97c30a - bool _coefficientsDistort;
    }; }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    a6e8955c

    commit a6e8955c7b40f8954863e1dcd0092c1a2701eafb
    Author: Kendrick Smith 
    Date:   Fri Feb 8 13:28:12 2013 -0500
    
        cleanup, add comments
    

    d95640da

    commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
    Author: Kendrick Smith 
    Date:   Tue Feb 19 23:44:14 2013 -0500
    
        move afw::image::XYTransform -> afw::geom::XYTransform
             afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
             afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
        
        wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom
    

    955fdb87

    commit 955fdb8793255b243261f56e85e36112ae6b6a79
    Author: Naoki Yasuda 
    Date:   Wed Apr 3 14:42:59 2013 +0900
    
        Change interpolation style depending on the number of available data points.
        Suppress some warnings during compilation.
    

    48ac4e21

    commit 48ac4e2159493034950651ab26088f503e79efdf
    Author: Kendrick Smith 
    Date:   Thu Jan 10 12:33:48 2013 -0500
    
        tweak XYTransform::invert() logic
    

    dd97c30a

    commit dd97c30a654e470f55aa39df0b90445b5877c2d5
    Author: Kendrick Smith 
    Date:   Mon Feb 4 15:33:01 2013 -0500
    
        add class RadialXYTransform
    

    f521567c

    commit f521567c57ba5e52e02ccc4b94d76ce4799ff0c8
    Author: Kendrick Smith 
    Date:   Mon Feb 4 16:41:08 2013 -0500
    
        XYTransform member functions to distort Quadrupoles
    

    18e8b2c4

    commit 18e8b2c4267bfe33fc68d4616d3b92f8f183402f
    Author: Kendrick Smith 
    Date:   Sat Feb 16 13:17:13 2013 -0500
    
        remove some lsst::'s
    

    e701b280

    commit e701b280170e48b6cd0c7dcef21abd351f94c990
    Author: Kendrick Smith 
    Date:   Tue Jan 29 14:58:39 2013 -0500
    
        IdentityXYTransform class
    

    9d9eb8af

    commit 9d9eb8afed792078da906a0e7c91c6ee510ad43c
    Author: Kendrick Smith 
    Date:   Wed Feb 20 00:45:06 2013 -0500
    
        add comment
    

    835d6946

    commit 835d69460ec124e6670e10726164395cf47d0853
    Author: Kendrick Smith 
    Date:   Sat Feb 16 13:12:57 2013 -0500
    
        doxygenize
    

    0a5ba669

    commit 0a5ba6691461a9ba3a61b11eda9494ab776f6d6a
    Author: Kendrick Smith 
    Date:   Mon Feb 4 16:22:02 2013 -0500
    
        class DetectorXYTransform
    

    e1996ce6

    commit e1996ce6b044a5977a9693420f5f9837947ec5eb
    Author: Kendrick Smith 
    Date:   Wed Dec 19 14:21:49 2012 -0500
    
        add XYTransform.h, XYTransform.cc (compiles but untested)
    

    Commits in /Users/nate/repos_lsst/afw/

    30733e1d

    commit 30733e1d3a4482e46e4d7de22fd39dbbb0ba1560
    Author: Russell Owen 
    Date:   Thu Feb 27 16:27:41 2014 -0800
    
        Fixes in response to the first review.
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    0a8d9c69

    commit 0a8d9c69b9efa9a486595305a950ce02ab1c2ade
    Author: Russell Owen 
    Date:   Tue Feb 18 17:31:35 2014 -0800
    
        Removed inFpCoordinateSystem flag from XYTransform.
    

    e72c7130

    commit e72c713067a8e785b42645b8ffe5c1a53b558641
    Author: Russell Owen 
    Date:   Sat Mar 1 06:08:25 2014 -0800
    
        Add RadialXYTransform.getCoeffs() and test it.
    

    a8afb4cc

    commit a8afb4cc71b25f8e140c7864ae94dd4d381e908e
    Author: Russell Owen 
    Date:   Fri Feb 28 15:29:33 2014 -0800
    
        Add MultiXYTransform, but something has gone wrong.
    

    835d6946

    commit 835d69460ec124e6670e10726164395cf47d0853
    Author: Kendrick Smith 
    Date:   Sat Feb 16 13:12:57 2013 -0500
    
        doxygenize
    

    0ac8b7e8

    commit 0ac8b7e884f4a1fbd6a378ed1f44738157624b75
    Author: Simon Krughoff 
    Date:   Fri Feb 7 15:22:02 2014 -0600
    
        Implementation of AffineXYTransform.  Switched Orientation to return AffineXYTransform instead of AffineTransform
    

    Return to list

    tests/offsetImage.py

    Diff:

    1 74a931c5 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for offsetting images in (dx, dy) Run with: python offsetImage.py or python >>> import offsetImage; offsetImage.run() """ import math import unittest import numpy import lsst.utils.tests as utilsTests
    40 74a931c5 - import lsst.daf.base
    import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom import lsst.afw.display.ds9 as ds9
    45 4d9957d5 - import lsst.afw.image.testUtils as imTestUtils
    try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class offsetImageTestCase(unittest.TestCase): """A test case for offsetImage""" def setUp(self): self.inImage = afwImage.ImageF(200, 100) self.background = 200 self.inImage.set(self.background) def tearDown(self): del self.inImage def testSetFluxConvervation(self): """Test that flux is preserved""" for algorithm in ("lanczos5", "bilinear", "nearest"): outImage = afwMath.offsetImage(self.inImage, 0, 0, algorithm) self.assertEqual(outImage.get(50, 50), self.background) outImage = afwMath.offsetImage(self.inImage, 0.5, 0, algorithm) self.assertAlmostEqual(outImage.get(50, 50), self.background, 4) outImage = afwMath.offsetImage(self.inImage, 0.5, 0.5, algorithm) self.assertAlmostEqual(outImage.get(50, 50), self.background, 4) def testSetIntegerOffset(self): """Test that we can offset by positive and negative amounts""" self.inImage.set(50, 50, 400) if False and display: frame = 0 ds9.mtv(self.inImage, frame=frame) ds9.pan(50, 50, frame=frame) ds9.dot("+", 50, 50, frame=frame) for algorithm in ("lanczos5", "bilinear", "nearest"): for delta in [-0.49, 0.51]: for dx, dy in [(2, 3), (-2, 3), (-2, -3), (2, -3)]: outImage = afwMath.offsetImage(self.inImage, dx + delta, dy + delta, algorithm) if False and display: frame += 1 ds9.mtv(outImage, frame=frame) ds9.pan(50, 50, frame=frame) ds9.dot("+", 50 + dx + delta - outImage.getX0(), 50 + dy + delta - outImage.getY0(), frame=frame) def calcGaussian(self, im, x, y, amp, sigma1): """Insert a Gaussian into the image centered at (x, y)""" x = x - im.getX0() y = y - im.getY0() for ix in range(im.getWidth()): for iy in range(im.getHeight()): r2 = math.pow(x - ix, 2) + math.pow(y - iy, 2) val = math.exp(-r2/(2.0*pow(sigma1, 2))) im.set(ix, iy, amp*val) def testOffsetGaussian(self): """Insert a Gaussian, offset, and check the residuals""" size = 50 refIm = afwImage.ImageF(size, size) unshiftedIm = afwImage.ImageF(size, size) xc, yc = size/2.0, size/2.0 amp, sigma1 = 1.0, 3 # # Calculate Gaussian directly at (xc, yc) # self.calcGaussian(refIm, xc, yc, amp, sigma1) for dx in (-55.5, -1.500001, -1.5, -1.499999, -1.00001, -1.0, -0.99999, -0.5, 0.0, 0.5, 0.99999, 1.0, 1.00001, 1.499999, 1.5, 1.500001, 99.3): for dy in (-3.7, -1.500001, -1.5, -1.499999, -1.00001, -1.0, -0.99999, -0.5, 0.0, 0.5, 0.99999, 1.0, 1.00001, 1.499999, 1.5, 1.500001, 2.99999): dOrigX, dOrigY, dFracX, dFracY = getOrigFracShift(dx, dy) self.calcGaussian(unshiftedIm, xc - dFracX, yc - dFracY, amp, sigma1) for algorithm, maxMean, maxLim in ( ("lanczos5", 1e-8, 0.0015), ("bilinear", 1e-8, 0.03), ("nearest", 1e-8, 0.2), ): im = afwImage.ImageF(size, size) im = afwMath.offsetImage(unshiftedIm, dx, dy, algorithm) if display: ds9.mtv(im, frame=0) im -= refIm if display: ds9.mtv(im, frame=1) imArr = im.getArray() imGoodVals = numpy.ma.array(imArr, copy=False, mask=numpy.isnan(imArr)).compressed() try: imXY0 = tuple(im.getXY0()) self.assertEqual(imXY0, (dOrigX, dOrigY)) self.assertLess(abs(imGoodVals.mean()), maxMean*amp) self.assertLess(abs(imGoodVals.max()), maxLim*amp) self.assertLess(abs(imGoodVals.min()), maxLim*amp) except: print "failed on algorithm=%s; dx = %s; dy = %s" % (algorithm, dx, dy) raise # the following would be preferable if there was an easy way to NaN pixels # # stats = afwMath.makeStatistics(im, afwMath.MEAN | afwMath.MAX | afwMath.MIN) # # if not False: # print "mean = %g, min = %g, max = %g" % (stats.getValue(afwMath.MEAN), # stats.getValue(afwMath.MIN), # stats.getValue(afwMath.MAX)) # # self.assertTrue(abs(stats.getValue(afwMath.MEAN)) < 1e-7) # self.assertTrue(abs(stats.getValue(afwMath.MIN)) < 1.2e-3*amp) # self.assertTrue(abs(stats.getValue(afwMath.MAX)) < 1.2e-3*amp) def getOrigFracShift(dx, dy): """Return the predicted integer shift to XY0 and the fractional shift that offsetImage will use offsetImage preserves the origin if dx and dy both < 1 pixel; larger shifts are to the nearest pixel. """ if (abs(dx) < 1) and (abs(dy) < 1): return (0, 0, dx, dy) dOrigX = math.floor(dx + 0.5) dOrigY = math.floor(dy + 0.5) dFracX = dx - dOrigX dFracY = dy - dOrigY return (int(dOrigX), int(dOrigY), dFracX, dFracY) class transformImageTestCase(unittest.TestCase): """A test case for rotating images""" def setUp(self): self.inImage = afwImage.ImageF(20, 10) self.inImage.set(0, 0, 100) self.inImage.set(10, 0, 50) def tearDown(self): del self.inImage def testRotate(self): """Test that we end up with the correct image after rotating by 90 degrees""" for nQuarter, x, y in [(0, 0, 0), (1, 9, 0), (2, 19, 9), (3, 0, 19)]: outImage = afwMath.rotateImageBy90(self.inImage, nQuarter) if display: ds9.mtv(outImage, frame=nQuarter, title="out %d" % nQuarter) self.assertEqual(self.inImage.get(0, 0), outImage.get(x, y)) def testFlip(self): """Test that we end up with the correct image after flipping it""" frame = 2 for flipLR, flipTB, x, y in [(True, False, 19, 0), (True, True, 19, 9), (False, True, 0, 9), (False, False, 0, 0)]: outImage = afwMath.flipImage(self.inImage, flipLR, flipTB) if display: ds9.mtv(outImage, frame=frame, title="%s %s" % (flipLR, flipTB)) frame += 1 self.assertEqual(self.inImage.get(0, 0), outImage.get(x, y)) def testMask(self): """Test that we can flip a Mask""" mask = afwImage.MaskU(10, 20) afwMath.flipImage(mask, True, False) # for a while, swig couldn't handle the resulting Mask::Ptr #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class binImageTestCase(unittest.TestCase): """A test case for binning images""" def setUp(self): pass def tearDown(self): pass def testBin(self): """Test that we can bin images""" inImage = afwImage.ImageF(203, 131) inImage.set(1) bin = 4 outImage = afwMath.binImage(inImage, bin) self.assertEqual(outImage.getWidth(), inImage.getWidth()//bin) self.assertEqual(outImage.getHeight(), inImage.getHeight()//bin) stats = afwMath.makeStatistics(outImage, afwMath.MAX | afwMath.MIN) self.assertEqual(stats.getValue(afwMath.MIN), 1) self.assertEqual(stats.getValue(afwMath.MAX), 1)
    264 4524b66d - def testBin(self):
    263 b80fe1d3 + def testBin2(self):
    ? + """Test that we can bin images anisotropically""" inImage = afwImage.ImageF(203, 131) val = 1 inImage.set(val) binX, binY = 2, 4 outImage = afwMath.binImage(inImage, binX, binY) self.assertEqual(outImage.getWidth(), inImage.getWidth()//binX) self.assertEqual(outImage.getHeight(), inImage.getHeight()//binY) stats = afwMath.makeStatistics(outImage, afwMath.MAX | afwMath.MIN) self.assertEqual(stats.getValue(afwMath.MIN), val) self.assertEqual(stats.getValue(afwMath.MAX), val) inImage.set(0) subImg = inImage.Factory(inImage, afwGeom.BoxI(afwGeom.PointI(4, 4), afwGeom.ExtentI(4, 8)), afwImage.LOCAL) subImg.set(100) del subImg outImage = afwMath.binImage(inImage, binX, binY) if display: ds9.mtv(inImage, frame=2, title="unbinned") ds9.mtv(outImage, frame=3, title="binned %dx%d" % (binX, binY)) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(offsetImageTestCase) suites += unittest.makeSuite(transformImageTestCase) suites += unittest.makeSuite(binImageTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4524b66d

    commit 4524b66d673bec9403da160e3bbe6f2138937174
    Author: rhl 
    Date:   Thu May 19 14:18:21 2011 +0000
    
        Support NxM binning
    

    74a931c5

    commit 74a931c5ef449f522f077892ca26d8db355bb811
    Author: rhl 
    Date:   Tue Mar 3 19:40:48 2009 +0000
    
        Added offsetImage
    

    4d9957d5

    commit 4d9957d519bf0293a85fdd5585bf071afb38dd4b
    Author: rowen 
    Date:   Thu Jun 4 00:18:53 2009 +0000
    
        Implemented ticket #806: improve setting of edge pixels in convolve function.
        Note that this is an API change:
        - the convolve and convolveLinear functions have lost their edgeBit arguments
        - convolved edge pixels are now (NaN, EDGE, info) for MaskedImage and NaN for Image
        All unit tests and examples have been updated accordingly.
        
        Also added the following subroutines to lsst.afw.image.testUtils:
          imagesDiffer, masksDiffer and maskedImagesDiffer
        and modified the following tests to use them:
          ConvolveImage_1.py, ConvolveMaskedImage_1.py and warpExposure_1.py
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    include/lsst/afw/image/Exposure.h

    Diff:

                    // -*- LSST-C++ -*- // fixed format comment for emacs
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    #ifndef LSST_AFW_IMAGE_EXPOSURE_H
                    #define LSST_AFW_IMAGE_EXPOSURE_H
                    
                    #include "boost/cstdint.hpp"
                    #include "boost/shared_ptr.hpp"
                    #include "boost/make_shared.hpp"
                    
                    #include "lsst/base.h"
                    #include "lsst/daf/base.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/image/ExposureInfo.h"
                    
                    namespace lsst { namespace afw {
                    
                    namespace formatters {
                        template class ExposureFormatter;
                    }
                    
                    namespace image {
                    
                    /// A class to contain the data, WCS, and other information needed to describe an %image of the sky
                    template
                    class Exposure : public lsst::daf::base::Persistable,
                                     public lsst::daf::base::Citizen {
                    public:
                        typedef MaskedImage MaskedImageT;
                        typedef boost::shared_ptr Ptr;
                        typedef boost::shared_ptr ConstPtr;
                    
                        // Class Constructors and Destructor
                        explicit Exposure(
                            unsigned int width, unsigned int height,
                            CONST_PTR(Wcs) wcs = CONST_PTR(Wcs)()
                        );
                    
                        explicit Exposure(
                            lsst::afw::geom::Extent2I const & dimensions=lsst::afw::geom::Extent2I(),
                            CONST_PTR(Wcs) wcs = CONST_PTR(Wcs)()
                        );
                    
                        explicit Exposure(
                            lsst::afw::geom::Box2I const & bbox,
                            CONST_PTR(Wcs) wcs = CONST_PTR(Wcs)()
                        );
                    
                        explicit Exposure(MaskedImageT & maskedImage,
                                          CONST_PTR(Wcs) wcs = CONST_PTR(Wcs)());
                    
                        /**
                         *  @brief Construct an Exposure by reading a regular FITS file.
                         *
                         *  @param[in]      fileName      File to read.
                         *  @param[in]      bbox          If non-empty, read only the pixels within the bounding box.
                         *  @param[in]      origin        Coordinate system of the bounding box; if PARENT, the bounding box
                         *                                should take into account the xy0 saved with the image.
                         *  @param[in]      conformMasks  If true, make Mask conform to the mask layout in the file.
                         */
                        explicit Exposure(
                            std::string const & fileName, geom::Box2I const& bbox=geom::Box2I(),
    
    85 271e8097 - ImageOrigin origin=LOCAL, bool conformMasks=false
    ? ^^^ ^
    85 93994d54 + ImageOrigin origin=PARENT, bool conformMasks=false
    ? ^ ^^^^ ); /** * @brief Construct an Exposure by reading a FITS image in memory. * * @param[in] manager An object that manages the memory buffer to read. * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. * @param[in] conformMasks If true, make Mask conform to the mask layout in the file. */ explicit Exposure( fits::MemFileManager & manager, geom::Box2I const & bbox=geom::Box2I(),
    99 271e8097 - ImageOrigin origin=LOCAL, bool conformMasks=false
    ? ^^^ ^
    99 93994d54 + ImageOrigin origin=PARENT, bool conformMasks=false
    ? ^ ^^^^ ); /** * @brief Construct an Exposure from an already-open FITS object. * * @param[in] fitsfile A FITS object to read from. Current HDU is ignored. * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. * @param[in] conformMasks If true, make Mask conform to the mask layout in the file. */ explicit Exposure( fits::Fits & fitsfile, geom::Box2I const & bbox=geom::Box2I(),
    113 271e8097 - ImageOrigin origin=LOCAL, bool conformMasks=false
    ? ^^^ ^
    113 93994d54 + ImageOrigin origin=PARENT, bool conformMasks=false
    ? ^ ^^^^ ); Exposure( Exposure const &src, bool const deep=false ); Exposure( Exposure const &src, lsst::afw::geom::Box2I const& bbox,
    124 bdc29e6a - ImageOrigin const origin=LOCAL,
    ? ^^^ ^
    124 93994d54 + ImageOrigin const origin=PARENT,
    ? ^ ^^^^ bool const deep=false ); /// generalised copy constructor; defined here in the header so that the compiler can instantiate /// N(N-1)/2 conversions between N ImageBase types. /// /// We only support converting the Image part template Exposure(Exposure const& rhs, //!< Input Exposure const bool deep //!< Must be true; needed to disambiguate ) : lsst::daf::base::Citizen(typeid(this)), _maskedImage(rhs.getMaskedImage(), deep), _info(new ExposureInfo(*rhs.getInfo(), deep)) { if (not deep) {
    141 bd598988 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    141 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Exposure's converting copy constructor must make a deep copy"); } } virtual ~Exposure(); // Get Members /// Return the MaskedImage MaskedImageT getMaskedImage() { return _maskedImage; } /// Return the MaskedImage MaskedImageT getMaskedImage() const { return _maskedImage; } CONST_PTR(Wcs) getWcs() const { return _info->getWcs(); } PTR(Wcs) getWcs() { return _info->getWcs(); } /// Return the Exposure's Detector information CONST_PTR(lsst::afw::cameraGeom::Detector) getDetector() const { return _info->getDetector(); } /// Return the Exposure's filter Filter getFilter() const { return _info->getFilter(); } /// Return flexible metadata lsst::daf::base::PropertySet::Ptr getMetadata() const { return _info->getMetadata(); } void setMetadata(lsst::daf::base::PropertySet::Ptr metadata) { _info->setMetadata(metadata); } /// Return the Exposure's width int getWidth() const { return _maskedImage.getWidth(); } /// Return the Exposure's height int getHeight() const { return _maskedImage.getHeight(); } /// Return the Exposure's size geom::Extent2I getDimensions() const { return _maskedImage.getDimensions(); } /** * Return the Exposure's row-origin * * \sa getXY0() */ int getX0() const { return _maskedImage.getX0(); } /** * Return the Exposure's column-origin * * \sa getXY0() */ int getY0() const { return _maskedImage.getY0(); } /** * Return the Exposure's origin * * This will usually be (0, 0) except for images created using the * Exposure(fileName, hdu, BBox, mode) ctor or Exposure(Exposure, BBox) cctor * The origin can be reset with \c setXY0 */ geom::Point2I getXY0() const { return _maskedImage.getXY0(); }
    194 2035d06f - geom::Box2I getBBox(ImageOrigin const origin=LOCAL) const {
    ? ^^^ ^
    194 93994d54 + geom::Box2I getBBox(ImageOrigin const origin=PARENT) const {
    ? ^ ^^^^ return _maskedImage.getBBox(origin); } /** * Set the Exposure's origin (including correcting the Wcs) * * The origin is usually set by the constructor, so you shouldn't need this function * * \note There are use cases (e.g. memory overlays) that may want to set these values, but * don't do so unless you are an Expert. */ void setXY0(geom::Point2I const & origin); // Set Members void setMaskedImage(MaskedImageT &maskedImage); void setWcs(PTR(Wcs) wcs) { _info->setWcs(wcs); } /// Set the Exposure's Detector information void setDetector(CONST_PTR(lsst::afw::cameraGeom::Detector) detector) { _info->setDetector(detector); } /// Set the Exposure's filter void setFilter(Filter const& filter) { _info->setFilter(filter); } /// Set the Exposure's Calib object void setCalib(PTR(Calib) calib) { _info->setCalib(calib); } /// Return the Exposure's Calib object PTR(Calib) getCalib() { return _info->getCalib(); } /// Return the Exposure's Calib object CONST_PTR(Calib) getCalib() const { return _info->getCalib(); } /// Set the Exposure's Psf void setPsf(CONST_PTR(lsst::afw::detection::Psf) psf) { _info->setPsf(psf); } /// Return the Exposure's Psf object PTR(lsst::afw::detection::Psf) getPsf() { return _info->getPsf(); } /// Return the Exposure's Psf object CONST_PTR(lsst::afw::detection::Psf) getPsf() const { return _info->getPsf(); } /// Does this Exposure have a Psf? bool hasPsf() const { return _info->hasPsf(); } /// Does this Exposure have a Wcs? bool hasWcs() const { return _info->hasWcs(); } /// Get the ExposureInfo that aggregates all the non-image components. Never null. PTR(ExposureInfo) getInfo() { return _info; } /// Get the ExposureInfo that aggregates all the non-image components. Never null. CONST_PTR(ExposureInfo) getInfo() const { return _info; } /** * @brief Write an Exposure to a regular multi-extension FITS file. * * @param[in] fileName Name of the file to write. * * As with MaskedImage persistence, an empty primary HDU will be created and all images planes * will be saved to extension HDUs. Most metadata will be saved only to the header of the * main image HDU, but the WCS will be saved to the header of the mask and variance as well. * If present, the Psf will be written to one or more additional HDUs. * * Note that the LSST pixel origin differs from the FITS convention by one, so the values * of CRPIX and LTV saved in the file are not the same as those in the C++ objects in memory, * but are rather modified so they are interpreted by external tools (like ds9). */ void writeFits(std::string const & fileName) const; /** * @brief Write an Exposure to a multi-extension FITS file in memory. * * @param[in] manager Manager for the memory to write to. * * @sa writeFits */ void writeFits(fits::MemFileManager & manager) const; /** * @brief Write an Exposure to an already-open FITS file object. * * @param[in] fitsfile FITS object to write. * * @sa writeFits */ void writeFits(fits::Fits & fitsfile) const; /** * @brief Read an Exposure from a regular FITS file. * * @param[in] filename Name of the file to read. */ static Exposure readFits(std::string const & filename) { return Exposure(filename); } /** * @brief Read an Exposure from a FITS RAM file. * * @param[in] manager Object that manages the memory to be read. */ static Exposure readFits(fits::MemFileManager & manager) { return Exposure(manager); } private: LSST_PERSIST_FORMATTER(lsst::afw::formatters::ExposureFormatter) void _readFits( fits::Fits & fitsfile, geom::Box2I const & bbox, ImageOrigin origin, bool conformMasks ); MaskedImageT _maskedImage; PTR(ExposureInfo) _info; }; /** * A function to return an Exposure of the correct type (cf. std::make_pair) */ template typename Exposure::Ptr makeExposure( MaskedImage & mimage, ///< the Exposure's image CONST_PTR(Wcs) wcs = CONST_PTR(Wcs)() ///< the Exposure's WCS ) { return typename Exposure::Ptr( new Exposure(mimage, wcs)); } }}} // lsst::afw::image #endif // LSST_AFW_IMAGE_EXPOSURE_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    bdc29e6a

    commit bdc29e6ad86424c77ce94df33957b3ee950deb92
    Author: Jim Bosch 
    Date:   Mon Nov 19 11:47:11 2012 -0500
    
        Re-enable RAM FITS reading, remove test cases that just test cfitsio.
    

    bd598988

    commit bd598988ef8c7e1e8c3a62a70aa4df4f44e34ac0
    Author: rhl 
    Date:   Fri Apr 29 16:06:24 2011 +0000
    
        As per KTL, there's no need to convert the metadata as the input Exposure is already known to contain a PropertyList
    

    2035d06f

    commit 2035d06f093eae708fc33e59f8733d7ed9303872
    Author: rhl 
    Date:   Mon Aug 22 19:16:06 2011 +0000
    
        Provided default of LOCAL for ImageOrigin in cctors
    

    271e8097

    commit 271e8097c7ebbadd88d2d43588a80148fdce619a
    Author: Jim Bosch 
    Date:   Mon Nov 19 12:50:21 2012 -0500
    
        Fix up and relocate doxygen for FITS-reading ctors.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    src/image/Calib.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     *
                     * Classes to support calibration (e.g. photometric zero points, exposure times)
                     */
                    #include 
                    
                    #include "boost/format.hpp"
                    #include "boost/lexical_cast.hpp"
                    #include "boost/algorithm/string/trim.hpp"
                    
                    #include "ndarray.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/daf/base/PropertySet.h"
                    #include "lsst/afw/image/Calib.h"
                    #include "lsst/afw/cameraGeom/Detector.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/table/io/InputArchive.h"
                    #include "lsst/afw/table/io/CatalogVector.h"
                    
                    namespace lsst { namespace afw { namespace image {
                    /**
                     * ctor
                     */
                    Calib::Calib() : _midTime(), _exptime(0.0), _fluxMag0(0.0), _fluxMag0Sigma(0.0) {}
                    /**
                     * ctor from a vector of Calibs
                     *
    
    53 e1771d06 - * \note All the input calibs must have the same zeropoint; throw InvalidParameterException if this isn't true
    ? ^^^^^^ ^
    53 21597d88 + * \note All the input calibs must have the same zeropoint; throw InvalidParameterError if this isn't true
    ? ^^ ^ */ Calib::Calib(std::vector const& calibs ///< Set of calibs to be merged ) : _midTime(), _exptime(0.0), _fluxMag0(0.0), _fluxMag0Sigma(0.0) { if (calibs.empty()) {
    60 e1771d06 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    60 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "You must provide at least one input Calib"); } double const fluxMag00 = calibs[0]->_fluxMag0; double const fluxMag0Sigma0 = calibs[0]->_fluxMag0Sigma; double midTimeSum = 0.0; // sum(time*expTime) for (std::vector::const_iterator ptr = calibs.begin(); ptr != calibs.end(); ++ptr) { Calib const& calib = **ptr; if (::fabs(fluxMag00 - calib._fluxMag0) > std::numeric_limits::epsilon() || ::fabs(fluxMag0Sigma0 - calib._fluxMag0Sigma) > std::numeric_limits::epsilon()) {
    73 e1771d06 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    73 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("You may only combine calibs with the same fluxMag0: " "%g +- %g v %g +- %g") % calib.getFluxMag0().first % calib.getFluxMag0().second % calibs[0]->getFluxMag0().first % calibs[0]->getFluxMag0().second ).str()); } double const exptime = calib._exptime; midTimeSum += calib._midTime.get()*exptime; _exptime += exptime; } daf::base::DateTime tmp(midTimeSum/_exptime); // there's no way to set the double value directly using std::swap; swap(_midTime, tmp); } /** * ctor */ Calib::Calib(CONST_PTR(lsst::daf::base::PropertySet) metadata) { lsst::daf::base::DateTime midTime; double exptime = 0.0; double fluxMag0 = 0.0, fluxMag0Sigma = 0.0; std::string key = "TIME-MID"; if (metadata->exists(key)) { midTime = lsst::daf::base::DateTime(boost::algorithm::trim_right_copy(metadata->getAsString(key))); } key = "EXPTIME"; if (metadata->exists(key)) { try { exptime = metadata->getAsDouble(key);
    109 db43227e - } catch (daf::base::TypeMismatchException & err) {
    109 21597d88 + } catch (lsst::pex::exceptions::TypeError & err) {
    std::string exptimeStr = metadata->getAsString(key); exptime = boost::lexical_cast(exptimeStr); } } key = "FLUXMAG0"; if (metadata->exists(key)) { fluxMag0 = metadata->getAsDouble(key); key = "FLUXMAG0ERR"; if (metadata->exists(key)) { fluxMag0Sigma = metadata->getAsDouble(key); } } _midTime = midTime; _exptime = exptime; _fluxMag0 = fluxMag0; _fluxMag0Sigma = fluxMag0Sigma; } /** * Control whether we throw an exception when faced with a negative flux */ bool Calib::_throwOnNegativeFlux = true; /** * Set whether Calib should throw an exception when asked to convert a flux to a magnitude */ void Calib::setThrowOnNegativeFlux(bool raiseException ///< Should the exception be raised? ) { _throwOnNegativeFlux = raiseException; } /** * Tell me whether Calib will throw an exception if asked to convert a flux to a magnitude */ bool Calib::getThrowOnNegativeFlux() { return _throwOnNegativeFlux; } namespace detail { /** * Remove Calib-related keywords from the metadata * * \return Number of keywords stripped */ int stripCalibKeywords(PTR(lsst::daf::base::PropertySet) metadata ///< Metadata to be stripped ) { int nstripped = 0; std::string key = "TIME-MID"; if (metadata->exists(key)) { metadata->remove(key); nstripped++; } key = "EXPTIME"; if (metadata->exists(key)) { metadata->remove(key); nstripped++; } key = "FLUXMAG0"; if (metadata->exists(key)) { metadata->remove(key); nstripped++; } key = "FLUXMAG0ERR"; if (metadata->exists(key)) { metadata->remove(key); nstripped++; } return nstripped; } } /** * Are two Calibs identical? * * \note Maybe this should be an approximate comparison */ bool Calib::operator==(Calib const& rhs) const { return ::fabs(_midTime.get() - rhs._midTime.get()) < std::numeric_limits::epsilon() && _exptime == rhs._exptime && _fluxMag0 == rhs._fluxMag0 && _fluxMag0Sigma == rhs._fluxMag0Sigma; } /** * Set the time of the middle of an exposure * * \note In general this is a function of position of the position of the detector in the focal plane */ void Calib::setMidTime(lsst::daf::base::DateTime const& midTime ///< Time at middle of exposure ) { _midTime = midTime; } /** * Return the time at the middle of an exposure */ lsst::daf::base::DateTime Calib::getMidTime () const { return _midTime; } /** * Return the time at the middle of an exposure at the specified position in the focal plane (as * described by a cameraGeom::Detector) * * @warning This implementation ignores its arguments! */ lsst::daf::base::DateTime Calib::getMidTime( boost::shared_ptr, ///< description of focal plane (ignored) lsst::afw::geom::Point2I const& ///< position in focal plane (ignored) ) const { return _midTime; } /** * Set the length of an exposure */ void Calib::setExptime(double exptime ///< the length of the exposure (s) ) { _exptime = exptime; } /** * Return the length of an exposure in seconds */ double Calib::getExptime() const { return _exptime; } /** * Set the flux of a zero-magnitude object */ void Calib::setFluxMag0(double fluxMag0, ///< The flux in question (ADUs) double fluxMag0Sigma ///< The error in the flux (ADUs) ) { _fluxMag0 = fluxMag0; _fluxMag0Sigma = fluxMag0Sigma; } void Calib::setFluxMag0(std::pair fluxMag0AndSigma ///< The flux and error (ADUs) ) { _fluxMag0 = fluxMag0AndSigma.first; _fluxMag0Sigma = fluxMag0AndSigma.second; } /** * Return the flux, and error in flux, of a zero-magnitude object */ std::pair Calib::getFluxMag0() const { return std::make_pair(_fluxMag0, _fluxMag0Sigma); } namespace { inline void checkNegativeFlux0(double fluxMag0) { if (fluxMag0 <= 0) {
    282 12def164 - throw LSST_EXCEPT(lsst::pex::exceptions::DomainErrorException,
    ? ---------
    282 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::DomainError,
    (boost::format("Flux of 0-mag object must be >= 0: saw %g") % fluxMag0).str()); } } inline bool isNegativeFlux(double flux, bool doThrow) { if (flux <= 0) { if (doThrow) {
    290 12def164 - throw LSST_EXCEPT(lsst::pex::exceptions::DomainErrorException,
    ? ---------
    290 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::DomainError,
    (boost::format("Flux must be >= 0: saw %g") % flux).str()); } return true; } return false; } inline double convertToFlux(double fluxMag0, double mag) { return fluxMag0 * ::pow(10.0, -0.4 * mag); } inline double convertToFluxErr(double fluxMag0InvSNR, double flux, double magErr) { // Want to: // return flux * hypot(_fluxMag0Sigma/_fluxMag0, 0.4*std::log(10)*magSigma/mag); // But hypot is not standard C++ so use double a = fluxMag0InvSNR; double b = 0.4 * std::log(10.0) * magErr; if (std::abs(a) < std::abs(b)) { std::swap(a, b); } return flux * std::abs(a) * std::sqrt(1 + std::pow(b / a, 2)); } inline double convertToMag(double fluxMag0, double flux) { return -2.5*::log10(flux/fluxMag0); } inline void convertToMagWithErr(double *mag, double *magErr, double fluxMag0, double fluxMag0InvSNR, double flux, double fluxErr) { double const rat = flux/fluxMag0; double const ratErr = ::sqrt((::pow(fluxErr, 2) + ::pow(flux*fluxMag0InvSNR, 2))/::pow(fluxMag0, 2)); *mag = -2.5*::log10(rat); *magErr = 2.5/::log(10.0)*ratErr/rat; } } // anonymous namespace /** * Return a flux (in ADUs) given a magnitude */ double Calib::getFlux(double const mag ///< the magnitude of the object ) const { checkNegativeFlux0(_fluxMag0); return convertToFlux(_fluxMag0, mag); } ndarray::Array Calib::getFlux(ndarray::Array const & mag) const { checkNegativeFlux0(_fluxMag0); ndarray::Array flux = ndarray::allocate(mag.size()); ndarray::Array::Iterator inIter = mag.begin(); ndarray::Array::Iterator outIter = flux.begin(); for (; inIter != mag.end(); ++inIter, ++outIter) { *outIter = convertToFlux(_fluxMag0, *inIter); } return flux; } /** * Return a flux and flux error (in ADUs) given a magnitude and magnitude error * * Assumes that the errors are small and uncorrelated. */ std::pair Calib::getFlux( double const mag, ///< the magnitude of the object double const magSigma ///< the error in the magnitude ) const { checkNegativeFlux0(_fluxMag0); double const flux = convertToFlux(_fluxMag0, mag); double const fluxErr = convertToFluxErr(_fluxMag0Sigma/_fluxMag0, flux, magSigma); return std::make_pair(flux, fluxErr); } std::pair, ndarray::Array > Calib::getFlux( ndarray::Array const & mag, ndarray::Array const & magErr ) const { checkNegativeFlux0(_fluxMag0); if (mag.size() != magErr.size()) {
    367 12def164 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    367 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Size of mag (%d) and magErr (%d) don't match") % mag.size() % magErr.size()).str()); } ndarray::Array flux = ndarray::allocate(mag.size()); ndarray::Array fluxErr = ndarray::allocate(mag.size()); ndarray::Array::Iterator magIter = mag.begin(); ndarray::Array::Iterator magErrIter = magErr.begin(); ndarray::Array::Iterator fluxIter = flux.begin(); ndarray::Array::Iterator fluxErrIter = fluxErr.begin(); double fluxMag0InvSNR = _fluxMag0Sigma/_fluxMag0; for (; magIter != mag.end(); ++magIter, ++magErrIter, ++fluxIter, ++fluxErrIter) { *fluxIter = convertToFlux(_fluxMag0, *magIter); *fluxErrIter = convertToFluxErr(fluxMag0InvSNR, *fluxIter, *magErrIter); } return std::make_pair(flux, fluxErr); } /** * Return a magnitude given a flux */ double Calib::getMagnitude(double const flux ///< the measured flux of the object (ADUs) ) const { checkNegativeFlux0(_fluxMag0); if (isNegativeFlux(flux, Calib::getThrowOnNegativeFlux())) { return std::numeric_limits::quiet_NaN(); } return convertToMag(_fluxMag0, flux); } /** * Return a magnitude and magnitude error given a flux and flux error */ std::pair Calib::getMagnitude(double const flux, ///< the measured flux of the object (ADUs) double const fluxErr ///< the error in the measured flux (ADUs) ) const { checkNegativeFlux0(_fluxMag0); if (isNegativeFlux(flux, Calib::getThrowOnNegativeFlux())) { double const NaN = std::numeric_limits::quiet_NaN(); return std::make_pair(NaN, NaN); } double mag, magErr; convertToMagWithErr(&mag, &magErr, _fluxMag0, _fluxMag0Sigma/_fluxMag0, flux, fluxErr); return std::make_pair(mag, magErr); } ndarray::Array Calib::getMagnitude(ndarray::Array const & flux) const { checkNegativeFlux0(_fluxMag0); ndarray::Array mag = ndarray::allocate(flux.size()); ndarray::Array::Iterator fluxIter = flux.begin(); ndarray::Array::Iterator magIter = mag.begin(); int nonPositive = 0; for (; fluxIter != flux.end(); ++fluxIter, ++magIter) { if (isNegativeFlux(*fluxIter, false)) { ++nonPositive; *magIter = std::numeric_limits::quiet_NaN(); continue; } *magIter = convertToMag(_fluxMag0, *fluxIter); } if (nonPositive && Calib::getThrowOnNegativeFlux()) {
    434 12def164 - throw LSST_EXCEPT(lsst::pex::exceptions::DomainErrorException,
    ? ---------
    434 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::DomainError,
    (boost::format("Flux must be >= 0: %d non-positive seen") % nonPositive).str()); } return mag; } std::pair, ndarray::Array > Calib::getMagnitude( ndarray::Array const & flux, ndarray::Array const & fluxErr ) const { checkNegativeFlux0(_fluxMag0); if (flux.size() != fluxErr.size()) {
    446 12def164 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    446 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Size of flux (%d) and fluxErr (%d) don't match") % flux.size() % fluxErr.size()).str()); } ndarray::Array mag = ndarray::allocate(flux.size()); ndarray::Array magErr = ndarray::allocate(flux.size()); ndarray::Array::Iterator fluxIter = flux.begin(); ndarray::Array::Iterator fluxErrIter = fluxErr.begin(); ndarray::Array::Iterator magIter = mag.begin(); ndarray::Array::Iterator magErrIter = magErr.begin(); int nonPositive = 0; double fluxMag0InvSNR = _fluxMag0Sigma/_fluxMag0; for (; fluxIter != flux.end(); ++fluxIter, ++fluxErrIter, ++magIter, ++magErrIter) { if (isNegativeFlux(*fluxIter, false)) { ++nonPositive; double const NaN = std::numeric_limits::quiet_NaN(); *magIter = NaN; *magErrIter = NaN; continue; } double f, df; convertToMagWithErr(&f, &df, _fluxMag0, fluxMag0InvSNR, *fluxIter, *fluxErrIter); *magIter = f; *magErrIter = df; } if (nonPositive && Calib::getThrowOnNegativeFlux()) {
    473 12def164 - throw LSST_EXCEPT(lsst::pex::exceptions::DomainErrorException,
    ? ---------
    473 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::DomainError,
    (boost::format("Flux must be >= 0: %d non-positive seen") % nonPositive).str()); } return std::make_pair(mag, magErr); } namespace { class CalibSchema : private boost::noncopyable { public: table::Schema schema; table::Key midTime; table::Key expTime; table::Key fluxMag0; table::Key fluxMag0Sigma; static CalibSchema const & get() { static CalibSchema instance; return instance; } private: CalibSchema() : schema(), midTime(schema.addField( "midtime", "middle of the time of the exposure relative to Unix epoch", "nanoseconds" )), expTime(schema.addField("exptime", "exposure time", "seconds")), fluxMag0(schema.addField("fluxmag0", "flux of a zero-magnitude object", "dn")), fluxMag0Sigma(schema.addField("fluxmag0.err", "1-sigma error on fluxmag0", "dn")) { schema.getCitizen().markPersistent(); } }; class CalibFactory : public table::io::PersistableFactory { public: virtual PTR(table::io::Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const { CalibSchema const & keys = CalibSchema::get(); LSST_ARCHIVE_ASSERT(catalogs.size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys.schema); table::BaseRecord const & record = catalogs.front().front(); PTR(Calib) result(new Calib()); result->setMidTime(daf::base::DateTime(static_cast(record.get(keys.midTime)))); result->setExptime(record.get(keys.expTime)); result->setFluxMag0(record.get(keys.fluxMag0), record.get(keys.fluxMag0Sigma)); return result; } explicit CalibFactory(std::string const & name) : table::io::PersistableFactory(name) {} }; std::string getCalibPersistenceName() { return "Calib"; } CalibFactory registration(getCalibPersistenceName()); } // anonymous std::string Calib::getPersistenceName() const { return getCalibPersistenceName(); } void Calib::write(OutputArchiveHandle & handle) const { CalibSchema const & keys = CalibSchema::get(); table::BaseCatalog cat = handle.makeCatalog(keys.schema); PTR(table::BaseRecord) record = cat.addNew(); record->set(keys.midTime, getMidTime().nsecs()); record->set(keys.expTime, getExptime()); std::pair fluxMag0 = getFluxMag0(); record->set(keys.fluxMag0, fluxMag0.first); record->set(keys.fluxMag0Sigma, fluxMag0.second); handle.saveCatalog(cat); }
    549 f3d3029c - void Calib::operator*=(double const scale) {
    550 f3d3029c - _fluxMag0 *= scale;
    551 f3d3029c - _fluxMag0Sigma *= scale;
    552 f3d3029c - }
    553 f3d3029c -
    }}} // lsst::afw::image

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    e1771d06

    commit e1771d06f69bb5650337e398e4dde4700f1e3d45
    Author: rhl 
    Date:   Tue Sep 20 18:16:34 2011 +0000
    
        Added ability to merge Calibs; #1326
    

    12def164

    commit 12def1643112ba594df60ff691b23efc7761d108
    Author: Paul Price 
    Date:   Fri Sep 7 16:16:40 2012 -0400
    
        Adding functionality to Calib to replace functionality lost with removal of lsst.meas.photocal.PhotometricMagnitude
    

    f3d3029c

    commit f3d3029c561b957069cbf280b62ea8e37447c068
    Author: Paul Price 
    Date:   Mon Apr 27 18:09:36 2015 -0400
    
        Calib: add operator*= for scaling zeropoint
    

    db43227e

    commit db43227e0941320ec8e9f07bc9cf59575f61a27c
    Author: Jim Bosch 
    Date:   Sun Feb 24 19:26:53 2013 +0900
    
        Handle EXPTIME keywords that are strings instead of floats (as in some SDSS data found in afwdata).
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/ticket2162.py

    Diff:

    1 f1301348 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import unittest
    27 f1301348 - import eups
    import lsst.daf.base as dafBase import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom
    31 f1301348 - import lsst.afw.coord as afwCoord
    import lsst.utils.tests as utilsTests def headerToPropertyList(header): pl = dafBase.PropertyList() for key, value in header.items(): pl.add(key, value) return pl class WcsTestCase(unittest.TestCase): def setUp(self): # Actual WCS from processing Suprime-Cam self.width = 2048 self.height = 4177 self.header = {'NAXIS': 2, 'EQUINOX': 2000.0000000000, 'RADESYS': "FK5", 'CRPIX1': -3232.7544925483, 'CRPIX2': 4184.4881091129, 'CD1_1': -5.6123808607273e-05, 'CD1_2': 2.8951544956703e-07, 'CD2_1': 2.7343044348306e-07, 'CD2_2': 5.6100888336445e-05, 'CRVAL1': 5.6066137655191, 'CRVAL2': -0.60804032498548, 'CUNIT1': "deg", 'CUNIT2': "deg", 'A_ORDER': 5, 'A_0_2': 1.9749832126246e-08, 'A_0_3': 9.3734869173527e-12, 'A_0_4': 1.8812994578840e-17, 'A_0_5': -2.3524013652433e-19, 'A_1_1': -9.8443908806559e-10, 'A_1_2': -4.9278297504858e-10, 'A_1_3': -2.8491604610001e-16, 'A_1_4': 2.3185723720750e-18, 'A_2_0': 4.9546089730708e-08, 'A_2_1': -8.8592221672777e-12, 'A_2_2': 3.3560100338765e-16, 'A_2_3': 3.0469486185035e-21, 'A_3_0': -4.9332471706700e-10, 'A_3_1': -5.3126029725748e-16, 'A_3_2': 4.7795824885726e-18, 'A_4_0': 1.3128844828963e-16, 'A_4_1': 4.4014452170715e-19, 'A_5_0': 2.1781986904162e-18, 'B_ORDER': 5, 'B_0_2': -1.0607653075899e-08, 'B_0_3': -4.8693887937365e-10, 'B_0_4': -1.0363305097301e-15, 'B_0_5': 1.9621640066919e-18, 'B_1_1': 3.0340657679481e-08, 'B_1_2': -5.0763819284853e-12, 'B_1_3': 2.8987281654754e-16, 'B_1_4': 1.8253389678593e-19, 'B_2_0': -2.4772849184248e-08, 'B_2_1': -4.9775588352207e-10, 'B_2_2': -3.6806326254887e-16, 'B_2_3': 4.4136985315418e-18, 'B_3_0': -1.7807191001742e-11, 'B_3_1': -2.4136396882531e-16, 'B_3_2': 2.9165413645768e-19, 'B_4_0': 4.1029951148438e-16, 'B_4_1': 2.3711874424169e-18, 'B_5_0': 4.9333635889310e-19, 'AP_ORDER': 5, 'AP_0_1': -5.9740855298291e-06, 'AP_0_2': -2.0433429597268e-08, 'AP_0_3': -8.6810071023434e-12, 'AP_0_4': -2.4974690826778e-17, 'AP_0_5': 1.9819631102516e-19, 'AP_1_0': -4.5896648256716e-05, 'AP_1_1': -1.5248993348644e-09, 'AP_1_2': 5.0283116166943e-10, 'AP_1_3': 4.3796281513144e-16, 'AP_1_4': -2.1447889127908e-18, 'AP_2_0': -4.7550300344365e-08, 'AP_2_1': 1.0924172283232e-11, 'AP_2_2': -4.9862026098260e-16, 'AP_2_3': -5.4470851768869e-20, 'AP_3_0': 5.0130654116966e-10, 'AP_3_1': 6.8649554020012e-16, 'AP_3_2': -4.2759588436342e-18, 'AP_4_0': -3.6306802581471e-16, 'AP_4_1': -5.3885285875084e-19, 'AP_5_0': -1.8802693525108e-18, 'BP_ORDER': 5, 'BP_0_1': -2.6627855995942e-05, 'BP_0_2': 1.1143451873584e-08, 'BP_0_3': 4.9323396530135e-10, 'BP_0_4': 1.1785185735421e-15, 'BP_0_5': -1.6169957016415e-18, 'BP_1_0': -5.7914490267576e-06, 'BP_1_1': -3.0565765766244e-08, 'BP_1_2': 5.7727475030971e-12, 'BP_1_3': -4.0586821113726e-16, 'BP_1_4': -2.0662723654322e-19, 'BP_2_0': 2.3705520015164e-08, 'BP_2_1': 5.0530823594352e-10, 'BP_2_2': 3.8904979943489e-16, 'BP_2_3': -3.8346209540986e-18, 'BP_3_0': 1.9505421473262e-11, 'BP_3_1': 1.7583146713289e-16, 'BP_3_2': -3.4876779564534e-19, 'BP_4_0': -3.3690937119054e-16, 'BP_4_1': -2.0853007589561e-18, 'BP_5_0': -5.5344298912288e-19, 'CTYPE1': "RA---TAN-SIP", 'CTYPE2': "DEC--TAN-SIP", } def testInputInvariance(self): pl = headerToPropertyList(self.header) wcs = afwImage.makeWcs(pl) for key, value in self.header.items(): self.assertEqual(value, pl.get(key), "%s not invariant: %s vs %s" % (key, value, pl.get(key))) def testRepeat(self): pl = headerToPropertyList(self.header) wcs1 = afwImage.makeWcs(pl) wcs2 = afwImage.makeWcs(pl) for x, y in ((0, 0), (0, self.height), (self.width, 0), (self.width, self.height)): point = afwGeom.Point2D(x, y) self.assertEqual(wcs1.pixelToSky(point), wcs2.pixelToSky(point)) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(WcsTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f1301348

    commit f1301348ed7ce9bc72f9550f0858e52363469f33
    Author: Paul Price 
    Date:   Tue Jun 12 11:54:35 2012 -0400
    
        Squashed merge of tickets/2162: input header was being hacked (remove SIP) so wcslib could parse it, but this was user-visible.  Updated many APIs used by WCS code (and in related files) to take CONST_PTR instead of ::Ptr, as being more rigorous with const would have revealed this problem.  Added a test demonstrating the bug, which now passes.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    tests/coordinates.py

    Diff:

    1 755df097 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for geom.Point, geom.Extent, geom.CoordinateExpr Run with: ./Coordinates.py or python >>> import coordinates; coordinates.run() """ import unittest import numpy import math
    39 4567a4cd + import operator
    import lsst.utils.tests as utilsTests
    40 755df097 - import lsst.pex.exceptions
    import lsst.afw.geom as geom
    44 4bae7ca1 + numpy.random.seed(1)
    45 4bae7ca1 +
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class CoordinateTestCase(unittest.TestCase):
    46 755df097 -
    49 4567a4cd +
    47 a7aa0c91 - def assertClose(self, a, b):
    50 4567a4cd + def assertClose(self, a, b, msg=None):
    ? ++++++++++ if not numpy.allclose(a, b):
    49 a7aa0c91 - return self.assertEqual(a, b)
    52 4567a4cd + return self.assertEqual(a, b, msg=msg)
    ? +++++++++ else:
    51 755df097 - return self.assert_(True)
    54 4567a4cd + return self.assert_(True, msg=msg)
    ? +++++++++ def testAccessors(self): for dtype, cls, rnd in self.classes: vector1 = rnd() p = cls(*vector1) self.assertEqual(p.__class__, cls) self.assertEqual(tuple(p), tuple(vector1)) self.assertEqual(tuple(p.clone()), tuple(p)) self.assert_(p.clone() is not p) vector2 = rnd() for n in range(cls.dimensions): p[n] = vector2[n] self.assertEqual(tuple(p), tuple(vector2)) def testComparison(self): for dtype, cls, rnd in self.classes: CoordinateExpr = geom.CoordinateExpr[cls.dimensions] vector1 = rnd() vector2 = rnd() p1 = cls(*vector1) p2 = cls(*vector2) self.assertEqual(p1 == p2, all(p1.eq(p2))) self.assertEqual(p1 != p2, any(p1.ne(p2))) self.assertNotEqual(p1, None) # should not throw self.assertNotEqual(p1, tuple(p1)) # should not throw self.assertEqual(tuple(p1.eq(p2)), tuple([v1 == v2 for v1, v2 in zip(vector1, vector2)])) self.assertEqual(tuple(p1.ne(p2)), tuple([v1 != v2 for v1, v2 in zip(vector1, vector2)])) self.assertEqual(tuple(p1.lt(p2)), tuple([v1 < v2 for v1, v2 in zip(vector1, vector2)])) self.assertEqual(tuple(p1.le(p2)), tuple([v1 <= v2 for v1, v2 in zip(vector1, vector2)])) self.assertEqual(tuple(p1.gt(p2)), tuple([v1 > v2 for v1, v2 in zip(vector1, vector2)])) self.assertEqual(tuple(p1.ge(p2)), tuple([v1 >= v2 for v1, v2 in zip(vector1, vector2)])) self.assertEqual(type(p1.eq(p2)), CoordinateExpr) self.assertEqual(type(p1.ne(p2)), CoordinateExpr) self.assertEqual(type(p1.lt(p2)), CoordinateExpr) self.assertEqual(type(p1.le(p2)), CoordinateExpr) self.assertEqual(type(p1.gt(p2)), CoordinateExpr) self.assertEqual(type(p1.ge(p2)), CoordinateExpr) scalar = dtype(rnd()[0]) self.assertEqual(tuple(p1.eq(scalar)), tuple([v1 == scalar for v1 in vector1])) self.assertEqual(tuple(p1.ne(scalar)), tuple([v1 != scalar for v1 in vector1])) self.assertEqual(tuple(p1.lt(scalar)), tuple([v1 < scalar for v1 in vector1])) self.assertEqual(tuple(p1.le(scalar)), tuple([v1 <= scalar for v1 in vector1])) self.assertEqual(tuple(p1.gt(scalar)), tuple([v1 > scalar for v1 in vector1])) self.assertEqual(tuple(p1.ge(scalar)), tuple([v1 >= scalar for v1 in vector1])) self.assertEqual(type(p1.eq(scalar)), CoordinateExpr) self.assertEqual(type(p1.ne(scalar)), CoordinateExpr) self.assertEqual(type(p1.lt(scalar)), CoordinateExpr) self.assertEqual(type(p1.le(scalar)), CoordinateExpr) self.assertEqual(type(p1.gt(scalar)), CoordinateExpr) self.assertEqual(type(p1.ge(scalar)), CoordinateExpr)
    108 4567a4cd +
    class PointTestCase(CoordinateTestCase): """A test case for Point""" def setUp(self): self.classes = [ (float, geom.Point2D, lambda: [float(x) for x in numpy.random.randn(2)]), (int, geom.Point2I, lambda: [int(x) for x in numpy.random.randint(-5, 5, 2)]), (float, geom.Point3D, lambda: [float(x) for x in numpy.random.randn(3)]), (int, geom.Point3I, lambda: [int(x) for x in numpy.random.randint(-5, 5, 3)]), ]
    116 755df097 - def testArithmetic(self):
    117 25e61ab4 - for dtype, cls, rnd in self.classes:
    118 a7aa0c91 - Extent = geom.Extent[dtype, cls.dimensions]
    119 755df097 - vector1 = rnd()
    120 755df097 - vector2 = rnd()
    121 25e61ab4 - p1 = cls(*vector1)
    122 25e61ab4 - p2 = cls(*vector2)
    123 a36b3236 - self.assertClose(tuple(p1-p2), tuple([v1 - v2 for v1, v2 in zip(vector1, vector2)]))
    124 755df097 - self.assertEqual(type(p1-p2), Extent)
    125 a36b3236 - self.assertClose(tuple(p1+Extent(p2)), tuple([v1 + v2 for v1, v2 in zip(vector1, vector2)]))
    126 755df097 - self.assertEqual(type(p1+Extent(p2)), cls)
    127 a36b3236 - self.assertClose(tuple(p1-Extent(p2)), tuple([v1 - v2 for v1, v2 in zip(vector1, vector2)]))
    128 755df097 - self.assertEqual(type(p1-Extent(p2)), cls)
    129 755df097 - p1 += Extent(p2)
    130 a36b3236 - vector1 = [v1 + v2 for v1, v2 in zip(vector1, vector2)]
    131 755df097 - self.assertEqual(tuple(p1), tuple(vector1))
    132 755df097 - p1 -= Extent(p2)
    133 a36b3236 - vector1 = [v1 - v2 for v1, v2 in zip(vector1, vector2)]
    134 755df097 - self.assertClose(tuple(p1), tuple(vector1))
    135 755df097 - p1.shift(Extent(p2))
    136 a36b3236 - vector1 = [v1 + v2 for v1, v2 in zip(vector1, vector2)]
    137 755df097 - self.assertClose(tuple(p1), tuple(vector1))
    138 755df097 -
    def testSpanIteration(self): span = geom.Span(4, 3, 8) points = list(span) self.assertEqual(len(span), len(points)) self.assertEqual(points, [geom.Point2I(x, 4) for x in xrange(3, 9)]) def testConstructors(self): #test 2-d e1 = geom.Point2I(1, 2) e2 = geom.Point2I(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Point2D(1.2, 3.4) e2 = geom.Point2D(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Point2I(1, 3) e2 = geom.Point2D(e1) self.assertClose(tuple(e1), tuple(e2)) #test 3-d e1 = geom.Point3I(1, 2, 3) e2 = geom.Point3I(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Point3D(1.2, 3.4, 5.6) e2 = geom.Point3D(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Point3I(1, 2, 3) e2 = geom.Point3D(e1) self.assertClose(tuple(e1), tuple(e2)) #test rounding to integral coordinates e1 = geom.Point2D(1.2, 3.4) e2 = geom.Point2I(e1) self.assertClose(tuple([math.floor(v + 0.5) for v in e1]), tuple(e2)) e1 = geom.Point3D(1.2, 3.4, 5.6) e2 = geom.Point3I(e1) self.assertClose(tuple([math.floor(v + 0.5) for v in e1]), tuple(e2)) class ExtentTestCase(CoordinateTestCase): """A test case for Extent""" def setUp(self): self.classes = [ (float, geom.Extent2D, lambda: [float(x) for x in numpy.random.randn(2)]), (int, geom.Extent2I, lambda: [int(x) for x in numpy.random.randint(-5, 5, 2)]), (float, geom.Extent3D, lambda: [float(x) for x in numpy.random.randn(3)]), (int, geom.Extent3I, lambda: [int(x) for x in numpy.random.randint(-5, 5, 3)]), ]
    176 4567a4cd + def testRounding(self):
    177 4567a4cd + e1 = geom.Extent2D(1.2, -3.4)
    178 4567a4cd + self.assertEqual(e1.floor(), geom.Extent2I(1, -4))
    179 4567a4cd + self.assertEqual(e1.ceil(), geom.Extent2I(2, -3))
    180 4567a4cd + self.assertEqual(e1.truncate(), geom.Extent2I(1, -3))
    195 755df097 - def testArithmetic(self):
    196 25e61ab4 - for dtype, cls, rnd in self.classes:
    197 a7aa0c91 - Point = geom.Point[dtype, cls.dimensions]
    198 755df097 - vector1 = rnd()
    199 755df097 - vector2 = rnd()
    200 25e61ab4 - p1 = cls(*vector1)
    201 25e61ab4 - p2 = cls(*vector2)
    202 a36b3236 - self.assertClose(tuple(p1+Point(p2)), tuple([v1 + v2 for v1, v2 in zip(vector1, vector2)]))
    203 755df097 - self.assertEqual(type(p1+Point(p2)), Point)
    204 a36b3236 - self.assertClose(tuple(p1+p2), tuple([v1 + v2 for v1, v2 in zip(vector1, vector2)]))
    205 755df097 - self.assertEqual(type(p1+p2), cls)
    206 a36b3236 - self.assertClose(tuple(p1-p2), tuple([v1 - v2 for v1, v2 in zip(vector1, vector2)]))
    207 755df097 - self.assertEqual(type(p1-p2), cls)
    208 a36b3236 - self.assertClose(tuple(+p1), tuple(vector1))
    209 755df097 - self.assertEqual(type(+p1), cls)
    210 a36b3236 - self.assertClose(tuple(-p1), tuple([-v1 for v1 in vector1]))
    211 755df097 - self.assertEqual(type(-p1), cls)
    212 755df097 - p1 += p2
    213 a36b3236 - vector1 = [v1 + v2 for v1, v2 in zip(vector1, vector2)]
    214 755df097 - self.assertClose(tuple(p1), tuple(vector1))
    215 755df097 - p1 -= p2
    216 a36b3236 - vector1 = [v1 - v2 for v1, v2 in zip(vector1, vector2)]
    217 755df097 - self.assertClose(tuple(p1), tuple(vector1))
    218 755df097 - scalar = 2
    219 755df097 - # Python handles integer division differently from C++ for negative numbers
    220 a36b3236 - vector1 = [abs(x) for x in vector1]
    221 25e61ab4 - p1 = cls(*vector1)
    222 a36b3236 - self.assertClose(tuple(p1*scalar), tuple([v1*scalar for v1 in vector1]))
    223 755df097 - self.assertEqual(type(p1*scalar), cls)
    224 a36b3236 - self.assertClose(tuple(p1/scalar), tuple([v1/scalar for v1 in vector1]))
    225 755df097 - self.assertEqual(type(p1/scalar), cls)
    226 755df097 - p1 *= scalar
    227 a36b3236 - vector1 = [v1*scalar for v1 in vector1]
    228 755df097 - self.assertClose(tuple(p1), tuple(vector1))
    229 755df097 - p1 /= scalar
    230 a36b3236 - vector1 = [v1/scalar for v1 in vector1]
    231 755df097 - self.assertClose(tuple(p1), tuple(vector1))
    def testConstructors(self): #test extent from extent 2-d e1 = geom.Extent2I(1, 2) e2 = geom.Extent2I(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Extent2D(1.2, 3.4) e2 = geom.Extent2D(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Extent2I(1,2) e2 = geom.Extent2D(e1) self.assertClose(tuple(e1), tuple(e2)) #test extent from extent 3-d e1 = geom.Extent3I(1, 2, 3) e2 = geom.Extent3I(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Extent3D(1.2, 3.4, 5.6) e2 = geom.Extent3D(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Extent3I(1,2,3) e2 = geom.Extent3D(e1) self.assertClose(tuple(e1), tuple(e2)) #test extent from point 2-d e1 = geom.Point2I(1, 2) e2 = geom.Extent2I(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Point2D(1.2, 3.4) e2 = geom.Extent2D(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Point2I(1,2) e2 = geom.Extent2D(e1) self.assertClose(tuple(e1), tuple(e2)) #test extent from point 3-d e1 = geom.Point3I(1, 2, 3) e2 = geom.Extent3I(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Point3D(1.2, 3.4, 5.6) e2 = geom.Extent3D(e1) self.assertClose(tuple(e1), tuple(e2)) e1 = geom.Point3I(1,2,3) e2 = geom.Extent3D(e1) self.assertClose(tuple(e1), tuple(e2)) #test invalid constructors try: e1 = geom.Extent2D(1.2, 3.4) e2 = geom.Extent2I(e1) except: pass else: self.fail("Should not allow conversion Extent2D to Extent2I") try: e1 = geom.Extent3D(1.2, 3.4, 5.6) e2 = geom.Extent3I(e1) except: pass else: self.fail("Should not allow conversion Extent3D to Extent3I") try: e1 = geom.Point2D(1.2, 3.4) e2 = geom.Extent2I(e1) except: pass else: self.fail("Should not allow conversion Point2D to Extent 2I") try: e1 = geom.Point3D(1.2, 3.4, 5.6) e2 = geom.Extent3I(e1) except: pass else: self.fail("Should not allow conversion Point3D to Extent3I")
    267 4567a4cd + class OperatorTestCase(utilsTests.TestCase):
    268 4567a4cd +
    269 4567a4cd + @staticmethod
    270 4567a4cd + def makeRandom(cls):
    271 4567a4cd + """Make a random Point, Extent, int, or float of the given type."""
    272 4567a4cd + if cls is int:
    273 4567a4cd + v = 0
    274 4567a4cd + while v == 0:
    275 4567a4cd + v = int(numpy.random.randn()*10)
    276 4567a4cd + elif cls is float:
    277 4567a4cd + v = float(numpy.random.randn()*10)
    278 4567a4cd + else:
    279 4567a4cd + v = cls()
    280 4567a4cd + t = type(v[0])
    281 4567a4cd + for i in range(len(v)):
    282 4567a4cd + while v[i] == 0:
    283 4567a4cd + v[i] = t(numpy.random.randn()*10)
    284 4567a4cd + return v
    285 4567a4cd +
    286 4567a4cd + def checkOperator(self, op, lhs, rhs, expected, inPlace=False):
    287 4567a4cd + """Check that the type and result of applying operator 'op' to types 'lhs' and 'rhs'
    288 4567a4cd + yield a result of type 'expected', and that the computed value is correct. If
    289 4567a4cd + 'expected' is an Exception subclass, instead check that attempting to apply the
    290 4567a4cd + operator raises that exception.
    291 4567a4cd + """
    292 4567a4cd + v1 = self.makeRandom(lhs)
    293 4567a4cd + v2 = self.makeRandom(rhs)
    294 4567a4cd + if issubclass(expected, Exception):
    295 4567a4cd + self.assertRaises(expected, op, v1, v2)
    296 4567a4cd + else:
    297 4567a4cd + check = op(numpy.array(v1), numpy.array(v2))
    298 4567a4cd + result = op(v1, v2)
    299 4567a4cd + if type(result) != expected:
    300 4567a4cd + self.fail("%s(%s, %s): expected %s, got %s" %
    301 4567a4cd + (op.__name__, lhs.__name__, rhs.__name__,
    302 4567a4cd + expected.__name__, type(result).__name__))
    303 4567a4cd + if not numpy.allclose(result, check):
    304 4567a4cd + self.fail("%s(%s, %s): expected %s, got %s" %
    305 4567a4cd + (op.__name__, lhs.__name__, rhs.__name__, tuple(check), tuple(result)))
    306 4567a4cd + if inPlace and result is not v1:
    307 4567a4cd + self.fail("%s(%s, %s): result is not self" % (op.__name__, lhs.__name__, rhs.__name__))
    308 4567a4cd +
    309 b449d4b3 + def testPointAsExtent(self):
    310 b449d4b3 + for n in (2, 3):
    311 b449d4b3 + for t in (int, float):
    312 b449d4b3 + p = self.makeRandom(geom.Point[t, n])
    313 b449d4b3 + e = p.asExtent()
    314 b449d4b3 + self.assertEqual(type(e), geom.Extent[t, n])
    315 b449d4b3 + self.assertClose(numpy.array(p), numpy.array(e), rtol=0.0, atol=0.0)
    316 b449d4b3 +
    317 b449d4b3 + def testExtentAsPoint(self):
    318 b449d4b3 + for n in (2, 3):
    319 b449d4b3 + for t in (int, float):
    320 b449d4b3 + e = self.makeRandom(geom.Extent[t, n])
    321 b449d4b3 + p = e.asPoint()
    322 b449d4b3 + self.assertEqual(type(p), geom.Point[t, n])
    323 b449d4b3 + self.assertClose(numpy.array(p), numpy.array(e), rtol=0.0, atol=0.0)
    324 b449d4b3 +
    325 4567a4cd + def testUnaryOperators(self):
    326 4567a4cd + for n in (2, 3):
    327 4567a4cd + for t in (int, float):
    328 4567a4cd + e1 = self.makeRandom(geom.Extent[t, n])
    329 4567a4cd + e2 = +e1
    330 4567a4cd + self.assertEqual(type(e1), type(e2))
    331 4567a4cd + self.assertClose(numpy.array(e1), numpy.array(e2), rtol=0.0, atol=0.0)
    332 4567a4cd + e3 = -e1
    333 4567a4cd + self.assertEqual(type(e1), type(e3))
    334 4567a4cd + self.assertClose(numpy.array(e3), -numpy.array(e1), rtol=0.0, atol=0.0)
    335 4567a4cd +
    336 4567a4cd + def testBinaryOperators(self):
    337 4567a4cd + for n in (2, 3):
    338 4567a4cd + pD = geom.Point[float, n]
    339 4567a4cd + pI = geom.Point[int, n]
    340 4567a4cd + eD = geom.Extent[float, n]
    341 4567a4cd + eI = geom.Extent[int, n]
    342 4567a4cd + # Addition
    343 4567a4cd + self.checkOperator(operator.add, pD, pD, TypeError)
    344 4567a4cd + self.checkOperator(operator.add, pD, pI, TypeError)
    345 4567a4cd + self.checkOperator(operator.add, pD, eD, pD)
    346 4567a4cd + self.checkOperator(operator.add, pD, eI, pD)
    347 4567a4cd + self.checkOperator(operator.add, pI, pD, TypeError)
    348 4567a4cd + self.checkOperator(operator.add, pI, pI, TypeError)
    349 4567a4cd + self.checkOperator(operator.add, pI, eD, pD)
    350 4567a4cd + self.checkOperator(operator.add, pI, eI, pI)
    351 4567a4cd + self.checkOperator(operator.add, eD, pD, pD)
    352 4567a4cd + self.checkOperator(operator.add, eD, pI, pD)
    353 4567a4cd + self.checkOperator(operator.add, eD, eI, eD)
    354 4567a4cd + self.checkOperator(operator.add, eD, eD, eD)
    355 4567a4cd + self.checkOperator(operator.add, eI, pD, pD)
    356 4567a4cd + self.checkOperator(operator.add, eI, pI, pI)
    357 4567a4cd + self.checkOperator(operator.add, eI, eD, eD)
    358 4567a4cd + self.checkOperator(operator.add, eI, eI, eI)
    359 4567a4cd + # Subtraction
    360 4567a4cd + self.checkOperator(operator.sub, pD, pD, eD)
    361 4567a4cd + self.checkOperator(operator.sub, pD, pI, eD)
    362 4567a4cd + self.checkOperator(operator.sub, pD, eD, pD)
    363 4567a4cd + self.checkOperator(operator.sub, pD, eI, pD)
    364 4567a4cd + self.checkOperator(operator.sub, pI, pD, eD)
    365 4567a4cd + self.checkOperator(operator.sub, pI, pI, eI)
    366 4567a4cd + self.checkOperator(operator.sub, pI, eD, pD)
    367 4567a4cd + self.checkOperator(operator.sub, pI, eI, pI)
    368 4567a4cd + self.checkOperator(operator.sub, eD, pD, TypeError)
    369 4567a4cd + self.checkOperator(operator.sub, eD, pI, TypeError)
    370 4567a4cd + self.checkOperator(operator.sub, eD, eD, eD)
    371 4567a4cd + self.checkOperator(operator.sub, eD, eI, eD)
    372 4567a4cd + self.checkOperator(operator.sub, eI, pD, TypeError)
    373 4567a4cd + self.checkOperator(operator.sub, eI, pI, TypeError)
    374 4567a4cd + self.checkOperator(operator.sub, eI, eD, eD)
    375 4567a4cd + self.checkOperator(operator.sub, eI, eI, eI)
    376 4567a4cd + # Multiplication
    377 4567a4cd + self.checkOperator(operator.mul, eD, int, eD)
    378 4567a4cd + self.checkOperator(operator.mul, eD, float, eD)
    379 4567a4cd + self.checkOperator(operator.mul, eI, int, eI)
    380 4567a4cd + self.checkOperator(operator.mul, eI, float, eD)
    381 4567a4cd + self.checkOperator(operator.mul, int, eD, eD)
    382 4567a4cd + self.checkOperator(operator.mul, float, eD, eD)
    383 4567a4cd + self.checkOperator(operator.mul, int, eI, eI)
    384 4567a4cd + self.checkOperator(operator.mul, float, eI, eD)
    385 4567a4cd + # Old-Style Division (note that operator.div doesn't obey the future statement; it just calls
    386 4567a4cd + # __div__ directly.
    387 4567a4cd + self.checkOperator(operator.div, eD, int, eD)
    388 4567a4cd + self.checkOperator(operator.div, eD, float, eD)
    389 4567a4cd + self.checkOperator(operator.div, eI, int, eI)
    390 4567a4cd + self.checkOperator(operator.div, eI, float, eD)
    391 4567a4cd + # New-Style Division
    392 4567a4cd + self.checkOperator(operator.truediv, eD, int, eD)
    393 4567a4cd + self.checkOperator(operator.truediv, eD, float, eD)
    394 4567a4cd + self.checkOperator(operator.truediv, eI, int, eD)
    395 4567a4cd + self.checkOperator(operator.truediv, eI, float, eD)
    396 4567a4cd + # Floor Division
    397 4567a4cd + self.checkOperator(operator.floordiv, eD, int, TypeError)
    398 4567a4cd + self.checkOperator(operator.floordiv, eD, float, TypeError)
    399 4567a4cd + self.checkOperator(operator.floordiv, eI, int, eI)
    400 4567a4cd + self.checkOperator(operator.floordiv, eI, float, TypeError)
    401 4567a4cd +
    402 4567a4cd + def testInPlaceOperators(self):
    403 4567a4cd + # Note: I have no idea why Swig throws NotImplementedError sometimes for in-place operators
    404 4567a4cd + # that don't match rather than TypeError (which is what it throws for regular binary operators,
    405 4567a4cd + # and what it should be throwing consistently here, if the Python built-ins are any indication).
    406 4567a4cd + # However, I've determined that it's not worth my time to fix it, as the only approach
    407 4567a4cd + # I could think of was to use %feature("shadow"), which I tried, and Swig simply ignored it
    408 4567a4cd + # (the code I put in those blocks never appeared in the .py file).
    409 4567a4cd + for n in (2, 3):
    410 4567a4cd + pD = geom.Point[float, n]
    411 4567a4cd + pI = geom.Point[int, n]
    412 4567a4cd + eD = geom.Extent[float, n]
    413 4567a4cd + eI = geom.Extent[int, n]
    414 4567a4cd + # Addition
    415 4567a4cd + self.checkOperator(operator.iadd, pD, pD, NotImplementedError)
    416 4567a4cd + self.checkOperator(operator.iadd, pD, pI, NotImplementedError)
    417 4567a4cd + self.checkOperator(operator.iadd, pD, eD, pD, inPlace=True)
    418 4567a4cd + self.checkOperator(operator.iadd, pD, eI, pD, inPlace=True)
    419 4567a4cd + self.checkOperator(operator.iadd, pI, pD, TypeError)
    420 4567a4cd + self.checkOperator(operator.iadd, pI, pI, TypeError)
    421 4567a4cd + self.checkOperator(operator.iadd, pI, eD, TypeError)
    422 4567a4cd + self.checkOperator(operator.iadd, pI, eI, pI, inPlace=True)
    423 4567a4cd + self.checkOperator(operator.iadd, eD, pD, NotImplementedError)
    424 4567a4cd + self.checkOperator(operator.iadd, eD, pI, NotImplementedError)
    425 4567a4cd + self.checkOperator(operator.iadd, eD, eI, eD, inPlace=True)
    426 4567a4cd + self.checkOperator(operator.iadd, eD, eD, eD, inPlace=True)
    427 4567a4cd + self.checkOperator(operator.iadd, eI, pD, TypeError)
    428 4567a4cd + self.checkOperator(operator.iadd, eI, pI, TypeError)
    429 4567a4cd + self.checkOperator(operator.iadd, eI, eD, TypeError)
    430 4567a4cd + self.checkOperator(operator.iadd, eI, eI, eI, inPlace=True)
    431 4567a4cd + # Subtraction
    432 4567a4cd + self.checkOperator(operator.isub, pD, pD, NotImplementedError)
    433 4567a4cd + self.checkOperator(operator.isub, pD, pI, NotImplementedError)
    434 4567a4cd + self.checkOperator(operator.isub, pD, eD, pD, inPlace=True)
    435 4567a4cd + self.checkOperator(operator.isub, pD, eI, pD, inPlace=True)
    436 4567a4cd + self.checkOperator(operator.isub, pI, pD, TypeError)
    437 4567a4cd + self.checkOperator(operator.isub, pI, pI, TypeError)
    438 4567a4cd + self.checkOperator(operator.isub, pI, eD, TypeError)
    439 4567a4cd + self.checkOperator(operator.isub, pI, eI, pI, inPlace=True)
    440 4567a4cd + self.checkOperator(operator.isub, eD, pD, NotImplementedError)
    441 4567a4cd + self.checkOperator(operator.isub, eD, pI, NotImplementedError)
    442 4567a4cd + self.checkOperator(operator.isub, eD, eD, eD, inPlace=True)
    443 4567a4cd + self.checkOperator(operator.isub, eD, eI, eD, inPlace=True)
    444 4567a4cd + self.checkOperator(operator.isub, eI, pD, TypeError)
    445 4567a4cd + self.checkOperator(operator.isub, eI, pI, TypeError)
    446 4567a4cd + self.checkOperator(operator.isub, eI, eD, TypeError)
    447 4567a4cd + self.checkOperator(operator.isub, eI, eI, eI, inPlace=True)
    448 4567a4cd + # Multiplication
    449 4567a4cd + self.checkOperator(operator.imul, eD, int, eD, inPlace=True)
    450 4567a4cd + self.checkOperator(operator.imul, eD, float, eD, inPlace=True)
    451 4567a4cd + self.checkOperator(operator.imul, eI, int, eI, inPlace=True)
    452 4567a4cd + self.checkOperator(operator.imul, eI, float, TypeError)
    453 4567a4cd + # Old-Style Division (note that operator.div doesn't obey the future statement; it just calls
    454 4567a4cd + # __div__ directly).
    455 4567a4cd + self.checkOperator(operator.idiv, eD, int, eD, inPlace=True)
    456 4567a4cd + self.checkOperator(operator.idiv, eD, float, eD, inPlace=True)
    457 4567a4cd + self.checkOperator(operator.idiv, eI, int, eI, inPlace=True)
    458 4567a4cd + self.checkOperator(operator.idiv, eI, float, TypeError)
    459 4567a4cd + # New-Style Division
    460 4567a4cd + self.checkOperator(operator.itruediv, eD, int, eD, inPlace=True)
    461 4567a4cd + self.checkOperator(operator.itruediv, eD, float, eD, inPlace=True)
    462 4567a4cd + self.checkOperator(operator.itruediv, eI, int, TypeError)
    463 4567a4cd + self.checkOperator(operator.itruediv, eI, float, TypeError)
    464 4567a4cd + # Floor Division
    465 4567a4cd + self.checkOperator(operator.floordiv, eD, int, TypeError)
    466 4567a4cd + self.checkOperator(operator.floordiv, eD, float, TypeError)
    467 4567a4cd + self.checkOperator(operator.floordiv, eI, int, eI)
    468 4567a4cd + self.checkOperator(operator.floordiv, eI, float, TypeError)
    469 4567a4cd +
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(PointTestCase) suites += unittest.makeSuite(ExtentTestCase)
    480 4567a4cd + suites += unittest.makeSuite(OperatorTestCase)
    suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    a36b3236

    commit a36b323614a7f997c01295ec44dc9d50d3785599
    Author: rhl 
    Date:   Fri Feb 19 13:48:39 2010 +0000
    
        Fix #1178
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    755df097

    commit 755df097c5529de20757c49ebf2034b75cc42fbd
    Author: jbosch 
    Date:   Fri Dec 18 02:49:46 2009 +0000
    
        afw/#892 - updated swig wrappers for ellipses, added tests for Point, Extent, ellipses
    

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    4bae7ca1

    commit 4bae7ca131d04a3f68e47748b0423617ffd33000
    Author: Paul Price 
    Date:   Wed Aug 6 16:40:49 2014 -0400
    
        tests: seed random number generator to make tests deterministic
    

    b449d4b3

    commit b449d4b3dd5e2b050d522b7c3990f50277096ef0
    Author: Jim Bosch 
    Date:   Fri Apr 3 18:17:10 2015 -0400
    
        Add conversion between Point and Extent as methods.
        
        Methods are much less verbose than the existing conversion constructors
        in Python.
    

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    Return to list

    examples/convolveLinear.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    #include 
                    
    
    27 a9aec7fc + #include "lsst/utils/Utils.h"
    28 a9aec7fc + #include "lsst/pex/exceptions.h"
    #include "lsst/daf/base.h" #include "lsst/pex/logging/Trace.h" #include "lsst/afw/image.h" #include "lsst/afw/math.h" namespace afwImage = lsst::afw::image; namespace afwMath= lsst::afw::math;
    35 071050d4 - const std::string outFile("clOut");
    ? ^^^
    37 a9aec7fc + const std::string outImagePath("clOut.fits");
    ? ^^^^ ++++ +++++
    36 071050d4 - const std::string altOutFile("clAltOut");
    int main(int argc, char **argv) { lsst::pex::logging::Trace::setDestination(std::cout); lsst::pex::logging::Trace::setVerbosity("lsst.afw.math", 5); typedef float ImagePixel; unsigned int const KernelCols = 19; unsigned int const KernelRows = 19; double const MinSigma = 1.5; double const MaxSigma = 4.5;
    48 8c6c0d93 - std::string mimg;
    ? ^^
    49 a9aec7fc + std::string inImagePath;
    ? +++ ^ +++++ if (argc < 2) {
    50 8c6c0d93 - std::string afwdata = getenv("AFWDATA_DIR");
    51 8c6c0d93 - if (afwdata.empty()) {
    51 a9aec7fc + try {
    52 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
    53 a9aec7fc + inImagePath = dataDir + "/data/med.fits";
    54 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    52 11297beb - std::cerr << "Usage: linearConvolve fitsFile" << std::endl;
    55 a9aec7fc + std::cerr << "Usage: linearConvolve [fitsFile]" << std::endl;
    ? + +
    56 a9aec7fc + std::cerr << "fitsFile is the path to a masked image" << std::endl;
    53 8c6c0d93 - std::cerr << "fitsFile excludes the \"_img.fits\" suffix" << std::endl;
    54 8c6c0d93 - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << std::endl;
    55 8c6c0d93 - std::cerr << "Is afwdata set up?\n" << std::endl;
    ? ^ ^^^^
    57 a9aec7fc + std::cerr << "\nError: setup afwdata or specify fitsFile.\n" << std::endl;
    ? ^^^^^^^^^ ++++ +++ + +++++++ ^^^^^^ exit(EXIT_FAILURE);
    57 8c6c0d93 - } else {
    58 eae9ad17 - mimg = afwdata + "/med_MI";
    59 8c6c0d93 - std::cerr << "Using " << mimg << std::endl;
    }
    61 8c6c0d93 -
    } else {
    63 8c6c0d93 - mimg = std::string(argv[1]);
    ? ^^
    61 a9aec7fc + inImagePath = std::string(argv[1]);
    ? +++ ^ +++++ } // block in which to allocate and deallocate memory { // read in fits file
    69 8c6c0d93 - afwImage::MaskedImage mImage(mimg);
    ? ^^
    67 a9aec7fc + afwImage::MaskedImage mImage(inImagePath);
    ? +++ ^ +++++ // construct basis kernels afwMath::KernelList kernelList; for (int ii = 0; ii < 3; ++ii) { double majorSigma = (ii == 1) ? MaxSigma : MinSigma; double minorSigma = (ii == 2) ? MinSigma : MaxSigma; double angle = 0.0; afwMath::GaussianFunction2 gaussFunc(majorSigma, minorSigma, angle); PTR(afwMath::Kernel) basisKernelPtr( new afwMath::AnalyticKernel(KernelCols, KernelRows, gaussFunc) ); kernelList.push_back(basisKernelPtr); } // construct spatially varying linear combination kernel int const polyOrder = 1; afwMath::PolynomialFunction2 polyFunc(polyOrder); afwMath::LinearCombinationKernel kernel(kernelList, polyFunc); // Get copy of spatial parameters (all zeros), set and feed back to the kernel std::vector > polyParams = kernel.getSpatialParameters(); // Set spatial parameters for basis kernel 0 polyParams[0][0] = 1.0; polyParams[0][1] = -0.5 / static_cast(mImage.getWidth()); polyParams[0][2] = -0.5 / static_cast(mImage.getHeight()); // Set spatial function parameters for basis kernel 1 polyParams[1][0] = 0.0; polyParams[1][1] = 1.0 / static_cast(mImage.getWidth()); polyParams[1][2] = 0.0; // Set spatial function parameters for basis kernel 2 polyParams[2][0] = 0.0; polyParams[2][1] = 0.0; polyParams[2][2] = 1.0 / static_cast(mImage.getHeight()); // Set spatial function parameters for kernel parameter 1 kernel.setSpatialParameters(polyParams);
    105 a9aec7fc + std::cerr << "Image: " << inImagePath << std::endl;
    std::cout << "Image size: " << mImage.getWidth() << " x " << mImage.getHeight() << std::endl; std::cout << "Kernel size: " << KernelCols << " x " << KernelRows << std::endl; std::cout << "Number of basis kernels: " << kernel.getNBasisKernels() << std::endl; std::cout << "Spatial order: " << polyOrder << std::endl; // convolve afwImage::MaskedImage resMaskedImage(mImage.getDimensions()); afwMath::convolve(resMaskedImage, mImage, kernel, false); // write results
    117 071050d4 - resMaskedImage.writeFits(outFile);
    ? ^^^
    116 a9aec7fc + resMaskedImage.writeFits(outImagePath);
    ? ^^^^ ++++
    118 071050d4 - std::cout << "Wrote " << outFile << "_img.fits, etc." << std::endl;
    117 a9aec7fc + std::cout << "Saved convolved image as " << outImagePath << std::endl;
    } // Check for memory leaks if (lsst::daf::base::Citizen::census(0) != 0) { std::cerr << "Leaked memory blocks:" << std::endl; lsst::daf::base::Citizen::census(std::cerr); } }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    11297beb

    commit 11297beb3d9ed018625592fa8e8e93f596002049
    Author: rowen 
    Date:   Wed Sep 15 22:32:51 2010 +0000
    
        Fixed a bug in KernelImagesForRegion::computeNextRow
        Implemented a unit test for KernelImagesForRegion::computeNextRow
    

    071050d4

    commit 071050d4ef0b454df76b47471834bafed90cf154
    Author: rowen 
    Date:   Fri Sep 21 23:37:16 2007 +0000
    
        Added examples/convolveLinear.
        Added some parentheses to KernelFunctions.cc to clarify the code.
    

    8c6c0d93

    commit 8c6c0d93eaf03478cc6379a16055c3ae6119aa35
    Author: bick 
    Date:   Fri Jan 8 21:49:43 2010 +0000
    
        #1113 Changed examples to default to afwdata fits files with no arguments.
    

    eae9ad17

    commit eae9ad175a79abc17b9939be5beb520d5e90dc1f
    Author: rowen 
    Date:   Sat Oct 16 00:21:41 2010 +0000
    
        Merge ticket #1469: further convolution speedups
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    tests/background.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    #include 
                    
                    #define BOOST_TEST_DYN_LINK
                    #define BOOST_TEST_MODULE Background
                    
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/test/unit_test.hpp"
                    #pragma clang diagnostic pop
                    #include "boost/test/floating_point_comparison.hpp"
                    
    
    38 a9aec7fc + #include "lsst/utils/Utils.h"
    39 a9aec7fc + #include "lsst/pex/exceptions.h"
    #include "lsst/afw/image/Image.h" #include "lsst/afw/math/Interpolate.h" #include "lsst/afw/math/Background.h" using namespace std; namespace image = lsst::afw::image; namespace math = lsst::afw::math; namespace geom = lsst::afw::geom; typedef image::Image Image; typedef image::DecoratedImage DecoratedImage; BOOST_AUTO_TEST_CASE(BackgroundBasic) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ int nX = 40; int nY = 40; Image img(geom::Extent2I(nX, nY)); Image::Pixel const pixVal = 10000; img = pixVal; { int xcen = nX/2; int ycen = nY/2; math::BackgroundControl bgCtrl("AKIMA_SPLINE"); // test methods native BackgroundControl bgCtrl.setNxSample(5); bgCtrl.setNySample(5); // test methods for public stats objects in bgCtrl bgCtrl.getStatisticsControl()->setNumSigmaClip(3); bgCtrl.getStatisticsControl()->setNumIter(3); PTR(math::Background) back = math::makeBackground(img, bgCtrl); double const TESTVAL = boost::dynamic_pointer_cast(back)->getPixel(xcen, ycen); image::Image::Ptr bImage = back->getImage(); Image::Pixel const testFromImage = *(bImage->xy_at(xcen, ycen)); BOOST_CHECK_EQUAL(TESTVAL, pixVal); BOOST_CHECK_EQUAL(TESTVAL, testFromImage); } } BOOST_AUTO_TEST_CASE(BackgroundTestImages) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ { vector imgfiles; imgfiles.push_back("v1_i1_g_m400_s20_f.fits"); imgfiles.push_back("v1_i1_g_m400_s20_u16.fits"); //imgfiles.push_back("v1_i2_g_m400_s20_f.fits"); //imgfiles.push_back("v1_i2_g_m400_s20_u16.fits"); //imgfiles.push_back("v2_i1_p_m9_f.fits"); //imgfiles.push_back("v2_i1_p_m9_u16.fits"); //imgfiles.push_back("v2_i2_p_m9_f.fits"); //imgfiles.push_back("v2_i2_p_m9_u16.fits");
    95 ff0c8fc4 - string afwdata_dir = getenv("AFWDATA_DIR");
    97 a9aec7fc + std::string afwdata_dir;
    98 a9aec7fc + try {
    99 7cbb2bb9 + afwdata_dir = lsst::utils::getPackageDir("afwdata");
    100 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    101 a9aec7fc + std::cout << "Warning: test skipped because afwdata is not setup" << std::endl;
    102 a9aec7fc + return;
    103 a9aec7fc + }
    for (vector::iterator imgfile = imgfiles.begin(); imgfile != imgfiles.end(); ++imgfile) { string img_path = afwdata_dir + "/Statistics/" + *imgfile; // get the image and header DecoratedImage dimg(img_path); Image::Ptr img = dimg.getImage(); lsst::daf::base::PropertySet::Ptr fitsHdr = dimg.getMetadata(); // the FITS header // get the true values of the mean and stdev float reqMean = static_cast(fitsHdr->getAsDouble("MEANREQ")); float reqStdev = static_cast(fitsHdr->getAsDouble("SIGREQ")); int const width = img->getWidth(); int const height = img->getHeight(); // create a background control object math::BackgroundControl bctrl(math::Interpolate::AKIMA_SPLINE); bctrl.setNxSample(5); bctrl.setNySample(5); float stdevSubimg = reqStdev / sqrt(width*height/(bctrl.getNxSample()*bctrl.getNySample())); // run the background constructor and call the getPixel() and getImage() functions. PTR(math::Background) backobj = math::makeBackground(*img, bctrl); // test getPixel() float testval = boost::dynamic_pointer_cast(backobj)->getPixel(width/2, height/2); BOOST_REQUIRE( fabs(testval - reqMean) < 2.0*stdevSubimg ); // test getImage() by checking the center pixel image::Image::Ptr bimg = backobj->getImage(); float testImgval = static_cast(*(bimg->xy_at(width/2, height/2))); BOOST_REQUIRE( fabs(testImgval - reqMean) < 2.0*stdevSubimg ); } } } BOOST_AUTO_TEST_CASE(BackgroundRamp) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ { // make a ramping image (spline should be exact for linear increasing image int const nX = 512; int const nY = 512;
    144 264e671e - image::Image rampimg = image::Image(geom::Extent2I(nX, nY));
    ? ^ ^^^ ^ ^^^
    152 c9c89e06 + image::Image rampimg = image::Image(geom::Extent2I(nX, nY));
    ? ^^^^ ^ ^^^^ ^
    145 264e671e - float dzdx = 0.1;
    ? ^ ^^^
    153 2eb9dac3 + double dzdx = 0.1;
    ? ^^^^ ^
    146 264e671e - float dzdy = 0.2;
    ? ^ ^^^
    154 ff0c8fc4 + double dzdy = 0.2;
    ? ^^^^ ^
    147 264e671e - float z0 = 10000.0;
    ? ^ ^^^
    155 ff0c8fc4 + double z0 = 10000.0;
    ? ^^^^ ^ for (int i = 0; i < nX; ++i) {
    150 264e671e - float x = static_cast(i);
    ? ^ ^^^ ^ ^^^
    158 ff0c8fc4 + double x = static_cast(i);
    ? ^^^^ ^ ^^^^ ^ for ( int j = 0; j < nY; ++j) {
    152 264e671e - float y = static_cast(j);
    ? ^ ^^^ ^ ^^^
    160 ff0c8fc4 + double y = static_cast(j);
    ? ^^^^ ^ ^^^^ ^ *rampimg.xy_at(i, j) = dzdx*x + dzdy*y + z0; } } // check corner, edge, and center pixels math::BackgroundControl bctrl = math::BackgroundControl(math::Interpolate::AKIMA_SPLINE); bctrl.setNxSample(6); bctrl.setNySample(6); bctrl.getStatisticsControl()->setNumSigmaClip(20.0); //something large enough to avoid clipping entirely bctrl.getStatisticsControl()->setNumIter(1); PTR(math::BackgroundMI) backobj = boost::dynamic_pointer_cast(math::makeBackground(rampimg, bctrl)); // test the values at the corners and in the middle int ntest = 3; for (int i = 0; i < ntest; ++i) { int xpix = i*(nX - 1)/(ntest - 1); for (int j = 0; j < ntest; ++j) { int ypix = j*(nY - 1)/(ntest - 1); double testval = backobj->getPixel(xpix, ypix); double realval = *rampimg.xy_at(xpix, ypix); BOOST_CHECK_CLOSE(testval/realval, 1.0, 2.5e-5); } } } } BOOST_AUTO_TEST_CASE(BackgroundParabola) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ { // make an image which varies parabolicly (spline should be exact for 2rd order polynomial) int const nX = 512; int const nY = 512;
    187 264e671e - image::Image parabimg = image::Image(geom::Extent2I(nX, nY));
    ? ^ ^^^ ^ ^^^
    195 c9c89e06 + image::Image parabimg = image::Image(geom::Extent2I(nX, nY));
    ? ^^^^ ^ ^^^^ ^
    188 264e671e - float d2zdx2 = -1.0e-4;
    ? ^ ^^^
    196 2eb9dac3 + double d2zdx2 = -1.0e-4;
    ? ^^^^ ^
    189 264e671e - float d2zdy2 = -1.0e-4;
    ? ^ ^^^
    197 ff0c8fc4 + double d2zdy2 = -1.0e-4;
    ? ^^^^ ^
    190 264e671e - float dzdx = 0.1;
    ? ^ ^^^
    198 ff0c8fc4 + double dzdx = 0.1;
    ? ^^^^ ^
    191 264e671e - float dzdy = 0.2;
    ? ^ ^^^
    199 ff0c8fc4 + double dzdy = 0.2;
    ? ^^^^ ^
    192 264e671e - float z0 = 10000.0; // no cross-terms
    ? ^ ^^^
    200 ff0c8fc4 + double z0 = 10000.0; // no cross-terms
    ? ^^^^ ^ for ( int i = 0; i < nX; ++i ) { for ( int j = 0; j < nY; ++j ) { *parabimg.xy_at(i, j) = d2zdx2*i*i + d2zdy2*j*j + dzdx*i + dzdy*j + z0; } } // check corner, edge, and center pixels math::BackgroundControl bctrl = math::BackgroundControl(math::Interpolate::CUBIC_SPLINE); bctrl.setNxSample(24); bctrl.setNySample(24); bctrl.getStatisticsControl()->setNumSigmaClip(10.0); bctrl.getStatisticsControl()->setNumIter(1); PTR(math::BackgroundMI) backobj = boost::dynamic_pointer_cast(math::makeBackground(parabimg, bctrl)); // check the values at the corners and in the middle int const ntest = 3; for (int i = 0; i < ntest; ++i) { int xpix = i*(nX - 1)/(ntest - 1); for (int j = 0; j < ntest; ++j) { int ypix = j*(nY - 1)/(ntest - 1); double testval = backobj->getPixel(xpix, ypix); double realval = *parabimg.xy_at(xpix, ypix); //print xpix, ypix, testval, realval // quadratic terms skew the averages of the subimages and the clipped mean for // a subimage != value of center pixel. 1/20 counts on a 10000 count sky // is a fair (if arbitrary) test. BOOST_CHECK_CLOSE( testval, realval, 0.05 ); } } } }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ff0c8fc4

    commit ff0c8fc4d3fb8d3e18c90ccf5d5efac743619b4a
    Author: bick 
    Date:   Wed Jan 14 16:50:33 2009 +0000
    
        Merging ticket 395 (image statistics and background estimation) on to trunk.
    

    264e671e

    commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
    Author: Steven Bickerton 
    Date:   Fri Oct 24 14:37:15 2014 +0900
    
        Use shared_ptr.  Add test.  Disable double,int backgrounds.
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    2eb9dac3

    commit 2eb9dac33eec6f13a73c03cc2827aa9884ff06cc
    Author: rowen 
    Date:   Mon Sep 28 22:55:55 2009 +0000
    
        Removed all tabs.
    

    ff0c8fc4

    commit ff0c8fc4d3fb8d3e18c90ccf5d5efac743619b4a
    Author: bick 
    Date:   Wed Jan 14 16:50:33 2009 +0000
    
        Merging ticket 395 (image statistics and background estimation) on to trunk.
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    tests/imageIo2.py

    Diff:

    1 01e7e5f9 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . #
    25 01e7e5f9 - import os
    26 01e7e5f9 -
    import unittest import lsst.utils.tests as utilsTests import lsst.afw.image as afwImage
    30 01e7e5f9 - import lsst.daf.base as dafBase
    31 01e7e5f9 - import lsst.daf.persistence as dafPers
    32 01e7e5f9 - import eups
    class ImageIoTestCase(unittest.TestCase): """A test case for Image Persistence""" def checkImages(self, image, original): # Check that two images are identical self.assertEqual(image.getHeight(), original.getHeight()) self.assertEqual(image.getWidth(), original.getWidth()) self.assertEqual(image.getY0(), original.getY0()) self.assertEqual(image.getX0(), original.getX0()) for x in xrange(0, original.getWidth()): for y in xrange(0, image.getHeight()): self.assertEqual(image.get(x, y), original.get(x, y)) def setUp(self): # Create the additionalData PropertySet self.cols = 4 self.rows = 4 def testIo(self): for Image in (afwImage.ImageU, afwImage.ImageL, afwImage.ImageI, afwImage.ImageF, afwImage.ImageD, ): image = Image(self.cols, self.rows) for x in xrange(0, self.cols): for y in xrange(0, self.rows): image.set(x, y, x + y)
    64 f684092f - with utilsTests.temporaryFile("imageIo2.fits") as filename:
    60 c605dfcd + with utilsTests.getTempFilePath("_%s.fits" % (Image.__name__,)) as filename:
    image.writeFits(filename) readImage = Image(filename) self.checkImages(readImage, image) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ImageIoTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    01e7e5f9

    commit 01e7e5f99d72e0307bcee83980c8747508afc177
    Author: price 
    Date:   Tue Nov 15 00:41:28 2011 +0000
    
        Add test for read/write images as FITS.
    

    f684092f

    commit f684092f0654521012789e18e3c192aabe428def
    Author: Robert Lupton the Good 
    Date:   Thu Nov 17 20:36:35 2011 -0500
    
        Remove temporary file (imageIo2.fits) after use
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    Return to list

    src/math/FixedKernel.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include 
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/KernelPersistenceHelper.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwMath = lsst::afw::math;
                    namespace afwImage = lsst::afw::image;
                    
                    afwMath::FixedKernel::FixedKernel()
                    :
                        Kernel(),
                        _image(),
                        _sum(0) {
                    }
                    
                    afwMath::FixedKernel::FixedKernel(
                        afwImage::Image const &image
                    ) :
                        Kernel(image.getWidth(), image.getHeight(), 0),
                        _image(image, true),
                        _sum(0) {
                    
                        typedef afwImage::Image::x_iterator XIter;
                        double imSum = 0.0;
                        for (int y = 0; y != image.getHeight(); ++y) {
                            for (XIter imPtr = image.row_begin(y), imEnd = image.row_end(y); imPtr != imEnd; ++imPtr) {
                                imSum += *imPtr;
                            }
                        }
                        this->_sum = imSum;
                    }
                    
                    afwMath::FixedKernel::FixedKernel(
                        afwMath::Kernel const& kernel,
                        afwGeom::Point2D const& pos
                    ) :
                        Kernel(kernel.getWidth(), kernel.getHeight(), 0),
                        _image(kernel.getDimensions()),
                        _sum(0) {
                        _sum = kernel.computeImage(_image, false, pos[0], pos[1]);
                    }
                    
                    PTR(afwMath::Kernel) afwMath::FixedKernel::clone() const {
                        PTR(afwMath::Kernel) retPtr(new afwMath::FixedKernel(_image));
                        retPtr->setCtr(this->getCtr());
                        return retPtr;
                    }
                    
                    double afwMath::FixedKernel::doComputeImage(
                        afwImage::Image &image,
                        bool doNormalize
                    ) const {
                        double multFactor = 1.0;
                        double imSum = this->_sum;
                        if (doNormalize) {
                            if (imSum == 0) {
    
    84 b79a02a2 - throw LSST_EXCEPT(pexExcept::OverflowErrorException, "Cannot normalize; kernel sum is 0");
    ? ---------
    84 21597d88 + throw LSST_EXCEPT(pexExcept::OverflowError, "Cannot normalize; kernel sum is 0");
    } multFactor = 1.0/static_cast(this->_sum); imSum = 1.0; } typedef afwImage::Image::x_iterator XIter; for (int y = 0; y != this->getHeight(); ++y) { for (XIter imPtr = image.row_begin(y), imEnd = image.row_end(y), kPtr = this->_image.row_begin(y); imPtr != imEnd; ++imPtr, ++kPtr) { imPtr[0] = multFactor*kPtr[0]; } } return imSum; } std::string afwMath::FixedKernel::toString(std::string const& prefix) const { std::ostringstream os; os << prefix << "FixedKernel:" << std::endl; os << prefix << "..sum: " << _sum << std::endl; os << Kernel::toString(prefix + "\t"); return os.str(); } // ------ Persistence --------------------------------------------------------------------------------------- namespace lsst { namespace afw { namespace math { namespace { struct FixedKernelPersistenceHelper : public Kernel::PersistenceHelper { table::Key< table::Array > image; explicit FixedKernelPersistenceHelper(geom::Extent2I const & dimensions) : Kernel::PersistenceHelper(0), image( schema.addField< table::Array >( "image", "pixel values (row-major)", dimensions.getX() * dimensions.getY() ) ) {} explicit FixedKernelPersistenceHelper(table::Schema const & schema_) : Kernel::PersistenceHelper(schema_), image(schema["image"]) {} }; } // anonymous class FixedKernel::Factory : public afw::table::io::PersistableFactory { public: virtual PTR(afw::table::io::Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const { LSST_ARCHIVE_ASSERT(catalogs.size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); FixedKernelPersistenceHelper const keys(catalogs.front().getSchema()); afw::table::BaseRecord const & record = catalogs.front().front(); image::Image image(geom::Extent2I(record.get(keys.dimensions))); ndarray::flatten<1>( ndarray::static_dimension_cast<2>(image.getArray()) ) = record[keys.image]; PTR(FixedKernel) result = boost::make_shared(image); result->setCtr(record.get(keys.center)); return result; } explicit Factory(std::string const & name) : afw::table::io::PersistableFactory(name) {} }; namespace { std::string getFixedKernelPersistenceName() { return "FixedKernel"; } FixedKernel::Factory registration(getFixedKernelPersistenceName()); } // anonymous std::string FixedKernel::getPersistenceName() const { return getFixedKernelPersistenceName(); } void FixedKernel::write(OutputArchiveHandle & handle) const { FixedKernelPersistenceHelper const keys(getDimensions()); PTR(afw::table::BaseRecord) record = keys.write(handle, *this); (*record)[keys.image] = ndarray::flatten<1>(ndarray::copy(_image.getArray())); } }}} // namespace lsst::afw::math

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b79a02a2

    commit b79a02a2c6c1b70fadfb74623e481172a3376579
    Author: rowen 
    Date:   Mon Nov 23 21:16:07 2009 +0000
    
        Implemented ticket #992:
        - Kernel.computeImage now raises lsst::pex::except::InvalidParameterException
          if doNormalize true and kernel sum 0.
        - SeparableKernel.computeVectors and basicComputeVectors do the same.
        - Added unit tests for the above.
        - Fixed typos in tests/Statistics.py so all tests pass again.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    examples/estimateBackground.py

    Diff:

                    #!/usr/bin/env python
                    
                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    
                    import os
    
    26 6d3610ca - import eups
    26 7cbb2bb9 + import lsst.utils
    import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.display.ds9 as ds9 try: display except NameError: display = not False ################################################ def getImage():
    39 6d3610ca - imagePath = os.path.join(eups.productDir("afwdata"),
    ? ^ ^ ^^^^^ ^
    39 7cbb2bb9 + imagePath = os.path.join(lsst.utils.getPackageDir("afwdata"),
    ? ^^^^^ ^^^ ^^^^^ ^^^^ "DC3a-Sim", "sci", "v5-e0", "v5-e0-c011-a00.sci_img.fits") return afwImage.MaskedImageF(imagePath) def simpleBackground(image): binsize = 128 nx = int(image.getWidth()/binsize) + 1 ny = int(image.getHeight()/binsize) + 1 bctrl = afwMath.BackgroundControl(nx, ny) bkgd = afwMath.makeBackground(image, bctrl) statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage() image -= bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE) return bkgd def complexBackground(image): binsize = 128 nx = int(image.getWidth()/binsize) + 1 ny = int(image.getHeight()/binsize) + 1 sctrl = afwMath.StatisticsControl() sctrl.setNumSigmaClip(3) sctrl.setNumIter(4) sctrl.setAndMask(afwImage.MaskU.getPlaneBitMask(["INTRP", "EDGE"])) sctrl.setNoGoodPixelsMask(afwImage.MaskU.getPlaneBitMask("BAD")) sctrl.setNanSafe(True) if False: sctrl.setWeighted(True) sctrl.setCalcErrorFromInputVariance(True) bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP) bkgd = afwMath.makeBackground(image, bctrl) statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage() ds9.mtv(statsImage.getVariance()) bkdgImages = dict(SPLINE = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE), LINEAR = bkgd.getImageF(afwMath.Interpolate.LINEAR)) return bkgd def main(): image = getImage() if display: ds9.mtv(image, frame=0) bkgd = simpleBackground(image) image = getImage() bkgd = complexBackground(image) if display: ds9.mtv(image, frame=1) ds9.mtv(afwMath.cast_BackgroundMI(bkgd).getStatsImage(), frame=2) order = 2 actrl = afwMath.ApproximateControl(afwMath.ApproximateControl.CHEBYSHEV, order, order) approx = bkgd.getApproximate(actrl) approx.getImage() approx.getMaskedImage() approx.getImage(order - 1) ################################################# if __name__ == '__main__': main()

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6d3610ca

    commit 6d3610cad0c01366fd4ff4b9df9c5cc84278a158
    Author: Robert Lupton the Good 
    Date:   Fri Oct 12 18:15:47 2012 -0400
    
        Add documentation for Background
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/math/Random.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    /**
                     * @file
                     * @brief Random number generator implementaion.
                     * @ingroup afw
                     */
                    
                    #include 
                    
                    #include "boost/format.hpp"
                    #include "boost/lexical_cast.hpp"
                    
                    #include "gsl/gsl_errno.h"
                    #include "gsl/gsl_randist.h"
                    
                    #include "lsst/pex/exceptions.h"
                    
                    #include "lsst/afw/math/Random.h"
                    
                    using lsst::pex::policy::Policy;
                    
                    namespace ex = lsst::pex::exceptions;
                    namespace math = lsst::afw::math;
                    
                    
                    // -- Static data --------
                    
                    ::gsl_rng_type const * const math::Random::_gslRngTypes[math::Random::NUM_ALGORITHMS] = {
                        ::gsl_rng_mt19937,
                        ::gsl_rng_ranlxs0,
                        ::gsl_rng_ranlxs1,
                        ::gsl_rng_ranlxs2,
                        ::gsl_rng_ranlxd1,
                        ::gsl_rng_ranlxd2,
                        ::gsl_rng_ranlux,
                        ::gsl_rng_ranlux389,
                        ::gsl_rng_cmrg,
                        ::gsl_rng_mrg,
                        ::gsl_rng_taus,
                        ::gsl_rng_taus2,
                        ::gsl_rng_gfsr4
                    };
                    
                    char const * const math::Random::_algorithmNames[math::Random::NUM_ALGORITHMS] = {
                        "MT19937",
                        "RANLXS0",
                        "RANLXS1",
                        "RANLXS2",
                        "RANLXD1",
                        "RANLXD2",
                        "RANLUX",
                        "RANLUX389",
                        "CMRG",
                        "MRG",
                        "TAUS",
                        "TAUS2",
                        "GFSR4"
                    };
                    
                    char const * const math::Random::_algorithmEnvVarName = "LSST_RNG_ALGORITHM";
                    char const * const math::Random::_seedEnvVarName = "LSST_RNG_SEED";
                    
                    
                    // -- Private helper functions --------
                    
                    /**
                     * @internal
                     * @brief   Initializes the underlying GSL random number generator.
    
    93 e2fd0793 - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    93 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * Thrown if a seed value of zero (corresponding to an algorithm specific seed) is chosen. */ void math::Random::initialize() { if (_seed == 0) {
    98 7a6ea5ce - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    98 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ (boost::format("Invalid RNG seed: %lu") % _seed).str()); } ::gsl_rng * rng = ::gsl_rng_alloc(_gslRngTypes[_algorithm]); if (rng == 0) {
    103 72a4ce55 - throw LSST_EXCEPT(ex::MemoryException, "gsl_rng_alloc() failed");
    ? ^^^^^^ ^
    103 21597d88 + throw LSST_EXCEPT(ex::MemoryError, "gsl_rng_alloc() failed");
    ? ^^ ^ } ::gsl_rng_set(rng, _seed); _rng.reset(rng, ::gsl_rng_free); } /** * @internal * @brief Initializes the underlying GSL random number generator. * * @param[in] algorithm the algorithm to use for random number generation *
    115 e2fd0793 - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    115 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * Thrown if the requested algorithm is not supported or a seed value of zero * (corresponding to an algorithm specific seed) is chosen. */ void math::Random::initialize(std::string const & algorithm) { // linear search (the number of algorithms is small) for (int i = 0; i < NUM_ALGORITHMS; ++i) { if (_algorithmNames[i] == algorithm) { _algorithm = static_cast(i); initialize(); return; } }
    128 e2fd0793 - throw LSST_EXCEPT(ex::InvalidParameterException, "RNG algorithm " +
    ? ^^^^^^ ^
    128 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError, "RNG algorithm " +
    ? ^^ ^ algorithm + " is not supported"); } // -- Constructor -------- /** * Creates a random number generator that uses the given algorithm to produce random numbers, * and seeds it with the specified value. Passing a seed-value of zero will cause the * generator to be seeded with an algorithm specific default value. The default value for * @a algorithm is MT19937, corresponding to the "Mersenne Twister" algorithm by * Makoto Matsumoto and Takuji Nishimura. * * @param[in] algorithm the algorithm to use for random number generation * @param[in] seed the seed value to initialize the generator with *
    145 72a4ce55 - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    145 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * Thrown if the requested algorithm is not supported or a seed value of zero * (corresponding to an algorithm specific seed) is chosen.
    148 72a4ce55 - * @throw lsst::pex::exceptions::MemoryException
    ? ^^^^^^ ^
    148 21597d88 + * @throw lsst::pex::exceptions::MemoryError
    ? ^^ ^ * Thrown if memory allocation for internal generator state fails. */ math::Random::Random(Algorithm const algorithm, unsigned long seed) : _rng(), _seed(seed), _algorithm(algorithm) { if (_algorithm < 0 || _algorithm >= NUM_ALGORITHMS) {
    155 282b39c2 - throw LSST_EXCEPT(ex::InvalidParameterException, "Invalid RNG algorithm");
    ? ^^^^^^ ^
    155 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError, "Invalid RNG algorithm");
    ? ^^ ^ } initialize(); } /** * Creates a random number generator that uses the algorithm with the given name to produce * random numbers, and seeds it with the specified value. Passing a seed-value of zero will * cause the generator to be seeded with an algorithm specific default value. * * @param[in] algorithm the name of the algorithm to use for random number generation * @param[in] seed the seed value to initialize the generator with *
    169 282b39c2 - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    169 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * Thrown if the requested algorithm is not supported or a seed value of zero * (corresponding to an algorithm specific seed) is chosen.
    172 282b39c2 - * @throw lsst::pex::exceptions::MemoryException
    ? ^^^^^^ ^
    172 21597d88 + * @throw lsst::pex::exceptions::MemoryError
    ? ^^ ^ * Thrown if memory allocation for internal generator state fails. */ math::Random::Random(std::string const & algorithm, unsigned long seed) : _rng(), _seed(seed) { initialize(algorithm); } /** * Creates a random number generator using the algorithm and seed specified * in the given policy. The algorithm name and seed are expected to be specified * in string-valued keys named "rngAlgorithm" and "rngSeed" respectively. The * "rngSeed" value is expected to be convertible to an unsigned long integer * and must not be positive. * * @param[in] policy policy which contains the algorithm and seed to * to use for random number generation * @return a newly created random number generator *
    193 e2fd0793 - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    193 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * Thrown if the requested algorithm is not supported.
    195 e2fd0793 - * @throw lsst::pex::exceptions::MemoryException
    ? ^^^^^^ ^
    195 21597d88 + * @throw lsst::pex::exceptions::MemoryError
    ? ^^ ^ * Thrown if memory allocation for internal generator state fails.
    197 e2fd0793 - * @throw lsst::pex::exceptions::RuntimeErrorException
    ? ---------
    197 21597d88 + * @throw lsst::pex::exceptions::RuntimeError
    * Thrown if the "rngSeed" policy value cannot be converted to an unsigned long int. */ math::Random::Random(lsst::pex::policy::Policy::Ptr const policy) : _rng(), _seed() { std::string const seed(policy->getString("rngSeed")); try { _seed = boost::lexical_cast(seed); } catch(boost::bad_lexical_cast &) {
    207 e2fd0793 - throw LSST_EXCEPT(ex::RuntimeErrorException,
    ? ---------
    207 21597d88 + throw LSST_EXCEPT(ex::RuntimeError,
    (boost::format("Invalid \"rngSeed\" policy value: \"%1%\"") % seed).str()); } initialize(policy->getString("rngAlgorithm")); } /** * Creates a deep copy of this random number generator. Both this random number * and its copy will subsequently produce an identical stream of random numbers. * * @return a deep copy of this random number generator *
    220 72a4ce55 - * @throw lsst::pex::exceptions::MemoryException
    ? ^^^^^^ ^
    220 21597d88 + * @throw lsst::pex::exceptions::MemoryError
    ? ^^ ^ * Thrown if memory allocation for internal generator state fails. */ math::Random math::Random::deepCopy() const { Random rng = *this; rng._rng.reset(::gsl_rng_clone(_rng.get()), ::gsl_rng_free); if (!rng._rng) {
    227 282b39c2 - throw LSST_EXCEPT(ex::MemoryException, "gsl_rng_clone() failed");
    ? ^^^^^^ ^
    227 21597d88 + throw LSST_EXCEPT(ex::MemoryError, "gsl_rng_clone() failed");
    ? ^^ ^ } return rng; } math::Random::State math::Random::getState() const { return State(static_cast(::gsl_rng_state(_rng.get())), getStateSize()); } void math::Random::setState(State const & state) { if (state.size() != getStateSize()) { throw LSST_EXCEPT(
    239 2923bfa1 - pex::exceptions::LengthErrorException,
    ? ---------
    239 21597d88 + pex::exceptions::LengthError,
    (boost::format("Size of given state vector (%d) does not match expected size (%d)") % state.size() % getStateSize()).str() ); } std::copy(state.begin(), state.end(), static_cast(::gsl_rng_state(_rng.get()))); } std::size_t math::Random::getStateSize() const { return ::gsl_rng_size(_rng.get()); } // -- Accessors -------- /** * @return The algorithm in use by this random number generator. */ math::Random::Algorithm math::Random::getAlgorithm() const { return _algorithm; } /** * @return The name of the algorithm in use by this random number generator. */ std::string math::Random::getAlgorithmName() const { return std::string(_algorithmNames[_algorithm]); } /** * @return The list of names of supported random number generation algorithms. */ std::vector const & math::Random::getAlgorithmNames() { static std::vector names; if (names.size() == 0) { for (int i = 0; i < NUM_ALGORITHMS; ++i) { names.push_back(_algorithmNames[i]); } } return names; } /** * @return The integer this random number generator was seeded with. * @note A seed value of 0 indicates that the random number generator * was seeded with an algorithm specific default value. */ unsigned long math::Random::getSeed() const { return _seed; } // -- Mutators: generating random numbers -------- /** * Returns a uniformly distributed random double precision floating point number from the * generator. The random number will be in the range [0, 1); the range includes 0.0 but * excludes 1.0. Note that some algorithms will not produce randomness across all mantissa * bits - choose an algorithm that produces double precisions results (such as * Random::RANLXD1, Random::TAUS, or * Random::MT19937) if this is important. * * @return a uniformly distributed random double precision floating point * number in the range [0, 1). * @sa uniformPositiveDouble() */ double math::Random::uniform() { return ::gsl_rng_uniform(_rng.get()); } /** * Returns a uniformly distributed random double precision floating point number from the * generator. The random number will be in the range (0, 1); the range excludes both 0.0 * and 1.0. Note that some algorithms will not produce randomness across all mantissa * bits - choose an algorithm that produces double precisions results (such as * Random::RANLXD1, Random::TAUS, or * Random::MT19937) if this is important. * * @return a uniformly distributed random double precision floating point * number in the range (0, 1). */ double math::Random::uniformPos() { return ::gsl_rng_uniform_pos(_rng.get()); } /** * Returns a uniformly distributed random integer from 0 to @a n-1. * * This function is not intended to generate values across the full range * of unsigned integer values [0, 2^32 - 1]. If this is necessary, use * a high precision algorithm like Random::RANLXD1, Random::TAUS, * or Random::MT19937 with a minimum value of zero and call get() directly. * * @param[in] n specifies the range of allowable return values (0 to @a n-1) * @return a uniformly distributed random integer *
    334 72a4ce55 - * @throw lsst::pex::exceptions::RangeErrorException
    ? ---------
    334 21597d88 + * @throw lsst::pex::exceptions::RangeError
    * Thrown if @a n is larger than the algorithm specific range of the generator. * * @sa get() * @sa getMin() * @sa getMax() */ unsigned long math::Random::uniformInt(unsigned long n) { if (n > ::gsl_rng_max(_rng.get()) - ::gsl_rng_min(_rng.get())) {
    343 72a4ce55 - throw LSST_EXCEPT(ex::RangeErrorException,
    ? ---------
    343 21597d88 + throw LSST_EXCEPT(ex::RangeError,
    "Desired random number range exceeds generator range"); } return ::gsl_rng_uniform_int(_rng.get(), n); } // -- Mutators: computing random variates for various distributions -------- /** * Returns a random variate from the flat (uniform) distribution on [@a a, @a b). * * @param[in] a lower endpoint of uniform distribution range (inclusive) * @param[in] b upper endpoint of uniform distribution range (exclusive) * @return a uniform random variate. */ double math::Random::flat(double const a, double const b) { return ::gsl_ran_flat(_rng.get(), a, b); } /** * Returns a gaussian random variate with mean @a 0 and standard deviation @a 1 * * @return a gaussian random variate * * @note The implementation uses the * Ziggurat algorithm. */ double math::Random::gaussian() { return ::gsl_ran_gaussian_ziggurat(_rng.get(), 1.0); } /** * Returns a random variate from the chi-squared distribution with @a nu degrees of freedom. * * @param[in] nu the number of degrees of freedom in the chi-squared distribution * @return a random variate from the chi-squared distribution */ double math::Random::chisq(double nu) { return ::gsl_ran_chisq(_rng.get(), nu); } /** * Returns a random variate from the poisson distribution with @a mean mu. * * @return a random variate from the Poission distribution */ double math::Random::poisson(double mu ///< desired mean (and variance) ) { return ::gsl_ran_poisson(_rng.get(), mu); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    e2fd0793

    commit e2fd079391f2668fd633fa992da84f7585063684
    Author: smm 
    Date:   Wed Mar 11 21:19:06 2009 +0000
    
        #678: changes to API based on feedback from RHL. Disallow 0 as a seed value, remove create() factory functions (lose ability to have env variables override constructor parameters)
    

    7a6ea5ce

    commit 7a6ea5ce178494cb61090089847aacd809082e36
    Author: bick 
    Date:   Wed Jan 6 20:50:58 2010 +0000
    
        #1113 sundry style corrections on afw.
    

    2923bfa1

    commit 2923bfa1ca211ca34bf66306496c1a20c26050c1
    Author: Jim Bosch 
    Date:   Mon Oct 14 15:32:50 2013 -0400
    
        Add accessors to save/load state in math::Random (#3025)
    

    72a4ce55

    commit 72a4ce55486da5742e7d29a05535b3092d6250c6
    Author: smm 
    Date:   Wed Mar 4 09:48:08 2009 +0000
    
        Intial check-in of GSL random number generator wrapper. Still needs unit tests
    

    282b39c2

    commit 282b39c2fe1558a4990a95d7ad77a6c634a2ccb5
    Author: smm 
    Date:   Thu Mar 5 08:57:19 2009 +0000
    
        #678: shorter names, provide factory functions for RNG creation which allow policy/env variables to override algorithm/seed parameters
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/math/warpExposure.h

    Diff:

                    // -*- LSST-C++ -*- // fixed format comment for emacs
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * \file
                     *
                     * \ingroup afw
                     *
                     * \brief Support for warping an image to a new WCS.
                     *
                     * \author Nicole M. Silvestri and Russell Owen, University of Washington
                     */
                    
                    #ifndef LSST_AFW_MATH_WARPEXPOSURE_H
                    #define LSST_AFW_MATH_WARPEXPOSURE_H
                    
                    #include 
                    
                    #include "boost/shared_ptr.hpp"
                    
                    #include "lsst/base.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/gpu/DevicePreference.h"
                    #include "lsst/afw/image/LsstImageTypes.h"
                    #include "lsst/afw/image/Exposure.h"
                    #include "lsst/afw/math/ConvolveImage.h"
                    #include "lsst/afw/math/Function.h"
                    #include "lsst/afw/math/FunctionLibrary.h"
                    #include "lsst/afw/math/Kernel.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace image {
                        class Wcs;
                    }
                    namespace math {
                    
                        /**
                        * \brief Lanczos warping: accurate but slow and can introduce ringing artifacts.
                        *
                        * This kernel is the product of two 1-dimensional Lanczos functions.
                        * The number of minima and maxima in the 1-dimensional Lanczos function is 2*order + 1.
                        * The kernel has one pixel per function minimum or maximum; but as applied to warping,
                        * the first or last pixel is always zero and can be omitted. Thus the kernel size is 2*order x 2*order.
                        *
                        * For more information about warping kernels see makeWarpingKernel
                        *
                        * @todo: make a new class WarpingKernel and make this a subclass.
                        */
                        class LanczosWarpingKernel : public SeparableKernel {
                        public:
                            explicit LanczosWarpingKernel(
                                int order ///< order of Lanczos function
                            )
                            :
                                SeparableKernel(2 * order, 2 * order,
                                    LanczosFunction1(order), LanczosFunction1(order))
                            {}
                    
                            virtual ~LanczosWarpingKernel() {}
                    
                            virtual PTR(Kernel) clone() const;
                    
                            int getOrder() const;
                    
                        protected:
                            virtual void setKernelParameter(unsigned int ind, double value) const;
                        };
                    
                        /**
                        * \brief Bilinear warping: fast; good for undersampled data.
                        *
                        * The kernel size is 2 x 2.
                        *
                        * For more information about warping kernels see makeWarpingKernel
                        *
                        * @todo: make a new class WarpingKernel and make this a subclass.
                        */
                        class BilinearWarpingKernel : public SeparableKernel {
                        public:
                            explicit BilinearWarpingKernel()
                            :
                                SeparableKernel(2, 2, BilinearFunction1(0.0), BilinearFunction1(0.0))
                            {}
                    
                            virtual ~BilinearWarpingKernel() {}
                    
                            virtual PTR(Kernel) clone() const;
                    
                            /**
                             * \brief 1-dimensional bilinear interpolation function.
                             *
                             * Optimized for bilinear warping so only accepts two values: 0 and 1
                             * (which is why it defined in the BilinearWarpingKernel class instead of
                             * being made available as a standalone function).
                             */
                            class BilinearFunction1: public Function1 {
                            public:
                                typedef PTR(Function1) Function1Ptr;
                    
                                /**
                                 * \brief Construct a Bilinear interpolation function
                                 */
                                explicit BilinearFunction1(
                                    double fracPos)    ///< fractional position; must be >= 0 and < 1
                                :
                                    Function1(1)
                                {
                                    this->_params[0] = fracPos;
                                }
                                virtual ~BilinearFunction1() {}
                    
                                virtual Function1Ptr clone() const {
                                    return Function1Ptr(new BilinearFunction1(this->_params[0]));
                                }
                    
                                virtual Kernel::Pixel operator() (double x) const;
                    
                                virtual std::string toString(std::string const& ="") const;
                            };
                    
                        protected:
                            virtual void setKernelParameter(unsigned int ind, double value) const;
                        };
                    
                        /**
                        * \brief Nearest neighbor warping: fast; good for undersampled data.
                        *
                        * The kernel size is 2 x 2.
                        *
                        * For more information about warping kernels see makeWarpingKernel
                        *
                        * @todo: make a new class WarpingKernel and make this a subclass.
                        */
                        class NearestWarpingKernel : public SeparableKernel {
                        public:
                            explicit NearestWarpingKernel()
                            :
                                SeparableKernel(2, 2, NearestFunction1(0.0), NearestFunction1(0.0))
                            {}
                    
                            virtual ~NearestWarpingKernel() {}
                    
                            virtual PTR(Kernel) clone() const;
                    
                            /**
                             * \brief 1-dimensional nearest neighbor interpolation function.
                             *
                             * Optimized for nearest neighbor warping so only accepts two values: 0 and 1
                             * (which is why it defined in the NearestWarpingKernel class instead of
                             * being made available as a standalone function).
                             */
                            class NearestFunction1: public Function1 {
                            public:
                                typedef PTR(Function1) Function1Ptr;
                    
                                /**
                                 * \brief Construct a Nearest interpolation function
                                 */
                                explicit NearestFunction1(
                                    double fracPos)    ///< fractional position
                                :
                                    Function1(1)
                                {
                                    this->_params[0] = fracPos;
                                }
                                virtual ~NearestFunction1() {}
                    
                                virtual Function1Ptr clone() const {
                                    return Function1Ptr(new NearestFunction1(this->_params[0]));
                                }
                    
                                virtual Kernel::Pixel operator() (double x) const;
                    
                                virtual std::string toString(std::string const& ="") const;
                            };
                    
                        protected:
                            virtual void setKernelParameter(unsigned int ind, double value) const;
                        };
                    
                        /**
                         * \brief Return a warping kernel given its name.
                         *
                         * Intended for use with warpImage() and warpExposure().
                         *
                         * Allowed names are:
                         * - bilinear: return a BilinearWarpingKernel
                         * - lanczos#: return a LanczosWarpingKernel of order #, e.g. lanczos4
                         * - nearest: return a NearestWarpingKernel
                         *
                         * A warping kernel is a subclass of SeparableKernel with the following properties
                         * (though for the sake of speed few, if any, of these are enforced):
                         * - Width and height are even. This is unusual for a kernel, but it is more efficient
                         *   because if the extra pixel was included it would always have value 0.
                         * - The center pixels should be adjacent to the kernel center.
                         *   Again, this avoids extra pixels that are sure to have value 0.
                         * - It has two parameters: fractional x and fractional row position on the source %image.
                         *   The fractional position is the offset of the pixel position on the source
                         *   from the center of a nearby source pixel:
                         *   - The pixel whose center is just below or to the left of the source position:
                         *     0 <= fractional x and y < 0 and the kernel center is the default (size-1)/2.
                         *   - The pixel whose center is just above or to the right of the source position:
                         *     -1.0 < fractional x and y <= 0 and the kernel center must be set to (size+1)/2.
                         */
                        PTR(SeparableKernel) makeWarpingKernel(std::string name);
                    
                        /**
                         * \brief Parameters to control convolution
                         *
                         * \note padValue is not member of this class to avoid making this a templated class.
                         *
                         * \warning: GPU acceleration requires interpLength > 0
                         *
                         * \ingroup afw
                         */
                        class WarpingControl {
                        public:
                            /**
                             * \brief Construct a WarpingControl object
                             *
                             * @warning: the GPU code does not yet support warping the mask with
                             * a separate kernel. Thus if maskWarpingKernelName is provided
                             * the GPU is disabled (or an exception is raised if the GPU is required)
                             *
    
    248 fba55aa3 - * @throw pex_exceptions InvalidParameterException if the warping kernel
    ? ^^^^^^ ^
    248 21597d88 + * @throw pex_exceptions InvalidParameterError if the warping kernel
    ? ^^ ^ * is smaller than the mask warping kernel.
    250 211140a5 - * @throw pex_exceptions InvalidParameterException if GPU is required
    ? ^^^^^^ ^
    250 21597d88 + * @throw pex_exceptions InvalidParameterError if GPU is required
    ? ^^ ^ * and maskWarpingKernelName supplied. */ explicit WarpingControl( std::string const &warpingKernelName, ///< name of warping kernel; ///< used as the argument to makeWarpingKernel std::string const &maskWarpingKernelName = "", ///< name of warping kernel used for ///< the mask plane; if "" then the regular warping kernel is used. ///< Intended so one can use a bilinear kernel or other compact kernel for the mask plane ///< to avoid smearing mask bits too far. The theory is that bad pixels are already ///< interpolated over, so we don't need to worry about bad values spreading very far. int cacheSize = 0, ///< cache size for warping kernel; no cache if 0 ///< (used as the argument to the warping kernels' computeCache method) int interpLength = 0, ///< distance over which the WCS can be linearly interpolated lsst::afw::gpu::DevicePreference devicePreference = lsst::afw::gpu::DEFAULT_DEVICE_PREFERENCE, ///< use GPU acceleration? lsst::afw::image::MaskPixel growFullMask = 0 ///< mask bits to grow to full width of image/variance kernel ) : _warpingKernelPtr(makeWarpingKernel(warpingKernelName)), _maskWarpingKernelPtr(), _cacheSize(cacheSize), _interpLength(interpLength), _devicePreference(devicePreference), _growFullMask(growFullMask) { setMaskWarpingKernelName(maskWarpingKernelName); _testDevicePreference(_devicePreference, _warpingKernelPtr); } /** * \brief This constructor supports the deprecated legacy warping API */ explicit WarpingControl( SeparableKernel &warpingKernel, ///< warping kernel int interpLength = 0, ///< distance over which the WCS can be linearly interpolated; ///< 0 means no interpolation and uses an optimized branch of the code ///< 1 also performs no interpolation but it runs the interpolation code branch ///< (and so is only intended for unit tests) lsst::afw::gpu::DevicePreference devicePreference = lsst::afw::gpu::DEFAULT_DEVICE_PREFERENCE ///< use GPU acceleration? ) : _warpingKernelPtr(boost::dynamic_pointer_cast(warpingKernel.clone())), _maskWarpingKernelPtr(), _cacheSize(warpingKernel.getCacheSize()), _interpLength(interpLength), _devicePreference(devicePreference),
    297 73fb00fd - _growFullMask(lsst::afw::image::Mask::getPlaneBitMask("EDGE") |
    ? ^^
    297 d11df1d4 + _growFullMask(lsst::afw::image::Mask::getPlaneBitMask("EDGE"))
    ? ^
    298 73fb00fd - lsst::afw::image::Mask::getPlaneBitMask("NO_DATA"))
    { _testDevicePreference(_devicePreference, _warpingKernelPtr); } virtual ~WarpingControl() {}; /** * @brief get the cache size for the interpolation kernel(s) */ int getCacheSize() const { return _cacheSize; }; /** * @brief set the cache size for the interpolation kernel(s) * * A value of 0 disables the cache for maximum accuracy. * 10,000 typically results in a warping error of a fraction of a count. * 100,000 typically results in a warping error of less than 0.01 count. * Note the new cache is not computed until getWarpingKernel or getMaskWarpingKernel is called. */ void setCacheSize( int cacheSize ///< cache size ) { _cacheSize = cacheSize; }; /** * @brief get the interpolation length (pixels) */ int getInterpLength() const { return _interpLength; }; /** * @brief set the interpolation length * * Interpolation length is the distance over which the WCS can be linearly interpolated, in pixels: * * 0 means no interpolation and uses an optimized branch of the code * * 1 also performs no interpolation but it runs the interpolation code branch * (and so is only intended for unit tests) */ void setInterpLength( int interpLength ///< interpolation length (pixels) ) { _interpLength = interpLength; }; /** * @brief get the GPU device preference */ lsst::afw::gpu::DevicePreference getDevicePreference() const { return _devicePreference; }; /** * @brief set the GPU device preference */ void setDevicePreference( lsst::afw::gpu::DevicePreference devicePreference ///< device preference ) { _testDevicePreference(devicePreference, _warpingKernelPtr); _devicePreference = devicePreference; } /** * @brief get the warping kernel */ PTR(SeparableKernel) getWarpingKernel() const; /** * @brief set the warping kernel by name */ void setWarpingKernelName( std::string const &warpingKernelName ///< name of warping kernel ); /** * @brief set the warping kernel *
    370 00ce5756 - * @throw lsst::pex::exceptions::InvalidParameterException if new kernel pointer is empty.
    ? ^^^^^^ ^
    369 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if new kernel pointer is empty.
    ? ^^ ^ */ void setWarpingKernel( SeparableKernel const &warpingKernel ///< warping kernel ); /** * @brief get the mask warping kernel */ PTR(SeparableKernel) getMaskWarpingKernel() const; /** * @brief return true if there is a mask kernel */ bool hasMaskWarpingKernel() const { return static_cast(_maskWarpingKernelPtr); } /** * @brief set or clear the mask warping kernel by name */ void setMaskWarpingKernelName( std::string const &maskWarpingKernelName ///< name of mask warping kernel; use "" to clear the kernel ); /** * @brief set the mask warping kernel * * @note To clear the mask warping kernel use setMaskWarpingKernelName(""). */ void setMaskWarpingKernel( SeparableKernel const &maskWarpingKernel ///< mask warping kernel ); /** * @brief get mask bits to grow to full width of image/variance kernel */ lsst::afw::image::MaskPixel getGrowFullMask() const { return _growFullMask; }; /** * @brief set mask bits to grow to full width of image/variance kernel */ void setGrowFullMask( lsst::afw::image::MaskPixel growFullMask ///< device preference ) { _growFullMask = growFullMask; } private: /** * @brief Throw an exception if the two kernels are not compatible in shape *
    419 00ce5756 - * @throw lsst::pex::exceptions::InvalidParameterException if the two kernels
    ? ^^^^^^ ^
    418 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the two kernels
    ? ^^ ^ * are not compatible in shape */ void _testWarpingKernels( SeparableKernel const &warpingKernel, ///< warping kernel SeparableKernel const &maskWarpingKernel ///< mask warping kernel ) const; /** * @brief test if GPU device preference and main warping kernel are compatible *
    430 00ce5756 - * @throw lsst::pex::exceptions::InvalidParameterException if the parameters are incompatible
    ? ^^^^^^ ^
    429 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the parameters are incompatible
    ? ^^ ^ */ void _testDevicePreference( lsst::afw::gpu::DevicePreference const &devicePreference, ///< GPU device preference CONST_PTR(SeparableKernel) const &warpingKernelPtr ///< warping kernel ) const; PTR(SeparableKernel) _warpingKernelPtr; PTR(SeparableKernel) _maskWarpingKernelPtr; int _cacheSize; int _interpLength; lsst::afw::gpu::DevicePreference _devicePreference; ///< choose CPU or GPU acceleration lsst::afw::image::MaskPixel _growFullMask; }; /** * \brief Warp (remap) one exposure to another. * * This is a convenience wrapper around warpImage(). */ template int warpExposure( DestExposureT &destExposure, ///< Remapped exposure. Wcs and xy0 are read, MaskedImage is set, ///< and Calib and Filter are copied from srcExposure. ///< All other attributes are left alone (including Detector and Psf) SrcExposureT const &srcExposure, ///< Source exposure WarpingControl const &control, ///< control parameters typename DestExposureT::MaskedImageT::SinglePixel padValue = lsst::afw::math::edgePixel( typename lsst::afw::image::detail::image_traits< typename DestExposureT::MaskedImageT>::image_category()) ///< use this value for undefined (edge) pixels ); /** * \brief Warp (remap) one exposure to another. * * This variant uses an older, deprecated interface. */ template int warpExposure( DestExposureT &destExposure, ///< Remapped exposure. Wcs and xy0 are read, MaskedImage is set, ///< and Calib and Filter are copied from srcExposure. ///< All other attributes are left alone (including Detector and Psf) SrcExposureT const &srcExposure, ///< Source exposure SeparableKernel &warpingKernel, ///< Warping kernel; determines warping algorithm int const interpLength=0, ///< Distance over which WCS can be linearily interpolated typename DestExposureT::MaskedImageT::SinglePixel padValue = lsst::afw::math::edgePixel( typename lsst::afw::image::detail::image_traits::image_category()), ///< use this value for undefined (edge) pixels lsst::afw::gpu::DevicePreference devPref = lsst::afw::gpu::DEFAULT_DEVICE_PREFERENCE ///< Specifies whether to use CPU or GPU device ); /** * \brief Warp an Image or MaskedImage to a new Wcs. See also convenience function * warpExposure() to warp an Exposure. * * Edge pixels are set to padValue; these are pixels that cannot be computed because they * are too near the edge of srcImage or miss srcImage entirely. * * \return the number of valid pixels in destImage (those that are not edge pixels). * * \note This function is able to use GPU acceleration when interpLength > 0. * * \b Algorithm Without Interpolation: * * For each integer pixel position in the remapped Exposure: * - The associated pixel position on srcImage is determined using the destination and source WCS * - The warping kernel's parameters are set based on the fractional part of the pixel position on srcImage * - The warping kernel is applied to srcImage at the integer portion of the pixel position * to compute the remapped pixel value * - A flux-conservation factor is determined from the source and destination WCS * and is applied to the remapped pixel * * The scaling of intensity for relative area of source and destination uses two minor approximations: * - The area of the sky marked out by a pixel on the destination %image * corresponds to a parallellogram on the source %image. * - The area varies slowly enough across the %image that we can get away with computing * the source area shifted by half a pixel up and to the left of the true area. * * \b Algorithm With Interpolation: * * Interpolation simply reduces the number of times WCS is used to map between destination and source * pixel position. This computation is only made at a grid of points on the destination image, * separated by interpLen pixels along rows and columns. All other source pixel positions are determined * by linear interpolation between those grid points. Everything else remains the same. *
    520 8a049406 - * \throw lsst::pex::exceptions::InvalidParameterException if destImage is srcImage
    ? ^^^^^^ ^
    519 21597d88 + * \throw lsst::pex::exceptions::InvalidParameterError if destImage is srcImage
    ? ^^ ^
    521 8a049406 - * \throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    520 21597d88 + * \throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    522 8a049406 - * \throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    521 21597d88 + * \throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    523 8a049406 - * \throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    522 21597d88 + * \throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * \todo Should support an additional color-based position correction in the remapping * (differential chromatic refraction). This can be done either object-by-object or pixel-by-pixel. * * \todo Need to deal with oversampling and/or weight maps. If done we can use faster kernels than sinc. */ template int warpImage( DestImageT &destImage, ///< remapped %image lsst::afw::image::Wcs const &destWcs, ///< WCS of remapped %image SrcImageT const &srcImage, ///< source %image lsst::afw::image::Wcs const &srcWcs, ///< WCS of source %image WarpingControl const &control, ///< control parameters typename DestImageT::SinglePixel padValue = lsst::afw::math::edgePixel( typename lsst::afw::image::detail::image_traits::image_category()) ///< use this value for undefined (edge) pixels ); /** * \brief A variant of warpImage that uses an older, deprecated interface */ template int warpImage( DestImageT &destImage, ///< remapped %image lsst::afw::image::Wcs const &destWcs, ///< WCS of remapped %image SrcImageT const &srcImage, ///< source %image lsst::afw::image::Wcs const &srcWcs, ///< WCS of source %image SeparableKernel &warpingKernel, ///< warping kernel; determines warping algorithm int const interpLength=0, ///< Distance over which WCS can be linearily interpolated ///< 0 means no interpolation and uses an optimized branch of the code ///< 1 also performs no interpolation but it runs the interpolation code branch typename DestImageT::SinglePixel padValue = lsst::afw::math::edgePixel( typename lsst::afw::image::detail::image_traits::image_category()), ///< use this value for undefined (edge) pixels lsst::afw::gpu::DevicePreference devPref = lsst::afw::gpu::DEFAULT_DEVICE_PREFERENCE ///< Specifies whether to use CPU or GPU device ); /** * \brief A variant of warpImage that uses an affine transformation instead of a WCS * to describe the transformation. */ template int warpImage( DestImageT &destImage, ///< remapped %image SrcImageT const &srcImage, ///< source %image lsst::afw::geom::AffineTransform const &affineTransform, ///< affine transformation to apply WarpingControl const &control, ///< control parameters typename DestImageT::SinglePixel padValue = lsst::afw::math::edgePixel( typename lsst::afw::image::detail::image_traits::image_category()) ///< use this value for undefined (edge) pixels ); /** * \brief A variant of the affine transformation warpImage that uses an older, deprecated interface */ template int warpImage( DestImageT &destImage, ///< remapped %image SrcImageT const &srcImage, ///< source %image SeparableKernel &warpingKernel, ///< warping kernel; determines warping algorithm lsst::afw::geom::AffineTransform const &affineTransform, ///< affine transformation to apply int const interpLength = 0, ///< Distance over which WCS can be linearily interpolated ///< 0 means no interpolation and uses an optimized branch of the code ///< 1 also performs no interpolation but it runs the interpolation code branch typename DestImageT::SinglePixel padValue = lsst::afw::math::edgePixel( typename lsst::afw::image::detail::image_traits::image_category()), ///< use this value for undefined (edge) pixels lsst::afw::gpu::DevicePreference devPref = lsst::afw::gpu::DEFAULT_DEVICE_PREFERENCE ///< Specifies whether to use CPU or GPU device );
    595 a845140d +
    596 a845140d + /**
    597 a845140d + * @brief Warp an image with a LinearTranform about a specified point.
    598 a845140d + * This enables warping an image of e.g. a PSF without translating the centroid.
    599 a845140d + */
    template int warpCenteredImage( DestImageT &destImage, ///< remapped %image SrcImageT const &srcImage, ///< source %image lsst::afw::geom::LinearTransform const &linearTransform, ///< linear transformation to apply
    601 fac833c8 - lsst::afw::geom::Point2D const ¢erPixel, ///< pixel corresponding to location of linearTransform
    ? ^^^ -- ^ -------------
    605 7edb421a + lsst::afw::geom::Point2D const ¢erPosition, ///< pixel position for location of linearTransform
    ? ++ ^^^^ ^^^^^^^^^^ WarpingControl const &control, ///< control parameters typename DestImageT::SinglePixel padValue = lsst::afw::math::edgePixel( typename lsst::afw::image::detail::image_traits::image_category()) ///< use this value for undefined (edge) pixels ); /** * @brief A variant of warpCenteredImage that supports the old, deprecated interface */ template int warpCenteredImage( DestImageT &destImage, ///< remapped %image SrcImageT const &srcImage, ///< source %image SeparableKernel &warpingKernel, ///< warping kernel; determines warping algorithm lsst::afw::geom::LinearTransform const &linearTransform, ///< linear transformation to apply
    617 8a049406 - lsst::afw::geom::Point2D const ¢erPixel, ///< pixel corresponding to location of linearTransform
    ? ^^^
    621 7edb421a + lsst::afw::geom::Point2D const ¢erPosition, ///< pixel corresponding to location of linearTransform
    ? ++ ^^^^ int const interpLength = 0, ///< Distance over which WCS can be linearily interpolated ///< 0 means no interpolation and uses an optimized branch of the code ///< 1 also performs no interpolation but it runs the interpolation code branch typename DestImageT::SinglePixel padValue = lsst::afw::math::edgePixel( typename lsst::afw::image::detail::image_traits::image_category()), ///< use this value for undefined (edge) pixels lsst::afw::gpu::DevicePreference devPref = lsst::afw::gpu::DEFAULT_DEVICE_PREFERENCE ///< Specifies whether to use CPU or GPU device ); namespace details { template bool isSameObject(A const&, B const&) { return false; } template bool isSameObject(A const& a, A const& b) { return &a == &b; } } }}} // lsst::afw::math #endif // !defined(LSST_AFW_MATH_WARPEXPOSURE_H)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    211140a5

    commit 211140a53f1ceb08c462a70d1c887f4c54d31906
    Author: Russell Owen 
    Date:   Fri Jun 29 15:35:07 2012 -0700
    
        Disable GPU if maskWarpingKernel specified (for now, until the GPU supports this case);
        raise an exception if the user requires the GPU and specifies a mask warping kernel.
        Replace NULL == ptr with !ptr at Jim's sensible request
        Fix error in tests/warpExposure.py: if verifyMaskWarp failed had problems in the error reporting.
    

    fba55aa3

    commit fba55aa3cbd26df56f7ddba6b55bc69e7dae2d77
    Author: Russell Owen 
    Date:   Fri Jun 29 13:08:53 2012 -0700
    
        Finished. Unit tests pass. The images look good.
    

    8a049406

    commit 8a0494065e210e37d4f92d61b38f9d126372b7eb
    Author: Russell Owen 
    Date:   Wed Jun 27 17:09:10 2012 -0700
    
        Preparatory work to support warping the mask plane with a different kernel (e.g. bilinear):
         * Added a WarpingControl object that allows specifying a separate mask kernel
         * Added getCacheSize method to Kernel to support WarpingControl
         * Added new versions of the various warping functions that support this control object,
           and modified the old ones to internally make a control object
         * Moved SrcPosFunctor to its own header file and moved the AffineTransform version there,
           to keep company with the base and WCS versions and make everything easier to find.
    

    00ce5756

    commit 00ce575662c509aecfdb39f8b73813a7fb362b85
    Author: Russell Owen 
    Date:   Mon Oct 8 16:46:08 2012 -0700
    
        Done
    

    73fb00fd

    commit 73fb00fd8b3533247dad52e9a46e2470b77fe48f
    Author: Paul Price 
    Date:   Thu May 22 11:08:42 2014 -0400
    
        add NO_DATA mask plane, and use in warping/convolution
        
        The EDGE mask plane was originally intended to mean "pixel near the
        edge of the detector, so we haven't been able to properly convolve to
        search for sources", but it was hijacked to mean "pixels in a warped
        image that are off the edge of the original".  It has since had both
        meanings, which should be distinct.
        
        We introduce the NO_DATA mask plane to mean "pixels off the edge of
        the original", and reserve "EDGE" to mean "pixels near the edge".
        afw::math::edgePixel (used for pixels with no good inputs when
        warping) now returns a value for pixels *off* the edge (should it
        be renamed? but that's changing a public API).  Convolution now
        masks pixels near the edge as EDGE if copying edge pixels, and
        NO_DATA otherwise.
    

    fac833c8

    commit fac833c87de064a4149664a51d8f5a8269c5a88d
    Author: Russell Owen 
    Date:   Fri Jun 29 14:37:28 2012 -0700
    
        Add new version of warpCenteredImage that uses WarpingControl and modified the old version to call it.
        Modified examples to use the new warping API. That only leaves the GPU example and tests
        which I'm reluctant to test without a GPU.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    7edb421a

    commit 7edb421a3873253a40cbdd4600c0ab25c47ba88a
    Author: Steven Bickerton 
    Date:   Mon Feb 17 15:50:18 2014 +0900
    
        variable centerPixel -> centerPosition.  Use 'position' in comments.
    

    d11df1d4

    commit d11df1d4191847e301cb3a08888bbfdbb8ea7d8b
    Author: Russell Owen 
    Date:   Mon Sep 24 13:10:52 2012 -0700
    
        Code implemented and passes all unit tests (despite the change in behavior).
        Needs new unit tests.
    

    a845140d

    commit a845140d940b4c919ac0e6da81cdc1b326dadd21
    Author: Steven Bickerton 
    Date:   Thu Jan 23 16:56:11 2014 +0900
    
        Added doxygen
    

    Return to list

    src/math/DeltaFunctionKernel.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include 
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/KernelPersistenceHelper.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace afwMath = lsst::afw::math;
                    namespace afwImage = lsst::afw::image;
                    namespace afwGeom = lsst::afw::geom;
                    
                    afwMath::DeltaFunctionKernel::DeltaFunctionKernel(
                        int width,
                        int height,
                        afwGeom::Point2I const &point
                    ) :
                        Kernel(width, height, 0),
                        _pixel(point)
                    {
                        if (point.getX() < 0 || point.getX() >= width || point.getY() < 0 || point.getY() >= height) {
                            std::ostringstream os;
                            os << "point (" << point.getX() << ", " << point.getY() << ") lies outside "
                                << width << "x" << height << " sized kernel";
    
    48 d7b24982 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    48 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } } PTR(afwMath::Kernel) afwMath::DeltaFunctionKernel::clone() const { PTR(afwMath::Kernel) retPtr(new afwMath::DeltaFunctionKernel(this->getWidth(), this->getHeight(), this->_pixel)); retPtr->setCtr(this->getCtr()); return retPtr; } std::string afwMath::DeltaFunctionKernel::toString(std::string const& prefix) const { const int pixelX = getPixel().getX(); // active pixel in Kernel const int pixelY = getPixel().getY(); std::ostringstream os; os << prefix << "DeltaFunctionKernel:" << std::endl; os << prefix << "Pixel (c,r) " << pixelX << "," << pixelY << ")" << std::endl; os << Kernel::toString(prefix + "\t"); return os.str(); } double afwMath::DeltaFunctionKernel::doComputeImage( afwImage::Image &image, bool ) const { const int pixelX = getPixel().getX(); // active pixel in Kernel const int pixelY = getPixel().getY(); image = 0; *image.xy_at(pixelX, pixelY) = 1; return 1; } // ------ Persistence --------------------------------------------------------------------------------------- namespace lsst { namespace afw { namespace math { namespace { struct DeltaFunctionKernelPersistenceHelper : public Kernel::PersistenceHelper, private boost::noncopyable { table::Key< table::Point > pixel; static DeltaFunctionKernelPersistenceHelper const & get() { static DeltaFunctionKernelPersistenceHelper const instance; return instance; } private: explicit DeltaFunctionKernelPersistenceHelper() : Kernel::PersistenceHelper(0), pixel(schema.addField< table::Point >("pixel", "position of nonzero pixel")) { schema.getCitizen().markPersistent(); } }; } // anonymous class DeltaFunctionKernel::Factory : public afw::table::io::PersistableFactory { public: virtual PTR(afw::table::io::Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const { LSST_ARCHIVE_ASSERT(catalogs.size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); DeltaFunctionKernelPersistenceHelper const & keys = DeltaFunctionKernelPersistenceHelper::get(); LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys.schema); afw::table::BaseRecord const & record = catalogs.front().front(); PTR(DeltaFunctionKernel) result( new DeltaFunctionKernel(record.get(keys.dimensions.getX()), record.get(keys.dimensions.getY()), record.get(keys.pixel)) ); result->setCtr(record.get(keys.center)); return result; } explicit Factory(std::string const & name) : afw::table::io::PersistableFactory(name) {} }; namespace { std::string getDeltaFunctionKernelPersistenceName() { return "DeltaFunctionKernel"; } DeltaFunctionKernel::Factory registration(getDeltaFunctionKernelPersistenceName()); } // anonymous std::string DeltaFunctionKernel::getPersistenceName() const { return getDeltaFunctionKernelPersistenceName(); } void DeltaFunctionKernel::write(OutputArchiveHandle & handle) const { DeltaFunctionKernelPersistenceHelper const & keys = DeltaFunctionKernelPersistenceHelper::get(); PTR(afw::table::BaseRecord) record = keys.write(handle, *this); record->set(keys.pixel, _pixel); } }}} // namespace lsst::afw::math

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d7b24982

    commit d7b24982db8562dc77c4bcc33c84107c65fd686d
    Author: rowen 
    Date:   Thu Oct 29 00:15:47 2009 +0000
    
        Fixed ticket #1000 by adding a missing test to a LinearCombinationKernel constructor.
        Updated tests/Kernel.cc as suggested by Serge so it would not trigger the problem.
        Updated many exceptions in kernel constructors to print more details.
        Added unit tests for the exceptions in kernel methods.
        
        Note: the current code has a swig warning about a shadowed constructor in LinearCombinationKernel.
        This should be resolved before committing the changes to the trunk. See my email to lsst-data.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/kernel.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import math, re import unittest import numpy import lsst.utils.tests as utilsTests import lsst.pex.exceptions as pexExcept import lsst.pex.logging as pexLog import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.math as afwMath
    35 b10ab54c - import lsst.afw.image.testUtils as imTestUtils
    VERBOSITY = 0 # increase to see trace pexLog.Debug("lsst.afw", VERBOSITY) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def makeGaussianKernelList(kWidth, kHeight, gaussParamsList): """Create a list of gaussian kernels. This is useful for constructing a LinearCombinationKernel. Inputs: - kWidth, kHeight: width and height of kernel - gaussParamsList: a list of parameters for GaussianFunction2D (each a 3-tuple of floats) """ kVec = afwMath.KernelList() for majorSigma, minorSigma, angle in gaussParamsList: kFunc = afwMath.GaussianFunction2D(majorSigma, minorSigma, angle) kVec.append(afwMath.AnalyticKernel(kWidth, kHeight, kFunc)) return kVec def makeDeltaFunctionKernelList(kWidth, kHeight): """Create a list of delta function kernels This is useful for constructing a LinearCombinationKernel. """ kVec = afwMath.KernelList() for activeCol in range(kWidth): for activeRow in range(kHeight): kVec.append(afwMath.DeltaFunctionKernel(kWidth, kHeight, afwGeom.Point2I(activeCol, activeRow))) return kVec class KernelTestCase(unittest.TestCase): """A test case for Kernels""" def testAnalyticKernel(self): """Test AnalyticKernel using a Gaussian function """ kWidth = 5 kHeight = 8 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) self.basicTests(kernel, 3, dimMustMatch=False) fArr = numpy.zeros(shape=[kernel.getWidth(), kernel.getHeight()], dtype=float) for xsigma in (0.1, 1.0, 3.0): for ysigma in (0.1, 1.0, 3.0): gaussFunc.setParameters((xsigma, ysigma, 0.0)) # compute array of function values and normalize for row in range(kernel.getHeight()): y = row - kernel.getCtrY() for col in range(kernel.getWidth()): x = col - kernel.getCtrX() fArr[col, row] = gaussFunc(x, y) fArr /= fArr.sum() kernel.setKernelParameters((xsigma, ysigma, 0.0)) kImage = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kImage, True) kArr = kImage.getArray().transpose() if not numpy.allclose(fArr, kArr): self.fail("%s = %s != %s for xsigma=%s, ysigma=%s" % \ (kernel.__class__.__name__, kArr, fArr, xsigma, ysigma)) kernel.setKernelParameters((0.5, 1.1, 0.3)) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) kernel.setKernelParameters((1.5, 0.2, 0.7)) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail("Clone was modified by changing original's kernel parameters") self.verifyCache(kernel, hasCache=False) def verifyCache(self, kernel, hasCache=False): """Verify the kernel cache @param kernel: kernel to test @param hasCache: set True if this kind of kernel supports a cache, False otherwise """ for cacheSize in (0, 100, 2000): kernel.computeCache(cacheSize) self.assertEqual(kernel.getCacheSize(), cacheSize if hasCache else 0) kernelCopy = kernel.clone() self.assertEqual(kernelCopy.getCacheSize(), kernel.getCacheSize()) def testShrinkGrowBBox(self): """Test Kernel methods shrinkBBox and growBBox """ boxStart = afwGeom.Point2I(3, -3) for kWidth in (1, 2, 6): for kHeight in (1, 2, 5): for deltaWidth in (-1, 0, 1, 20): fullWidth = kWidth + deltaWidth for deltaHeight in (-1, 0, 1, 20): fullHeight = kHeight + deltaHeight kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, afwGeom.Point2I(0, 0)) fullBBox = afwGeom.Box2I(boxStart, afwGeom.Extent2I(fullWidth, fullHeight)) if (fullWidth < kWidth) or (fullHeight < kHeight): self.assertRaises(Exception, kernel.shrinkBBox, fullBBox) continue shrunkBBox = kernel.shrinkBBox(fullBBox) self.assert_((shrunkBBox.getWidth() == fullWidth + 1 - kWidth) and (shrunkBBox.getHeight() == fullHeight + 1 - kHeight), "shrinkBBox returned box of wrong size") self.assert_((shrunkBBox.getMinX() == boxStart[0] + kernel.getCtrX()) and (shrunkBBox.getMinY() == boxStart[1] + kernel.getCtrY()), "shrinkBBox returned box with wrong minimum") newFullBBox = kernel.growBBox(shrunkBBox) self.assert_(newFullBBox == fullBBox, "growBBox(shrinkBBox(x)) != x") def testDeltaFunctionKernel(self): """Test DeltaFunctionKernel """ for kWidth in range(1, 4): for kHeight in range(1, 4): for activeCol in range(kWidth): for activeRow in range(kHeight): kernel = afwMath.DeltaFunctionKernel(kWidth, kHeight, afwGeom.Point2I(activeCol, activeRow)) kImage = afwImage.ImageD(kernel.getDimensions()) kSum = kernel.computeImage(kImage, False) self.assertEqual(kSum, 1.0) kArr = kImage.getArray().transpose() self.assertEqual(kArr[activeCol, activeRow], 1.0) kArr[activeCol, activeRow] = 0.0 self.assertEqual(kArr.sum(), 0.0) errStr = self.compareKernels(kernel, kernel.clone()) if errStr: self.fail(errStr)
    173 3771b5eb - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    173 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ afwMath.DeltaFunctionKernel, 0, kHeight, afwGeom.Point2I(kWidth, kHeight))
    175 3771b5eb - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    175 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ afwMath.DeltaFunctionKernel, kWidth, 0, afwGeom.Point2I(kWidth, kHeight)) kernel = afwMath.DeltaFunctionKernel(5, 6, afwGeom.Point2I(1, 1)) self.basicTests(kernel, 0) self.verifyCache(kernel, hasCache=False) def testFixedKernel(self): """Test FixedKernel using a ramp function """ kWidth = 5 kHeight = 6 inArr = numpy.arange(kWidth * kHeight, dtype=float) inArr.shape = [kWidth, kHeight] inImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) for row in range(inImage.getHeight()): for col in range(inImage.getWidth()): inImage.set(col, row, inArr[col, row]) kernel = afwMath.FixedKernel(inImage) self.basicTests(kernel, 0) outImage = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(outImage, False) outArr = outImage.getArray().transpose() if not numpy.allclose(inArr, outArr): self.fail("%s = %s != %s (not normalized)" % \ (kernel.__class__.__name__, inArr, outArr)) normInArr = inArr / inArr.sum() normOutImage = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(normOutImage, True) normOutArr = normOutImage.getArray().transpose() if not numpy.allclose(normOutArr, normInArr): self.fail("%s = %s != %s (normalized)" % \ (kernel.__class__.__name__, normInArr, normOutArr)) errStr = self.compareKernels(kernel, kernel.clone()) if errStr: self.fail(errStr) self.verifyCache(kernel, hasCache=False) def testLinearCombinationKernelDelta(self): """Test LinearCombinationKernel using a set of delta basis functions """ kWidth = 3 kHeight = 2 # create list of kernels basisKernelList = makeDeltaFunctionKernelList(kWidth, kHeight) basisImArrList = [] for basisKernel in basisKernelList: basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImArrList.append(basisImage.getArray()) kParams = [0.0]*len(basisKernelList) kernel = afwMath.LinearCombinationKernel(basisKernelList, kParams) self.assert_(kernel.isDeltaFunctionBasis()) self.basicTests(kernel, len(kParams)) for ii in range(len(basisKernelList)): kParams = [0.0]*len(basisKernelList) kParams[ii] = 1.0 kernel.setKernelParameters(kParams) kIm = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kIm, True) kImArr = kIm.getArray() if not numpy.allclose(kImArr, basisImArrList[ii]): self.fail("%s = %s != %s for the %s'th basis kernel" % \ (kernel.__class__.__name__, kImArr, basisImArrList[ii], ii)) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) self.verifyCache(kernel, hasCache=False) def testComputeImageRaise(self): """Test Kernel.computeImage raises OverflowException iff doNormalize True and kernel sum exactly 0 """ kWidth = 4 kHeight = 3 polyFunc1 = afwMath.PolynomialFunction1D(0) polyFunc2 = afwMath.PolynomialFunction2D(0) analKernel = afwMath.AnalyticKernel(kWidth, kHeight, polyFunc2) kImage = afwImage.ImageD(analKernel.getDimensions()) for coeff in (-1, -1e-99, 0, 1e99, 1): analKernel.setKernelParameters([coeff]) analKernel.computeImage(kImage, False) fixedKernel = afwMath.FixedKernel(kImage) sepKernel = afwMath.SeparableKernel(kWidth, kHeight, polyFunc1, polyFunc1) sepKernel.setKernelParameters([coeff, coeff]) kernelList = afwMath.KernelList() kernelList.append(analKernel) lcKernel = afwMath.LinearCombinationKernel(kernelList, [1]) self.assert_(not lcKernel.isDeltaFunctionBasis()) doRaise = (coeff == 0) self.basicTestComputeImageRaise(analKernel, doRaise, "AnalyticKernel") self.basicTestComputeImageRaise(fixedKernel, doRaise, "FixedKernel") self.basicTestComputeImageRaise(sepKernel, doRaise, "SeparableKernel") self.basicTestComputeImageRaise(lcKernel, doRaise, "LinearCombinationKernel") lcKernel.setKernelParameters([0]) self.basicTestComputeImageRaise(lcKernel, True, "LinearCombinationKernel") def testLinearCombinationKernelAnalytic(self): """Test LinearCombinationKernel using analytic basis kernels. The basis kernels are mutable so that we can verify that the LinearCombinationKernel has private copies of the basis kernels. """ kWidth = 5 kHeight = 8 # create list of kernels basisImArrList = [] basisKernelList = afwMath.KernelList() for basisKernelParams in [(1.2, 0.3, 1.570796), (1.0, 0.2, 0.0)]: basisKernelFunction = afwMath.GaussianFunction2D(*basisKernelParams) basisKernel = afwMath.AnalyticKernel(kWidth, kHeight, basisKernelFunction) basisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(basisImage, True) basisImArrList.append(basisImage.getArray()) basisKernelList.append(basisKernel) kParams = [0.0]*len(basisKernelList) kernel = afwMath.LinearCombinationKernel(basisKernelList, kParams) self.assert_(not kernel.isDeltaFunctionBasis()) self.basicTests(kernel, len(kParams)) # make sure the linear combination kernel has private copies of its basis kernels # by altering the local basis kernels and making sure the new images do NOT match modBasisImArrList = [] for basisKernel in basisKernelList: basisKernel.setKernelParameters((0.4, 0.5, 0.6)) modBasisImage = afwImage.ImageD(basisKernel.getDimensions()) basisKernel.computeImage(modBasisImage, True) modBasisImArrList.append(modBasisImage.getArray()) for ii in range(len(basisKernelList)): kParams = [0.0]*len(basisKernelList) kParams[ii] = 1.0 kernel.setKernelParameters(kParams) kIm = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kIm, True) kImArr = kIm.getArray() if not numpy.allclose(kImArr, basisImArrList[ii]): self.fail("%s = %s != %s for the %s'th basis kernel" % \ (kernel.__class__.__name__, kImArr, basisImArrList[ii], ii)) if numpy.allclose(kImArr, modBasisImArrList[ii]): self.fail("%s = %s == %s for *modified* %s'th basis kernel" % \ (kernel.__class__.__name__, kImArr, modBasisImArrList[ii], ii)) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) self.verifyCache(kernel, hasCache=False) def testSeparableKernel(self): """Test SeparableKernel using a Gaussian function """ kWidth = 5 kHeight = 8 gaussFunc1 = afwMath.GaussianFunction1D(1.0) kernel = afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1) self.basicTests(kernel, 2) fArr = numpy.zeros(shape=[kernel.getWidth(), kernel.getHeight()], dtype=float) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) for xsigma in (0.1, 1.0, 3.0): gaussFunc1.setParameters((xsigma,)) for ysigma in (0.1, 1.0, 3.0): gaussFunc.setParameters((xsigma, ysigma, 0.0)) # compute array of function values and normalize for row in range(kernel.getHeight()): y = row - kernel.getCtrY() for col in range(kernel.getWidth()): x = col - kernel.getCtrX() fArr[col, row] = gaussFunc(x, y) fArr /= fArr.sum() kernel.setKernelParameters((xsigma, ysigma)) kImage = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kImage, True) kArr = kImage.getArray().transpose() if not numpy.allclose(fArr, kArr): self.fail("%s = %s != %s for xsigma=%s, ysigma=%s" % \ (kernel.__class__.__name__, kArr, fArr, xsigma, ysigma)) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) kernel.setKernelParameters((1.2, 0.6)) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail("Clone was modified by changing original's kernel parameters") self.verifyCache(kernel, hasCache=True) def testMakeBadKernels(self): """Attempt to make various invalid kernels; make sure the constructor shows an exception """ kWidth = 4 kHeight = 3 gaussFunc1 = afwMath.GaussianFunction1D(1.0) gaussFunc2 = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) spFunc = afwMath.PolynomialFunction2D(1) kernelList = afwMath.KernelList() kernelList.append(afwMath.FixedKernel(afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight), 0.1))) kernelList.append(afwMath.FixedKernel(afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight), 0.2))) for numKernelParams in (2, 4): spFuncList = afwMath.Function2DList() for ii in range(numKernelParams): spFuncList.append(spFunc.clone()) try: afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc2, spFuncList) self.fail("Should have failed with wrong # of spatial functions")
    407 cfac7626 - except pexExcept.LsstCppException:
    ? -------
    407 6fc1c3d1 + except pexExcept.Exception:
    pass for numKernelParams in (1, 3): spFuncList = afwMath.Function2DList() for ii in range(numKernelParams): spFuncList.append(spFunc.clone()) try: afwMath.LinearCombinationKernel(kernelList, spFuncList) self.fail("Should have failed with wrong # of spatial functions")
    417 cfac7626 - except pexExcept.LsstCppException:
    ? -------
    417 6fc1c3d1 + except pexExcept.Exception:
    pass kParamList = [0.2]*numKernelParams try: afwMath.LinearCombinationKernel(kernelList, kParamList) self.fail("Should have failed with wrong # of kernel parameters")
    423 cfac7626 - except pexExcept.LsstCppException:
    ? -------
    423 6fc1c3d1 + except pexExcept.Exception:
    pass try: afwMath.SeparableKernel(kWidth, kHeight, gaussFunc1, gaussFunc1, spFuncList) self.fail("Should have failed with wrong # of spatial functions")
    428 cfac7626 - except pexExcept.LsstCppException:
    ? -------
    428 6fc1c3d1 + except pexExcept.Exception:
    pass for pointX in range(-1, kWidth+2): for pointY in range(-1, kHeight+2): if (0 <= pointX < kWidth) and (0 <= pointY < kHeight): continue try: afwMath.DeltaFunctionKernel(kWidth, kHeight, afwGeom.Point2I(pointX, pointY)) self.fail("Should have failed with point not on kernel")
    438 d7b24982 - except pexExcept.LsstCppException, e:
    ? -------
    438 6fc1c3d1 + except pexExcept.Exception, e:
    pass def testSVAnalyticKernel(self): """Test spatially varying AnalyticKernel using a Gaussian function Just tests cloning. """ kWidth = 5 kHeight = 8 # spatial model spFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (1.0, 1.0, 0.0), (1.0, 0.0, 1.0), (0.5, 0.5, 0.5), ) gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc, spFunc) kernel.setSpatialParameters(sParams) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) newSParams = ( (0.1, 0.2, 0.5), (0.1, 0.5, 0.2), (0.2, 0.3, 0.3), ) kernel.setSpatialParameters(newSParams) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail("Clone was modified by changing original's spatial parameters") # # check that we can construct a FixedKernel from a LinearCombinationKernel # x, y = 100, 200 kernel2 = afwMath.FixedKernel(kernel, afwGeom.PointD(x, y)) self.assertTrue(re.search("AnalyticKernel", kernel.toString())) self.assertFalse(kernel2.isSpatiallyVarying()) self.assertTrue(re.search("FixedKernel", kernel2.toString())) self.assertTrue(kernel.isSpatiallyVarying()) kim = afwImage.ImageD(kernel.getDimensions()) kernel.computeImage(kim, True, x, y) kim2 = afwImage.ImageD(kernel2.getDimensions()) kernel2.computeImage(kim2, True) self.assertTrue(numpy.allclose(kim.getArray(), kim2.getArray())) def testSVLinearCombinationKernelFixed(self): """Test a spatially varying LinearCombinationKernel """ kWidth = 3 kHeight = 2 # create image arrays for the basis kernels basisImArrList = [] imArr = numpy.zeros((kWidth, kHeight), dtype=float) imArr += 0.1 imArr[kWidth//2, :] = 0.9 basisImArrList.append(imArr) imArr = numpy.zeros((kWidth, kHeight), dtype=float) imArr += 0.2 imArr[:, kHeight//2] = 0.8 basisImArrList.append(imArr) # create a list of basis kernels from the images basisKernelList = afwMath.KernelList() for basisImArr in basisImArrList: basisImage = afwImage.makeImageFromArray(basisImArr.transpose().copy()) kernel = afwMath.FixedKernel(basisImage) basisKernelList.append(kernel) # create spatially varying linear combination kernel spFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (0.0, 1.0, 0.0), (0.0, 0.0, 1.0), ) kernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) self.assert_(not kernel.isDeltaFunctionBasis()) self.basicTests(kernel, 2, 3) kernel.setSpatialParameters(sParams) kImage = afwImage.ImageD(afwGeom.Extent2I(kWidth, kHeight)) for colPos, rowPos, coeff0, coeff1 in [ (0.0, 0.0, 0.0, 0.0), (1.0, 0.0, 1.0, 0.0), (0.0, 1.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0), (0.5, 0.5, 0.5, 0.5), ]: kernel.computeImage(kImage, False, colPos, rowPos) kImArr = kImage.getArray().transpose() refKImArr = (basisImArrList[0] * coeff0) + (basisImArrList[1] * coeff1) if not numpy.allclose(kImArr, refKImArr): self.fail("%s = %s != %s at colPos=%s, rowPos=%s" % \ (kernel.__class__.__name__, kImArr, refKImArr, colPos, rowPos)) sParams = ( (0.1, 1.0, 0.0), (0.1, 0.0, 1.0), ) kernel.setSpatialParameters(sParams) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) newSParams = ( (0.1, 0.2, 0.5), (0.1, 0.5, 0.2), ) kernel.setSpatialParameters(newSParams) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail("Clone was modified by changing original's spatial parameters") def testSVSeparableKernel(self): """Test spatially varying SeparableKernel using a Gaussian function Just tests cloning. """ kWidth = 5 kHeight = 8 # spatial model spFunc = afwMath.PolynomialFunction2D(1) # spatial parameters are a list of entries, one per kernel parameter; # each entry is a list of spatial parameters sParams = ( (1.0, 1.0, 0.0), (1.0, 0.0, 1.0), ) gaussFunc = afwMath.GaussianFunction1D(1.0) kernel = afwMath.SeparableKernel(kWidth, kHeight, gaussFunc, gaussFunc, spFunc) kernel.setSpatialParameters(sParams) kernelClone = kernel.clone() errStr = self.compareKernels(kernel, kernelClone) if errStr: self.fail(errStr) newSParams = ( (0.1, 0.2, 0.5), (0.1, 0.5, 0.2), ) kernel.setSpatialParameters(newSParams) errStr = self.compareKernels(kernel, kernelClone) if not errStr: self.fail("Clone was modified by changing original's spatial parameters") def testSetCtr(self): """Test setCtrCol/Row""" kWidth = 3 kHeight = 4 gaussFunc = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) kernel = afwMath.AnalyticKernel(kWidth, kHeight, gaussFunc) for xCtr in range(kWidth): kernel.setCtrX(xCtr) for yCtr in range(kHeight): kernel.setCtrY(yCtr) self.assertEqual(kernel.getCtrX(), xCtr) self.assertEqual(kernel.getCtrY(), yCtr) def testZeroSizeKernel(self): """Creating a kernel with width or height < 1 should raise an exception. Note: this ignores the default constructors, which produce kernels with height = width = 0. The default constructors are only intended to support persistence, not to produce useful kernels. """ emptyImage = afwImage.ImageF(afwGeom.Extent2I(0, 0)) gaussFunc2D = afwMath.GaussianFunction2D(1.0, 1.0, 0.0) gaussFunc1D = afwMath.GaussianFunction1D(1.0) zeroPoint = afwGeom.Point2I(0, 0) for kWidth in (-1, 0, 1): for kHeight in (-1, 0, 1): if (kHeight > 0) and (kWidth > 0): continue if (kHeight >= 0) and (kWidth >= 0): # don't try to create an image with negative dimensions blankImage = afwImage.ImageF(afwGeom.Extent2I(kWidth, kHeight)) self.assertRaises(Exception, afwMath.FixedKernel, blankImage) self.assertRaises(Exception, afwMath.AnalyticKernel, kWidth, kHeight, gaussFunc2D) self.assertRaises(Exception, afwMath.SeparableKernel, kWidth, kHeight, gaussFunc1D, gaussFunc1D) self.assertRaises(Exception, afwMath.DeltaFunctionKernel, kWidth, kHeight, zeroPoint) def testRefactorDeltaLinearCombinationKernel(self): """Test LinearCombinationKernel.refactor with delta function basis kernels """ kWidth = 4 kHeight = 3 for spOrder in (0, 1, 2): spFunc = afwMath.PolynomialFunction2D(spOrder) numSpParams = spFunc.getNParameters() basisKernelList = makeDeltaFunctionKernelList(kWidth, kHeight) kernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc) numBasisKernels = kernel.getNKernelParameters() maxVal = 1.01 + ((numSpParams - 1) * 0.1) sParamList = [numpy.arange(kInd + 1.0, kInd + maxVal, 0.1) for kInd in range(numBasisKernels)] kernel.setSpatialParameters(sParamList) refKernel = kernel.refactor() self.assert_(refKernel) errStr = self.compareKernels(kernel, refKernel, compareParams=False) if errStr: self.fail("failed with %s for spOrder=%s (numSpCoeff=%s)" % (errStr, spOrder, numSpParams)) def testRefactorGaussianLinearCombinationKernel(self): """Test LinearCombinationKernel.refactor with Gaussian basis kernels """ kWidth = 4 kHeight = 3 for spOrder in (0, 1, 2): spFunc = afwMath.PolynomialFunction2D(spOrder) numSpParams = spFunc.getNParameters() gaussParamsList = [ (1.5, 1.5, 0.0), (2.5, 1.5, 0.0), (2.5, 1.5, math.pi / 2.0), ] gaussBasisKernelList = makeGaussianKernelList(kWidth, kHeight, gaussParamsList) kernel = afwMath.LinearCombinationKernel(gaussBasisKernelList, spFunc) numBasisKernels = kernel.getNKernelParameters() maxVal = 1.01 + ((numSpParams - 1) * 0.1) sParamList = [numpy.arange(kInd + 1.0, kInd + maxVal, 0.1) for kInd in range(numBasisKernels)] kernel.setSpatialParameters(sParamList) refKernel = kernel.refactor() self.assert_(refKernel) errStr = self.compareKernels(kernel, refKernel, compareParams=False) if errStr: self.fail("failed with %s for spOrder=%s; numSpCoeff=%s" % (errStr, spOrder, numSpParams)) def basicTests(self, kernel, nKernelParams, nSpatialParams=0, dimMustMatch=True): """Basic tests of a kernel""" self.assert_(kernel.getNSpatialParameters() == nSpatialParams) self.assert_(kernel.getNKernelParameters() == nKernelParams) if nSpatialParams == 0: self.assert_(not kernel.isSpatiallyVarying()) for ii in range(nKernelParams+5):
    704 92d5dbf6 - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    704 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ kernel.getSpatialFunction, ii) else: self.assert_(kernel.isSpatiallyVarying()) for ii in range(nKernelParams): kernel.getSpatialFunction(ii) for ii in range(nKernelParams, nKernelParams+5):
    711 92d5dbf6 - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    711 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ kernel.getSpatialFunction, ii) for nsp in range(nSpatialParams + 2): spatialParamsForOneKernel = (1.0,)*nsp for nkp in range(nKernelParams + 2): spatialParams = (spatialParamsForOneKernel,)*nkp if ((nkp == nKernelParams) and ((nsp == nSpatialParams) or (nkp == 0))): kernel.setSpatialParameters(spatialParams) self.assert_(numpy.alltrue(numpy.equal(kernel.getSpatialParameters(), spatialParams))) else:
    721 13d4bf8b - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    721 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ kernel.setSpatialParameters, spatialParams) kernelDim = kernel.getDimensions() kernelCtr = kernel.getCtr() for dx in (-1, 0, 1): xDim = kernelDim.getX() + dx for dy in (-1, 0, 1): if dx == dy == 0: continue yDim = kernelDim.getY() + dy image = afwImage.ImageD(xDim, yDim) if (dx == dy == 0) or not dimMustMatch: ksum = kernel.computeImage(image, True) self.assertAlmostEqual(ksum, 1.0)
    736 92570c02 - llBorder = (image.getDimensions() - kernelDim) / 2
    736 4567a4cd + llBorder = ((image.getDimensions() - kernelDim) / 2).truncate()
    ? + ++++++++++++
    737 92570c02 - predCtr = afwGeom.Point2I(afwGeom.Extent2I(llBorder + kernelCtr))
    ? ----------------- -
    737 4567a4cd + predCtr = afwGeom.Point2I(llBorder + kernelCtr)
    self.assertEqual(kernel.getCtr(), predCtr) else: self.assertRaises(Exception, kernel.computeImage, image, True) def basicTestComputeImageRaise(self, kernel, doRaise, kernelDescr=""): """Test that computeImage either does or does not raise an exception, as appropriate """ kImage = afwImage.ImageD(kernel.getDimensions()) try: kernel.computeImage(kImage, True) if doRaise: self.fail(kernelDescr + ".computeImage should have raised an exception")
    750 b79a02a2 - except pexExcept.LsstCppException, e:
    ? -------
    750 6fc1c3d1 + except pexExcept.Exception, e:
    if not doRaise: self.fail(kernelDescr + ".computeImage should not have raised an exception") def compareKernels(self, kernel1, kernel2, compareParams=True, newCtr1=(0, 0)): """Compare two kernels; return None if they match, else return a string kernelDescribing a difference. kernel1: one kernel to test kernel2: the other kernel to test compareParams: compare spatial parameters and kernel parameters if they exist newCtr: if not None then set the center of kernel1 and see if it changes the center of kernel2 """ retStrs = [] if kernel1.getDimensions() != kernel2.getDimensions(): retStrs.append("dimensions differ: %s != %s" % (kernel1.getDimensions(), kernel2.getDimensions())) ctr1 = kernel1.getCtrX(), kernel1.getCtrY() ctr2 = kernel2.getCtrX(), kernel2.getCtrY() if ctr1 != ctr2: retStrs.append("centers differ: %s != %s" % (ctr1, ctr2)) if kernel1.isSpatiallyVarying() != kernel2.isSpatiallyVarying(): retStrs.append("isSpatiallyVarying differs: %s != %s" % \ (kernel1.isSpatiallyVarying(), kernel2.isSpatiallyVarying())) if compareParams: if kernel1.getSpatialParameters() != kernel2.getSpatialParameters(): retStrs.append("spatial parameters differ: %s != %s" % \ (kernel1.getSpatialParameters(), kernel2.getSpatialParameters())) if kernel1.getNSpatialParameters() != kernel2.getNSpatialParameters(): retStrs.append("# spatial parameters differs: %s != %s" % \ (kernel1.getNSpatialParameters(), kernel2.getNSpatialParameters())) if not kernel1.isSpatiallyVarying() and hasattr(kernel1, "getKernelParameters"): if kernel1.getKernelParameters() != kernel2.getKernelParameters(): retStrs.append("kernel parameters differs: %s != %s" % \ (kernel1.getKernelParameters(), kernel2.getKernelParameters())) if retStrs: return "; ".join(retStrs) im1 = afwImage.ImageD(kernel1.getDimensions()) im2 = afwImage.ImageD(kernel2.getDimensions()) if kernel1.isSpatiallyVarying(): posList = [(0, 0), (200, 0), (0, 200), (200, 200)] else: posList = [(0, 0)] for doNormalize in (False, True): for pos in posList: kernel1.computeImage(im1, doNormalize, pos[0], pos[1]) kernel2.computeImage(im2, doNormalize, pos[0], pos[1]) im1Arr = im1.getArray() im2Arr = im2.getArray() if not numpy.allclose(im1Arr, im2Arr): print "im1Arr =", im1Arr print "im2Arr =", im2Arr return "kernel images do not match at %s with doNormalize=%s" % (pos, doNormalize) if newCtr1 != None: kernel1.setCtrX(newCtr1[0]) kernel1.setCtrY(newCtr1[1]) newCtr2 = kernel2.getCtrX(), kernel2.getCtrY() if ctr2 != newCtr2: return "changing center of kernel1 to %s changed the center of kernel2 from %s to %s" % \ (newCtr1, ctr2, newCtr2) def testCast(self): instances = [] kVec = makeGaussianKernelList(9, 9, [(2.0, 2.0, 0.0)]) kParams = [0.0]*len(kVec) instances.append(afwMath.LinearCombinationKernel(kVec, kParams)) instances.append(afwMath.AnalyticKernel(7, 7, afwMath.GaussianFunction2D(2.0, 2.0, 0.0))) instances.append(afwMath.DeltaFunctionKernel(5, 5, afwGeom.Point2I(1, 1))) instances.append(afwMath.FixedKernel(afwImage.ImageD(afwGeom.Extent2I(7, 7)))) instances.append(afwMath.SeparableKernel(3, 3, afwMath.PolynomialFunction1D(0), afwMath.PolynomialFunction1D(0))) for instance in instances: Class = type(instance) base = instance.clone() self.assertEqual(type(base), afwMath.Kernel) derived = Class.cast(base) self.assertEqual(type(derived), Class) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(KernelTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(doExit=False): """Run the tests""" utilsTests.run(suite(), doExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b79a02a2

    commit b79a02a2c6c1b70fadfb74623e481172a3376579
    Author: rowen 
    Date:   Mon Nov 23 21:16:07 2009 +0000
    
        Implemented ticket #992:
        - Kernel.computeImage now raises lsst::pex::except::InvalidParameterException
          if doNormalize true and kernel sum 0.
        - SeparableKernel.computeVectors and basicComputeVectors do the same.
        - Added unit tests for the above.
        - Fixed typos in tests/Statistics.py so all tests pass again.
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    b10ab54c

    commit b10ab54c802578e3cc4158bc33aa212a5cba5bc4
    Author: rallsman 
    Date:   Sun Apr 6 01:43:41 2008 +0000
    
        Mostly replacing the files which were inexplicably zero length on last commit.
    

    d7b24982

    commit d7b24982db8562dc77c4bcc33c84107c65fd686d
    Author: rowen 
    Date:   Thu Oct 29 00:15:47 2009 +0000
    
        Fixed ticket #1000 by adding a missing test to a LinearCombinationKernel constructor.
        Updated tests/Kernel.cc as suggested by Serge so it would not trigger the problem.
        Updated many exceptions in kernel constructors to print more details.
        Added unit tests for the exceptions in kernel methods.
        
        Note: the current code has a swig warning about a shadowed constructor in LinearCombinationKernel.
        This should be resolved before committing the changes to the trunk. See my email to lsst-data.
    

    92d5dbf6

    commit 92d5dbf60dae26fd6f52314abbd982c835df331b
    Author: rowen 
    Date:   Thu Feb 26 01:18:56 2009 +0000
    
        Fixed a bug in setSpatialParams: if the kernel was spatially invariant
        then this function would crash (abort in python) if passed an empty vector of the right shape.
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    cfac7626

    commit cfac7626af85c24d5061a0dad7c59003c8b6f796
    Author: rowen 
    Date:   Tue Nov 3 22:04:46 2009 +0000
    
        Fixed various bugs found by pylint.
    

    13d4bf8b

    commit 13d4bf8b8b433de4d867184bbe5743968e254987
    Author: rowen 
    Date:   Thu Feb 26 01:19:48 2009 +0000
    
        Reapplied the real code in one test.
    

    92570c02

    commit 92570c02a059d1547b68e84d8a7326f68938b71b
    Author: Russell Owen 
    Date:   Tue May 7 10:23:10 2013 -0700
    
        Implement ticket #2620: computeImage should set xy0.
        Removed the ability to pass a smaller image to LinearCombinationKernel::computeImage.
        AnalyticKernel::computeImage can still be called with an image of any dimensions,
        but only on that class; if you try to do this on a pointer or reference to Kernel
        then Kernel::computeImage is called,which rejects images whose dimensions do not match that of Kernel
        (Jim Bosch and I consider this a feature).
        Added a unit test to tests/kernel.py that exercises the dimension checking code.
        Moved some boilerplate code for computeImage into a protected member function doComputeImage
        and made Kernel::computeImage nonvirtual.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    Return to list

    tests/testFitsTables.cc

    Diff:

                    #define BOOST_TEST_DYN_LINK
                    #define BOOST_TEST_MODULE table-fits
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
    
    5 2f75198f + #include "lsst/afw/table/aggregates.h"
    #include "boost/test/unit_test.hpp" #pragma clang diagnostic pop #include #include #include #include #include "boost/filesystem.hpp" #include "lsst/utils/ieee.h" #include "lsst/afw/table/Source.h" struct EqualityCompare { bool operator()( lsst::afw::detection::Span::Ptr const & a, lsst::afw::detection::Span::Ptr const & b ) const { return a->getY() == b->getY() && a->getX0() == b->getX0() && a->getX1() == b->getX1(); } bool operator()(float a, float b) const { return std::fabs(a - b) < 1E-8 || (lsst::utils::isnan(a) && lsst::utils::isnan(b)); } bool operator()( lsst::afw::detection::PeakRecord const & a, lsst::afw::detection::PeakRecord const & b ) const { return (*this)(a.getFx(), b.getFx()) && (*this)(a.getFy(), b.getFy()) && (*this)(a.getPeakValue(), b.getPeakValue()); } }; struct ExtractSchemaStrings { template void operator()(lsst::afw::table::SchemaItem const & item) const { names.push_back(item.field.getName()); docs.push_back(item.field.getDoc()); units.push_back(item.field.getUnits()); } mutable std::vector names; mutable std::vector docs; mutable std::vector units; }; BOOST_AUTO_TEST_CASE(testFits) { using namespace lsst::afw::table; std::string filename = "tests/data/testTable.fits"; Schema schema = SourceTable::makeMinimalSchema();
    64 bd692192 + schema.setVersion(0);
    Key a_b_i = schema.addField("a.b.i", "int"); Key a_b_i_valid = schema.addField("a.b.i.valid", "is field a.b.i valid?"); Key a_c_f = schema.addField("a.c.f", "an extremely long string for documenting this float field that will require use of the FITS long-string convention that splits long values up and puts them on different keys using CONTINUE.", "femtoseamonkeys"); Key e_g_d = schema.addField("e.g.d", "double", "bargles^2"); Key e_g_d_flag1 = schema.addField("e.g.d.flag1", "flag1 for e.g.d"); Key e_g_d_flag2 = schema.addField("e.g.d.flag2", "flag2 for e.g.d"); Key< Point > a_b_p = schema.addField< Point >("a.b.p", "point", "pixels"); Key< std::string > a_s = schema.addField< std::string >("a.s", "string", 5); KeyTuple flux = addFluxFields(schema, "flux", "flux doc"); KeyTuple centroid = addCentroidFields(schema, "centroid", "centroid doc"); SourceCatalog vector(SourceTable::make(schema));
    75 5f0980b1 -
    76 6581586d - vector.getTable()->defineModelFlux(flux.meas, flux.err, flux.flag);
    ? ^^^^^^^^^^^^^^^^^^^^^^^^^^
    77 2f75198f + vector.getTable()->defineModelFlux("flux");
    ? + ^
    77 6581586d - vector.getTable()->defineCentroid(centroid.meas, centroid.err, centroid.flag);
    78 2f75198f + vector.getTable()->defineCentroid("centroid");
    vector.getTable()->setMetadata(boost::make_shared()); vector.getTable()->getMetadata()->add("SHEEP", 7.3, "total number of sheep on the farm"); vector.getTable()->getMetadata()->add("MONKEYS", 155, "monkeys per tree"); { PTR(Footprint) fp1 = boost::make_shared(); fp1->addSpan(0, 5, 8); fp1->addSpan(1, 4, 9); fp1->addSpan(2, 6, 7); fp1->addPeak(4.5f, 1.2f, 25.6f); fp1->addPeak(6.8f, 0.8f, 23.2f); PTR(SourceRecord) r1 = vector.getTable()->makeRecord(); r1->setFootprint(fp1); r1->set(a_b_i, 314); r1->set(a_b_i_valid, true); r1->set(a_c_f, 3.14f); r1->set(e_g_d, 3.14E12); r1->set(e_g_d_flag1, false); r1->set(e_g_d_flag2, true); r1->set(a_b_p, lsst::afw::geom::Point2D(1.2, 0.5)); r1->set(a_s, "foo"); vector.push_back(r1); PTR(SourceRecord) r2 = vector.getTable()->makeRecord(); r2->set(a_b_i, 5123); r2->set(a_b_i_valid, true); r2->set(a_c_f, 44.8f); r2->set(e_g_d, 12.2E-3); r2->set(e_g_d_flag1, true); r2->set(e_g_d_flag2, false); r2->set(a_b_p, lsst::afw::geom::Point2D(-32.1, 63.2)); r2->set(a_s, "bar"); PTR(Footprint) fp2 = boost::make_shared(); fp2->addSpan(3, 2, 7); fp2->addSpan(4, 3, 5); fp2->addPeak(4.2f, 3.3f, 32.1f); r2->setFootprint(fp2); vector.push_back(r2); BOOST_CHECK_EQUAL( r2->get(e_g_d_flag1), true ); BOOST_CHECK_EQUAL( r2->get(e_g_d_flag2), false ); } vector.writeFits(filename); SourceCatalog readVector = SourceCatalog::readFits(filename); BOOST_CHECK_EQUAL( schema, readVector.getSchema() ); // only checks equality of keys BOOST_CHECK_EQUAL( readVector.getTable()->getMetadata()->get("SHEEP"), vector.getTable()->getMetadata()->get("SHEEP") ); BOOST_CHECK_EQUAL( readVector.getTable()->getMetadata()->get("MONKEYS"), vector.getTable()->getMetadata()->get("MONKEYS") ); BOOST_CHECK_EQUAL( readVector.getTable()->getMetadata()->nameCount(), vector.getTable()->getMetadata()->nameCount() ); ExtractSchemaStrings func1; schema.forEach(boost::ref(func1)); ExtractSchemaStrings func2; readVector.getSchema().forEach(boost::ref(func2)); BOOST_CHECK( func1.names == func2.names ); BOOST_CHECK( func1.docs == func2.docs ); BOOST_CHECK( func1.units == func2.units );
    142 5f0980b1 - BOOST_CHECK_EQUAL( vector.getTable()->getModelFluxKey(), readVector.getTable()->getModelFluxKey() );
    ? ------ ^
    143 2f75198f + BOOST_CHECK( vector.getTable()->getModelFluxKey() == readVector.getTable()->getModelFluxKey() );
    ? ^^^
    143 5f0980b1 - BOOST_CHECK_EQUAL( vector.getTable()->getModelFluxErrKey(), readVector.getTable()->getModelFluxErrKey() );
    ? ------ ^
    144 2f75198f + BOOST_CHECK( vector.getTable()->getModelFluxErrKey() == readVector.getTable()->getModelFluxErrKey() );
    ? ^^^
    145 5f0980b1 - BOOST_CHECK_EQUAL( vector.getTable()->getCentroidKey(), readVector.getTable()->getCentroidKey() );
    ? ------ ^
    146 2f75198f + BOOST_CHECK( vector.getTable()->getCentroidKey() == readVector.getTable()->getCentroidKey() );
    ? ^^^
    146 6581586d - BOOST_CHECK_EQUAL( vector.getTable()->getCentroidErrKey(), readVector.getTable()->getCentroidErrKey() );
    ? ------ ^
    147 2f75198f + BOOST_CHECK( vector.getTable()->getCentroidErrKey() == readVector.getTable()->getCentroidErrKey() );
    ? ^^^ { SourceRecord const & a1 = vector[0]; SourceRecord const & b1 = readVector[0]; BOOST_CHECK_EQUAL( a1.get(a_b_i), b1.get(a_b_i) ); BOOST_CHECK_EQUAL( a1.get(a_b_i_valid), b1.get(a_b_i_valid) ); BOOST_CHECK_CLOSE_FRACTION( a1.get(a_c_f), b1.get(a_c_f), 1E-8 ); BOOST_CHECK_CLOSE_FRACTION( a1.get(e_g_d), b1.get(e_g_d), 1E-16 ); BOOST_CHECK_EQUAL( a1.get(e_g_d_flag1), b1.get(e_g_d_flag1) ); BOOST_CHECK_EQUAL( a1.get(e_g_d_flag2), b1.get(e_g_d_flag2) ); BOOST_CHECK_EQUAL( a1.get(a_s), b1.get(a_s) ); BOOST_CHECK_CLOSE_FRACTION( a1.get(a_b_p.getX()), b1.get(a_b_p.getX()), 1E-8 ); BOOST_CHECK_CLOSE_FRACTION( a1.get(a_b_p.getY()), b1.get(a_b_p.getY()), 1E-8 ); Footprint const & fp1a = *a1.getFootprint(); Footprint const & fp1b = *b1.getFootprint(); BOOST_CHECK( std::equal(fp1a.getSpans().begin(), fp1a.getSpans().end(), fp1b.getSpans().begin(), EqualityCompare()) ); BOOST_CHECK( std::equal(fp1a.getPeaks().begin(), fp1a.getPeaks().end(), fp1b.getPeaks().begin(), EqualityCompare()) ); BOOST_CHECK_EQUAL( fp1a.getBBox(), fp1b.getBBox() ); SourceRecord const & a2 = vector[1]; SourceRecord const & b2 = readVector[1]; BOOST_CHECK_EQUAL( a2.get(a_b_i), b2.get(a_b_i) ); BOOST_CHECK_EQUAL( a2.get(a_b_i_valid), b2.get(a_b_i_valid) ); BOOST_CHECK_CLOSE_FRACTION( a2.get(a_c_f), b2.get(a_c_f), 1E-8 ); BOOST_CHECK_CLOSE_FRACTION( a2.get(e_g_d), b2.get(e_g_d), 1E-16 ); BOOST_CHECK_EQUAL( a2.get(e_g_d_flag1), b2.get(e_g_d_flag1) ); BOOST_CHECK_EQUAL( a2.get(e_g_d_flag2), b2.get(e_g_d_flag2) ); BOOST_CHECK_EQUAL( a2.get(a_s), b2.get(a_s) ); BOOST_CHECK_CLOSE_FRACTION( a2.get(a_b_p.getX()), b2.get(a_b_p.getX()), 1E-8 ); BOOST_CHECK_CLOSE_FRACTION( a2.get(a_b_p.getY()), b2.get(a_b_p.getY()), 1E-8 ); Footprint const & fp2a = *a2.getFootprint(); Footprint const & fp2b = *b2.getFootprint(); BOOST_CHECK( std::equal(fp2a.getSpans().begin(), fp2a.getSpans().end(), fp2b.getSpans().begin(), EqualityCompare()) ); BOOST_CHECK( std::equal(fp2a.getPeaks().begin(), fp2a.getPeaks().end(), fp2b.getPeaks().begin(), EqualityCompare()) ); BOOST_CHECK_EQUAL( fp2a.getBBox(), fp2b.getBBox() ); } boost::filesystem::remove(filename); } BOOST_AUTO_TEST_CASE(ticket2164) { using namespace lsst::afw::table; Schema schema; schema.addField("i", "test int field"); schema.addField("d", "test double field"); BaseCatalog cat(schema); cat.addNew(); cat.addNew(); ConstBaseCatalog constCat(cat);
    201 792c66db - BOOST_CHECK_THROW( constCat.getColumnView(), lsst::pex::exceptions::LogicErrorException );
    ? ---------
    202 21597d88 + BOOST_CHECK_THROW( constCat.getColumnView(), lsst::pex::exceptions::LogicError );
    }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    792c66db

    commit 792c66db1bfc223cf318302a65bab6776608f1d4
    Author: Jim Bosch 
    Date:   Tue Sep 4 12:02:31 2012 -0400
    
        Add unit test to verify exception when getting a column view from a const catalog.
    

    6581586d

    commit 6581586d25bea008aadd57a10968ca6c9fb72677
    Author: Jim Bosch 
    Date:   Mon Jan 30 01:09:10 2012 -0500
    
        fixed bug in schema key-based lookups, added flag fields to standard measurements
    

    5f0980b1

    commit 5f0980b13f25349d67fd8c160519ed0fe11450e7
    Author: Jim Bosch 
    Date:   Sun Jan 29 00:12:48 2012 -0500
    
        fixed period-handling bug in table FITS reading, added slot reading/writing in FITS
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    2f75198f

    commit 2f75198fac120aa8d7d376014b1dba1a37922464
    Author: Perry Gee 
    Date:   Tue Jul 22 14:19:12 2014 -0500
    
        Fix quick tests for DM-936 where definition of slots is done with keys.  That is no longer supported.
    

    bd692192

    commit bd692192367d33bb64a79ca008bff10eb9b41932
    Author: pgee 
    Date:   Mon Aug 18 15:06:04 2014 -0700
    
        Move API version number from BaseTable to Schema
        
        In FitsReader, move reading the AFW_TABLE_VERSION header key into the
        Schema-from-metadata constructor.
        In FitsWriter, use the version attached to the table schema to write the
        metadata.
    

    Return to list

    python/lsst/afw/detection/detectionLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define detectionLib_DOCSTRING
                    "
                    Python interface to lsst::afw::detection classes
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.detection", docstring=detectionLib_DOCSTRING) detectionLib
                    
                    // Suppress swig complaints
                    // I had trouble getting %warnfilter to work; hence the pragmas
                    #pragma SWIG nowarn=314                 // print is a python keyword (--> _print)
                    #pragma SWIG nowarn=362                 // operator=  ignored
                    
                    %{
                    #include "lsst/daf/base.h"
                    #include "lsst/pex/logging.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/pex/policy.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/geom/ellipses.h"
                    #include "lsst/afw/cameraGeom.h"
                    #include "lsst/afw/image.h"
                    #include "lsst/afw/math.h"
                    #include "lsst/afw/table.h"
    
    50 6ed18f74 -
    51 17d1d529 - #define PY_ARRAY_UNIQUE_SYMBOL LSST_AFW_DETECTION_NUMPY_ARRAY_API
    52 17d1d529 - #include "numpy/arrayobject.h"
    53 a7ce1e71 - #include "ndarray/swig.h"
    54 a7ce1e71 - #include "ndarray/swig/eigen.h"
    55 17d1d529 - %}
    56 17d1d529 -
    57 17d1d529 - %init %{
    58 17d1d529 - import_array();
    %} %pythoncode %{ import numpy # used by some afw.table stuff we invoked here, but not included by %import %} %include "std_string.i" %include "lsst/p_lsstSwig.i"
    59 853c5734 +
    60 853c5734 + %initializeNumPy(afw_detection)
    61 853c5734 + %{
    62 853c5734 + #include "ndarray/swig.h"
    63 853c5734 + #include "ndarray/swig/eigen.h"
    64 853c5734 + %}
    65 853c5734 + %include "ndarray.i"
    66 853c5734 +
    %include "lsst/base.h" %import "lsst/afw/utils.i" %include "lsst/daf/base/persistenceMacros.i" %import "lsst/afw/image/imageLib.i" %import "lsst/afw/geom/geomLib.i" %import "lsst/afw/geom/ellipses/ellipsesLib.i" %import "lsst/afw/math/mathLib.i" %import "lsst/afw/table/tableLib.i" %include "ndarray.i" %lsst_exceptions() %include "Peak.i" %include "footprints.i" %include "psf.i" %include "footprintset.i" %pythoncode %{ from lsst.afw.geom import Span %} %include "GaussianPsf.i"

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6ed18f74

    commit 6ed18f74b67c84fc2d7454c494008656d9896608
    Author: Jim Bosch 
    Date:   Sun Apr 7 11:35:29 2013 -0400
    
        If detectionLib.i is going to %import mathLib.i, it better #include afw/math.h.
    

    a7ce1e71

    commit a7ce1e71d391ee1b194eabea9cead705bd9858da
    Author: Jim Bosch 
    Date:   Mon Mar 19 16:09:24 2012 -0400
    
        moved ndarray out of lsst namespace and header directories
    

    17d1d529

    commit 17d1d529ed63e98f98e5d1a7a7da4811e95fc26c
    Author: dubcovsky 
    Date:   Tue Feb 15 00:00:43 2011 +0000
    
        #1556 Split Footprint.h into Threshold.h, FootprintSet.h, and FootprintFunctor.h, to correspond with class names. Added a constructors to Footprint which use geom objects (BoxI and Ellipse) to construct footprints. Footprints now exclusively use geom::PointI and geom::BoxI internally. (but still accept image::PointI and image::BBox for backwards compatibility wherever possible). FootprintArray.h contains a static functions to flatten and expand ndarrays using a Footprint to map between 2-d and 1-d indices.
    

    Commits in /Users/nate/repos_lsst/afw/

    853c5734

    commit 853c5734ee13f55fd35e9e18ed5ac69a0073b97f
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:18:28 2015 -0400
    
        Utilize new numeric scalar typemaps and NumPy import macro.
    

    Return to list

    src/table/BaseColumnView.cc

    Diff:

                    #include "boost/preprocessor/seq/for_each.hpp"
                    #include "boost/preprocessor/tuple/to_seq.hpp"
                    
                    #include "lsst/afw/table/BaseColumnView.h"
                    #include "lsst/afw/table/detail/Access.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    // =============== BitsColumn implementation ================================================================
                    
                    namespace {
                    
                    struct MatchKey {
                        bool operator()(SchemaItem const & item) const { 
                            return item.key == target;
                        }
                    
                        explicit MatchKey(Key const & t) : target(t) {}
                    
                        Key const & target;
                    };
                    
                    struct MatchName {
                        bool operator()(SchemaItem const & item) const { 
                            return item.field.getName() == target;
                        }
                    
                        explicit MatchName(std::string const & t) : target(t) {}
                    
                        std::string const & target;
                    };
                    
                    } // namespace
                    
                    BitsColumn::IntT BitsColumn::getBit(Key const & key) const {
                        IntT r = std::find_if(_items.begin(), _items.end(), MatchKey(key)) - _items.begin();
                        if (std::size_t(r) == _items.size()) {
                            throw LSST_EXCEPT(
    
    39 ecd0c5af - pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    39 21597d88 + pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("'%s' not found in BitsColumn") % key).str() ); } return r; } BitsColumn::IntT BitsColumn::getBit(std::string const & name) const { IntT r = std::find_if(_items.begin(), _items.end(), MatchName(name)) - _items.begin(); if (std::size_t(r) == _items.size()) { throw LSST_EXCEPT(
    50 ecd0c5af - pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    50 21597d88 + pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("'%s' not found in BitsColumn") % name).str() ); } return r; } BitsColumn::BitsColumn(int size) : _array(ndarray::allocate(size)) { _array.deep() = IntT(0); } // =============== BaseColumnView private Impl object ======================================================= struct BaseColumnView::Impl { int recordCount; // number of records void * buf; // pointer to the beginning of the first record's data PTR(BaseTable) table; // table that owns the records ndarray::Manager::Ptr manager; // manages lifetime of 'buf' Impl(PTR(BaseTable) const & table_, int recordCount_, void * buf_, ndarray::Manager::Ptr const & manager_) : recordCount(recordCount_), buf(buf_), table(table_), manager(manager_) {} }; // =============== BaseColumnView member function implementations =========================================== PTR(BaseTable) BaseColumnView::getTable() const { return _impl->table; } template typename ndarray::ArrayRef const BaseColumnView::operator[](Key const & key) const { return ndarray::external( reinterpret_cast( reinterpret_cast(_impl->buf) + key.getOffset() ), ndarray::makeVector(_impl->recordCount), ndarray::makeVector(int(_impl->table->getSchema().getRecordSize() / sizeof(T))), _impl->manager ); } template typename ndarray::ArrayRef const BaseColumnView::operator[](Key< Array > const & key) const { if (key.isVariableLength()) { throw LSST_EXCEPT(
    95 0b745ec6 - pex::exceptions::LogicErrorException,
    ? ---------
    95 2d6be90c + pex::exceptions::LogicError,
    "Cannot get columns for variable-length array fields" ); } return ndarray::external( reinterpret_cast( reinterpret_cast(_impl->buf) + key.getOffset() ), ndarray::makeVector(_impl->recordCount, key.getSize()), ndarray::makeVector(int(_impl->table->getSchema().getRecordSize() / sizeof(T)), 1), _impl->manager ); } ndarray::result_of::vectorize< detail::FlagExtractor, ndarray::Array< Field::Element const,1> >::type BaseColumnView::operator[](Key const & key) const { return ndarray::vectorize( detail::FlagExtractor(key), ndarray::Array::Element const,1>( ndarray::external( reinterpret_cast::Element *>( reinterpret_cast(_impl->buf) + key.getOffset() ), ndarray::makeVector(_impl->recordCount), ndarray::makeVector(int(_impl->table->getSchema().getRecordSize() / sizeof(Field::Element))), _impl->manager ) ) ); } BitsColumn BaseColumnView::getBits(std::vector< Key > const & keys) const { BitsColumn result(_impl->recordCount); ndarray::ArrayRef array = result._array.deep(); if (keys.size() > sizeof(BitsColumn::IntT)) { throw LSST_EXCEPT(
    132 ecd0c5af - pex::exceptions::LengthErrorException,
    ? ---------
    132 21597d88 + pex::exceptions::LengthError,
    (boost::format("Too many keys passed to getBits(); %d > %d.") % keys.size() % sizeof(BitsColumn::IntT)).str() ); } BitsColumn::IntT const size = keys.size(); // just for unsigned/signed comparisons for (BitsColumn::IntT i = 0; i < size; ++i) { array |= (BitsColumn::IntT(1) << i) * (*this)[keys[i]]; result._items.push_back(getSchema().find(keys[i])); } return result; } namespace { struct ExtractFlagItems { template void operator()(SchemaItem const &) const {} void operator()(SchemaItem const & item) const { items->push_back(item); } std::vector< SchemaItem > * items; }; } // anonymous BitsColumn BaseColumnView::getAllBits() const { BitsColumn result(_impl->recordCount); ExtractFlagItems func = { &result._items }; getSchema().forEach(func); if (result._items.size() > sizeof(BitsColumn::IntT)) { throw LSST_EXCEPT(
    167 ecd0c5af - pex::exceptions::LengthErrorException,
    ? ---------
    167 21597d88 + pex::exceptions::LengthError,
    (boost::format("Too many Flag keys in schema; %d > %d.") % result._items.size() % sizeof(BitsColumn::IntT)).str() ); } ndarray::ArrayRef array = result._array.deep(); BitsColumn::IntT const size = result._items.size(); // just for unsigned/signed comparisons for (BitsColumn::IntT i = 0; i < size; ++i) { array |= (BitsColumn::IntT(1) << i) * (*this)[result._items[i].key]; } return result; } // needs to be in source file so it can (implicitly) call Impl's (implicit) dtor BaseColumnView::~BaseColumnView() {} BaseColumnView::BaseColumnView( PTR(BaseTable) const & table, int recordCount, void * buf, ndarray::Manager::Ptr const & manager ) : _impl(boost::make_shared(table, recordCount, buf, manager)) {} // =============== Explicit instantiations ================================================================== #define INSTANTIATE_COLUMNVIEW_SCALAR(r, data, elem) \ template ndarray::ArrayRef< elem, 1> const BaseColumnView::operator[](Key< elem > const &) const; BOOST_PP_SEQ_FOR_EACH( INSTANTIATE_COLUMNVIEW_SCALAR, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_SCALAR_FIELD_TYPE_N, AFW_TABLE_SCALAR_FIELD_TYPE_TUPLE) ) #define INSTANTIATE_COLUMNVIEW_ARRAY(r, data, elem) \ template ndarray::ArrayRef< elem, 2, 1 > const BaseColumnView::operator[](Key< Array< elem > > const &) const; BOOST_PP_SEQ_FOR_EACH( INSTANTIATE_COLUMNVIEW_ARRAY, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_ARRAY_FIELD_TYPE_N, AFW_TABLE_ARRAY_FIELD_TYPE_TUPLE) ) }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ecd0c5af

    commit ecd0c5af7cb5b6b33e0d963d6e12d711d4bed447
    Author: Jim Bosch 
    Date:   Tue Mar 13 20:31:29 2012 -0400
    
        added packed bit flag arrays to column views
    

    0b745ec6

    commit 0b745ec681de903b911691c49f07f3ebc52c692f
    Author: Jim Bosch 
    Date:   Mon Dec 1 13:46:03 2014 -0500
    
        Add variable-length array fields to afw::table
        
        We use Array with a size of zero to indicate variable-length fields.
        It'd probably be better to use a completely different tag type, but
        Boost.Variant puts an upper limit on how many tags we have, so until
        we rewrite afw::table to avoid it, we need to limit how many we use.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    2d6be90c

    commit 2d6be90c6e14ab8fa2803a84a45106345037f1f5
    Author: Lauren MacArthur 
    Date:   Thu Apr 2 13:50:52 2015 -0400
    
        Remove trailing Exception in exception names
    

    Return to list

    src/math/Spline.cc

    Diff:

                    /**
                     * \brief A number of non-trivial splines
                     *
                     * \note These should be merged into lsst::afw::math::Interpolate, but its current implementation
                     * (and to some degree interface) uses gsl explicitly
                     */
                    #include 
                    
                    #include "boost/format.hpp"
                    #include "lsst/pex/exceptions/Runtime.h"
                    #include "lsst/afw/math/detail/Spline.h"
                    #include "lsst/afw/geom/Angle.h"
                    
                    namespace afwGeom = lsst::afw::geom;
                    
                    namespace lsst { namespace afw { namespace math { namespace detail {
                    
                                    static int search_array(double z, double const *x, int n, int i);
                    
                    /*****************************************************************************/
                    /*
                     * Allocate the storage a Spline needs
                     */
                    void
                    Spline::_allocateSpline(int const nknot)
                    {
                        _knots.resize(nknot);
                        _coeffs.resize(4);
                        for (unsigned int i = 0; i != _coeffs.size(); ++i) {
                            _coeffs[i].reserve(nknot);
                        }
                    }
                                    
                    /**
                     * Interpolate a Spline.
                     */
                    void
                    Spline::interpolate(std::vector const& x, ///< points to interpolate at
                                        std::vector & y       ///< values of spline interpolation
                                       ) const
                    {
                        int const nknot = _knots.size();
                        int const n = x.size();
                    
                        y.resize(n);                         // may default-construct elements which is a little inefficient
                        /*
                         * For _knots[i] <= x <= _knots[i+1], the interpolant
                         * has the form
                         *    val = _coeff[0][i] +dx*(_coeff[1][i] + dx*(_coeff[2][i]/2 + dx*_coeff[3][i]/6))
                         * with
                         *    dx = x - knots[i]
                         */
                        int ind = -1;                        // no idea initially
                        for (int i = 0; i != n; ++i) {
                            ind = search_array(x[i], &_knots[0], nknot, ind);
                    
                            if(ind < 0) {           // off bottom
                                ind = 0;
                            } else if(ind >= nknot) {       // off top
                                ind = nknot - 1;
                            }
                    
                            double const dx = x[i] - _knots[ind];
                            y[i] = _coeffs[0][ind] + dx*(_coeffs[1][ind] + dx*(_coeffs[2][ind]/2 + dx*_coeffs[3][ind]/6));
                        }
                    }
                    
                    /*****************************************************************************/
                    /**
                     * Find the derivative of a Spline.
                     */
                    void
                    Spline::derivative(std::vector const& x, ///< points to evaluate derivative at
                                       std::vector &dydx     ///< derivatives at x
                                      ) const
                    {
                        int const nknot = _knots.size();
                        int const n = x.size();
                    
                        dydx.resize(n);                      // may default-construct elements which is a little inefficient
                        /*
                         * For _knots[i] <= x <= _knots[i+1], the * interpolant has the form
                         *    val = _coeff[0][i] +dx*(_coeff[1][i] + dx*(_coeff[2][i]/2 + dx*_coeff[3][i]/6))
                         * with
                         *    dx = x - knots[i]
                         * so the derivative is
                         *    val = _coeff[1][i] + dx*(_coeff[2][i] + dx*_coeff[3][i]/2))
                         */
                       
                        int ind = -1;                        // no idea initially
                        for (int i = 0; i != n; ++i) {
                            ind = search_array(x[i], &_knots[0], nknot, ind);
                           
                            if(ind < 0) {           // off bottom
                                ind = 0;
                            } else if(ind >= nknot) {       // off top
                                ind = nknot - 1;
                            }
                           
                            double const dx = x[i] - _knots[ind];
                            dydx[i] = _coeffs[1][ind] + dx*(_coeffs[2][ind] + dx*_coeffs[3][ind]/2);
                        }
                    }
                                    
                    /*****************************************************************************/
                    /**
                     * Adapted from
                     *      A Practical Guide to Splines
                     * by
                     *      C. de Boor (N.Y. : Springer-Verlag, 1978)
                     * (His routine tautsp converted to C by Robert Lupton and then to C++ by an older and grayer Robert Lupton)
                     *
                     * Construct cubic spline interpolant to given data.
                     *
                     * If gamma .gt. 0., additional knots are introduced where needed to
                     * make the interpolant more flexible locally. this avoids extraneous
                     * inflection points typical of cubic spline interpolation at knots to
                     * rapidly changing data. Values for gamma are:
                     *
                     *          = 0., no additional knots
                     *          in (0.,3.), under certain conditions on the given data at
                     *                points i-1, i, i+1, and i+2, a knot is added in the
                     *                i-th interval, i=1,...,ntau-3. see description of method
                     *                below. the interpolant gets rounded with increasing
                     *                gamma. a value of  2.5  for gamma is typical.
                     *          in (3.,6.), same , except that knots might also be added in
                     *                intervals in which an inflection point would be permitted.
                     *                a value of  5.5  for gamma is typical.
                     *
                     * Returns:
                     *          a SPLINE giving knots and coefficients, if all was OK
                     *          NULL otherwise (and pushes message on error stack)
                     *
                     *  ------  m e t h o d  ------
                     *  on the i-th interval, (tau[i], tau[i+1]), the interpolant is of the
                     *  form
                     *  (*)  f(u(x)) = a + b*u + c*h(u,z) + d*h(1-u,1-z) ,
                     *  with u = u(x) = (x - tau[i])/dtau[i].  Here,
                     *       z = z(i) = addg(i+1)/(addg(i) + addg(i+1))
                     *  (= .5, in case the denominator vanishes). with
                     *       ddg(j) = dg(j+1) - dg(j),
                     *       addg(j) = abs(ddg(j)),
                     *       dg(j) = divdif(j) = (gtau[j+1] - gtau[j])/dtau[j]
                     *  and
                     *       h(u,z) = alpha*u**3 + (1 - alpha)*(max(((u-zeta)/(1-zeta)),0)**3
                     *  with
                     *       alpha(z) = (1-gamma/3)/zeta
                     *       zeta(z) = 1 - gamma*min((1 - z), 1/3)
                     *  thus, for 1/3 .le. z .le. 2/3,  f  is just a cubic polynomial on
                     *  the interval i. otherwise, it has one additional knot, at
                     *         tau[i] + zeta*dtau[i] .
                     *  as  z  approaches  1, h(.,z) has an increasingly sharp bend  near 1,
                     *  thus allowing  f  to turn rapidly near the additional knot.
                     *     in terms of f(j) = gtau[j] and
                     *       fsecnd[j] = 2*derivative of f at tau[j],
                     *  the coefficients for (*) are given as
                     *       a = f(i) - d
                     *       b = (f(i+1) - f(i)) - (c - d)
                     *       c = fsecnd[i+1]*dtau[i]**2/hsecnd(1,z)
                     *       d = fsecnd[i]*dtau[i]**2/hsecnd(1,1-z)
                     *  hence can be computed once fsecnd[i],i=0,...,ntau-1, is fixed.
                     *
                     *   f  is automatically continuous and has a continuous second derivat-
                     *  ive (except when z = 0 or 1 for some i). we determine fscnd(.) from
                     *  the requirement that also the first derivative of  f  be continuous.
                     *  in addition, we require that the third derivative be continuous
                     *  across  tau[1] and across tau[ntau-2] . this leads to a strictly
                     *  diagonally dominant tridiagonal linear system for the fsecnd[i]
                     *  which we solve by gauss elimination without pivoting.
                     *
                     *  There must be at least 4 interpolation points for us to fit a taut
                     * cubic spline, but if you provide fewer we'll fit a quadratic or linear
                     * polynomial (but you must provide at least 2)
                     *
                     * See also phSplineFindTautEven and phSplineFindTautOdd for splining
                     * functions with known symmetries
                     */
                                    TautSpline::TautSpline(std::vector const& x, ///< points where function's specified
                                                           std::vector const& y, ///< values of function at tau[]
                                                           double const gamma0,          ///< control extra knots
                                                           Symmetry type                 ///< specify the desired symmetry (e.g. Even)
                                                          )
                                    {
                                        if(x.size() != y.size()) {
    
    185 66ed4513 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    185 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("TautSpline: x and y must have the same size; saw %d %d\n") % x.size() % y.size()).str()); } int const ntau = x.size(); /* size of tau and gtau, must be >= 2*/ if(ntau < 2) {
    192 66ed4513 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    192 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("TautSpline: ntau = %d, should be >= 2\n") % ntau).str()); } switch (type) { case Unknown: calculateTautSpline(x, y, gamma0); break; case Even: case Odd: calculateTautSplineEvenOdd(x, y, gamma0, type == Even); break; } } /************************************************************************************************************/ /** * Here's the worker routine for the TautSpline ctor */ void TautSpline::calculateTautSpline(std::vector const& x, ///< points where function's specified std::vector const& y, ///< values of function at tau[] double const gamma0 ///< control extra knots ) { const double *tau = &x[0]; const double *gtau = &y[0]; int const ntau = x.size(); // size of tau and gtau, must be >= 2 if(ntau < 4) { // use a single quadratic int const nknot = ntau; _allocateSpline(nknot); _knots[0] = tau[0]; for (int i = 1; i < nknot;i++) { _knots[i] = tau[i]; if(tau[i - 1] >= tau[i]) {
    231 66ed4513 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    231 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("point %d and the next, %f %f, are out of order") % (i - 1) % tau[i - 1] % tau[i]).str()); } } if(ntau == 2) { _coeffs[0][0] = gtau[0]; _coeffs[1][0] = (gtau[1] - gtau[0])/(tau[1] - tau[0]); _coeffs[2][0] = _coeffs[3][0] = 0; _coeffs[0][1] = gtau[1]; _coeffs[1][1] = (gtau[1] - gtau[0])/(tau[1] - tau[0]); _coeffs[2][1] = _coeffs[3][1] = 0; } else { /* must be 3 */ double tmp = (tau[2]-tau[0])*(tau[2]-tau[1])*(tau[1]-tau[0]); _coeffs[0][0] = gtau[0]; _coeffs[1][0] = ((gtau[1] - gtau[0])*pow(tau[2] - tau[0],2) - (gtau[2] - gtau[0])*pow(tau[1] - tau[0],2))/tmp; _coeffs[2][0] = -2*((gtau[1] - gtau[0])*(tau[2] - tau[0]) - (gtau[2] - gtau[0])*(tau[1] - tau[0]))/tmp; _coeffs[3][0] = 0; _coeffs[0][1] = gtau[1]; _coeffs[1][1] = _coeffs[1][0] + (tau[1] - tau[0])*_coeffs[2][0]; _coeffs[2][1] = _coeffs[2][0]; _coeffs[3][1] = 0; _coeffs[0][2] = gtau[2]; _coeffs[1][2] = _coeffs[1][0] + (tau[2] - tau[0])*_coeffs[2][0]; _coeffs[2][2] = _coeffs[2][0]; _coeffs[3][2] = 0; } return; } /* * Allocate scratch space * s[0][...] = dtau = tau(.+1) - tau * s[1][...] = diag = diagonal in linear system * s[2][...] = u = upper diagonal in linear system * s[3][...] = r = right side for linear system (initially) * = fsecnd = solution of linear system , namely the second * derivatives of interpolant at tau * s[4][...] = z = indicator of additional knots * s[5][...] = 1/hsecnd(1,x) with x = z or = 1-z. see below. */ std::vector > s(6); // scratch space for (int i = 0; i != 6; i++) { s[i].resize(ntau); } /* * Construct delta tau and first and second (divided) differences of data */ for (int i = 0; i < ntau - 1; i++) { s[0][i] = tau[i + 1] - tau[i]; if(s[0][i] <= 0.) {
    290 66ed4513 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    290 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("point %d and the next, %f %f, are out of order") % i % tau[i] % tau[i+1]).str()); } s[3][i + 1] = (gtau[i + 1] - gtau[i])/s[0][i]; } for (int i = 1; i < ntau - 1; ++i) { s[3][i] = s[3][i + 1] - s[3][i]; } /* * Construct system of equations for second derivatives at tau. At each * interior data point, there is one continuity equation, at the first * and the last interior data point there is an additional one for a * total of ntau equations in ntau unknowns. */ s[1][1] = s[0][0]/3; int method; double gamma = gamma0; // control the smoothing if(gamma <= 0) { method = 1; } else if(gamma > 3) { gamma -= 3; method = 3; } else { method = 2; } double const onemg3 = 1 - gamma/3; int nknot = ntau; // count number of knots /* * Some compilers don't realise that the flow of control always initialises * these variables; so initialise them to placate e.g. gcc */ double zeta = 0.0; double alpha = 0.0; double ratio = 0.0; //double c, d; //double z, denom, factr2; //double onemzt, zt2, del; double entry3 = 0.0; double factor = 0.0; double onemzt = 0; double zt2 = 0; double z_half = 0; for (int i = 1; i < ntau - 2; ++i) { /* * construct z[i] and zeta[i] */ double z = .5; if((method == 2 && s[3][i]*s[3][i + 1] >= 0) || method == 3) { double const temp = fabs(s[3][i + 1]); double const denom = fabs(s[3][i]) + temp; if(denom != 0) { z = temp/denom; if (fabs(z - 0.5) <= 1.0/6.0) { z = 0.5; } } } s[4][i] = z; /* set up part of the i-th equation which depends on the i-th interval */ z_half = z - 0.5; if(z_half < 0) { zeta = gamma*z; onemzt = 1 - zeta; zt2 = zeta*zeta; double temp = onemg3/onemzt; alpha = (temp < 1 ? temp : 1); factor = zeta/(alpha*(zt2 - 1) + 1); s[5][i] = zeta*factor/6; s[1][i] += s[0][i]*((1 - alpha*onemzt)*factor/2 - s[5][i]); /* * if z = 0 and the previous z = 1, then d[i] = 0. Since then * also u[i-1] = l[i+1] = 0, its value does not matter. Reset * d[i] = 1 to insure nonzero pivot in elimination. */ if (s[1][i] <= 0.) { s[1][i] = 1; } s[2][i] = s[0][i]/6; if(z != 0) { /* we'll get a new knot */ nknot++; } } else if(z_half == 0) { s[1][i] += s[0][i]/3; s[2][i] = s[0][i]/6; } else { onemzt = gamma*(1 - z); zeta = 1 - onemzt; double const temp = onemg3/zeta; alpha = (temp < 1 ? temp : 1); factor = onemzt/(1 - alpha*zeta*(onemzt + 1)); s[5][i] = onemzt*factor/6; s[1][i] += s[0][i]/3; s[2][i] = s[5][i]*s[0][i]; if(onemzt != 0) { /* we'll get a new knot */ nknot++; } } if (i == 1) { s[4][0] = 0.5; /* * the first two equations enforce continuity of the first and of * the third derivative across tau[1]. */ s[1][0] = s[0][0]/6; s[2][0] = s[1][1]; entry3 = s[2][1]; if(z_half < 0) { const double factr2 = zeta*(alpha*(zt2 - 1.) + 1.)/(alpha*(zeta*zt2 - 1.) + 1.); ratio = factr2*s[0][1]/s[1][0]; s[1][1] = factr2*s[0][1] + s[0][0]; s[2][1] = -factr2*s[0][0]; } else if (z_half == 0) { ratio = s[0][1]/s[1][0]; s[1][1] = s[0][1] + s[0][0]; s[2][1] = -s[0][0]; } else { ratio = s[0][1]/s[1][0]; s[1][1] = s[0][1] + s[0][0]; s[2][1] = -s[0][0]*6*alpha*s[5][1]; } /* * at this point, the first two equations read * diag[0]*x0 + u[0]*x1 + entry3*x2 = r[1] * -ratio*diag[0]*x0 + diag[1]*x1 + u[1]*x2 = 0 * set r[0] = r[1] and eliminate x1 from the second equation */ s[3][0] = s[3][1]; s[1][1] += ratio*s[2][0]; s[2][1] += ratio*entry3; s[3][1] = ratio*s[3][1]; } else { /* * the i-th equation enforces continuity of the first derivative * across tau[i]; it reads * -ratio*diag[i-1]*x_{i-1} + diag[i]*x_i + u[i]*x_{i+1} = r[i] * eliminate x_{i-1} from this equation */ s[1][i] += ratio*s[2][i - 1]; s[3][i] += ratio*s[3][i - 1]; } /* * Set up the part of the next equation which depends on the i-th interval. */ if(z_half < 0) { ratio = -s[5][i]*s[0][i]/s[1][i]; s[1][i + 1] = s[0][i]/3; } else if(z_half == 0) { ratio = -(s[0][i]/6)/s[1][i]; s[1][i + 1] = s[0][i]/3; } else { ratio = -(s[0][i]/6)/s[1][i]; s[1][i + 1] = s[0][i]*((1 - zeta*alpha)*factor/2 - s[5][i]); } } s[4][ntau - 2] = 0.5; /* * last two equations, which enforce continuity of third derivative and * of first derivative across tau[ntau - 2] */ double const entry_ = ratio*s[2][ntau - 3] + s[1][ntau - 2] + s[0][ntau - 2]/3; s[1][ntau - 1] = s[0][ntau - 2]/6; s[3][ntau - 1] = ratio*s[3][ntau - 3] + s[3][ntau - 2]; if (z_half < 0) { ratio = s[0][ntau - 2]*6*s[5][ntau - 3]*alpha/s[1][ntau - 3]; s[1][ntau - 2] = ratio*s[2][ntau - 3] + s[0][ntau - 2] + s[0][ntau - 3]; s[2][ntau - 2] = -s[0][ntau - 3]; } else if (z_half == 0) { ratio = s[0][ntau - 2]/s[1][ntau - 3]; s[1][ntau - 2] = ratio*s[2][ntau - 3] + s[0][ntau - 2] + s[0][ntau - 3]; s[2][ntau - 2] = -s[0][ntau - 3]; } else { const double factr2 = onemzt*(alpha*(onemzt*onemzt - 1) + 1)/(alpha*(onemzt*onemzt*onemzt - 1) + 1); ratio = factr2*s[0][ntau - 2]/s[1][ntau - 3]; s[1][ntau - 2] = ratio*s[2][ntau - 3] + factr2*s[0][ntau - 3] + s[0][ntau - 2]; s[2][ntau - 2] = -factr2*s[0][ntau - 3]; } /* * at this point, the last two equations read * diag[i]*x_i + u[i]*x_{i+1} = r[i] * -ratio*diag[i]*x_i + diag[i+1]*x_{i+1} = r[i+1] * eliminate x_i from last equation */ s[3][ntau - 2] = ratio*s[3][ntau - 3]; ratio = -entry_/s[1][ntau - 2]; s[1][ntau - 1] += ratio*s[2][ntau - 2]; s[3][ntau - 1] += ratio*s[3][ntau - 2]; /* * back substitution */ s[3][ntau - 1] /= s[1][ntau - 1]; for (int i = ntau - 2; i > 0; --i) { s[3][i] = (s[3][i] - s[2][i]*s[3][i + 1])/s[1][i]; } s[3][0] = (s[3][0] - s[2][0]*s[3][1] - entry3*s[3][2])/s[1][0]; /* * construct polynomial pieces; first allocate space for the coefficients */ #if 1 /* * Start by counting the knots */ { int const nknot0 = nknot; int nknot = ntau; for (int i = 0; i < ntau - 1; ++i) { double const z = s[4][i]; if((z < 0.5 && z != 0.0) || (z > 0.5 && (1 - z) != 0.0)) { nknot++; } } assert (nknot == nknot0); } #endif _allocateSpline(nknot); _knots[0] = tau[0]; int j = 0; for (int i = 0; i < ntau - 1; ++i) { _coeffs[0][j] = gtau[i]; _coeffs[2][j] = s[3][i]; double const divdif = (gtau[i + 1] - gtau[i])/s[0][i]; double z = s[4][i]; double const z_half = z - 0.5; if (z_half < 0) { if (z == 0) { _coeffs[1][j] = divdif; _coeffs[2][j] = 0; _coeffs[3][j] = 0; } else { zeta = gamma*z; onemzt = 1 - zeta; double const c = s[3][i + 1]/6; double const d = s[3][i]*s[5][i]; j++; double const del = zeta*s[0][i]; _knots[j] = tau[i] + del; zt2 = zeta*zeta; double temp = onemg3/onemzt; alpha = (temp < 1 ? temp : 1); factor = onemzt*onemzt*alpha; temp = s[0][i]; _coeffs[0][j] = gtau[i] + divdif*del + temp*temp*(d*onemzt*(factor - 1) + c*zeta*(zt2 - 1)); _coeffs[1][j] = divdif + s[0][i]*(d*(1 - 3*factor) + c*(3*zt2 - 1)); _coeffs[2][j] = (d*alpha*onemzt + c*zeta)*6; _coeffs[3][j] = (c - d*alpha)*6/s[0][i]; if(del*zt2 == 0) { _coeffs[1][j - 1] = 0; /* would be NaN in an */ _coeffs[3][j - 1] = 0; /* 0-length interval */ } else { _coeffs[3][j - 1] = _coeffs[3][j] - d*6*(1 - alpha)/(del*zt2); _coeffs[1][j - 1] = _coeffs[1][j] - del*(_coeffs[2][j] - del/2*_coeffs[3][j - 1]); } } } else if (z_half == 0) { _coeffs[1][j] = divdif - s[0][i]*(s[3][i]*2 + s[3][i + 1])/6; _coeffs[3][j] = (s[3][i + 1] - s[3][i])/s[0][i]; } else { onemzt = gamma*(1 - z); if (onemzt == 0) { _coeffs[1][j] = divdif; _coeffs[2][j] = 0; _coeffs[3][j] = 0; } else { zeta = 1 - onemzt; double const temp = onemg3/zeta; alpha = (temp < 1 ? temp : 1); double const c = s[3][i + 1]*s[5][i]; double const d = s[3][i]/6; double const del = zeta*s[0][i]; _knots[j + 1] = tau[i] + del; _coeffs[1][j] = divdif - s[0][i]*(2*d + c); _coeffs[3][j] = (c*alpha - d)*6/s[0][i]; j++; _coeffs[3][j] = _coeffs[3][j - 1] + (1 - alpha)*6*c/(s[0][i]*(onemzt*onemzt*onemzt)); _coeffs[2][j] = _coeffs[2][j - 1] + del*_coeffs[3][j - 1]; _coeffs[1][j] = _coeffs[1][j - 1] + del*(_coeffs[2][j - 1] + del/2*_coeffs[3][j - 1]); _coeffs[0][j] = _coeffs[0][j - 1] + del*(_coeffs[1][j - 1] + del/2*(_coeffs[2][j - 1] + del/3*_coeffs[3][j - 1])); } } j++; _knots[j] = tau[i + 1]; } /* * If there are discontinuities some of the knots may be at the same * position; in this case we generated some NaNs above. As they only * occur for 0-length segments, it's safe to replace them by 0s * * Due to the not-a-knot condition, the last set of coefficients isn't * needed (the last-but-one is equivalent), but it makes the book-keeping * easier if we _do_ generate them */ double const del = tau[ntau - 1] - _knots[nknot - 2]; _coeffs[0][nknot - 1] = _coeffs[0][nknot - 2] + del*(_coeffs[1][nknot - 2] + del*(_coeffs[2][nknot - 2]/2 + del*_coeffs[3][nknot - 2]/6)); _coeffs[1][nknot - 1] = _coeffs[1][nknot - 2] + del*(_coeffs[2][nknot - 2] + del*_coeffs[3][nknot - 2]/2); _coeffs[2][nknot - 1] = _coeffs[2][nknot - 2] + del*_coeffs[3][nknot - 2]; _coeffs[3][nknot - 1] = _coeffs[3][nknot - 2]; assert (j + 1 == nknot); } /*****************************************************************************/ /* * Here's the code to fit smoothing splines through data points */ static void spcof1(const double x[], double avh, const double y[], const double dy[], int n, double p, double q, double a[], double *c[3], double u[], const double v[]); static void sperr1(const double x[], double avh, const double dy[], int n, double *r[3], double p, double var, std::vector *se); static double spfit1(const double x[], double avh, const double dy[], int n, double rho, double *p, double *q, double var, double stat[], const double a[], double *c[3], double *r[3], double *t[2], double u[], double v[]); static double spint1(const double x[], double *avh, const double y[], double dy[], int n, double a[], double *c[3], double *r[3], double *t[2]); /** * Algorithm 642 collected algorithms from ACM. * Algorithm appeared in Acm-Trans. Math. Software, vol.12, no. 2, * Jun., 1986, p. 150. * * Translated from fortran by a combination of f2c and RHL * * Author - M.F.Hutchinson * CSIRO Division of Mathematics and Statistics * P.O. Box 1965 * Canberra, ACT 2601 * Australia * * latest revision - 15 August 1985 * * purpose - cubic spline data smoother * * arguments: * @param x array of length n containing the abscissae of the n data points * (x(i),f(i)) i=0..n-1. x must be ordered so that x(i) .lt. x(i+1) * * @param f vector of length >= 3 containing the ordinates (or function values) * of the data points * * @param df vector of standard deviations of * the error associated with the data point; each df[] must be positive. * * y,c: spline coefficients (output). y is an array of length n; c is * an n-1 by 3 matrix. The value of the spline approximation at t is * s(t) = c[2][i]*d^3 + c[1][i]*d^2 + c[0][i]*d + y[i] * where x[i] <= t < x[i+1] and d = t - x[i]. * * var: error variance. If var is negative (i.e. unknown) then the * smoothing parameter is determined by minimizing the generalized * cross validation and an estimate of the error variance is returned. * If var is non-negative (i.e. known) then the smoothing parameter is * determined to minimize an estimate, which depends on var, of the true * mean square error. In particular, if var is zero, then an interpolating * natural cubic spline is calculated. Set var to 1 if absolute standard * deviations have been provided in df (see above). * * Notes: * * Additional information on the fit is available in the stat array. on normal exit the values are assigned as follows: * stat[0] = smoothing parameter (= rho/(rho + 1)) * stat[1] = estimate of the number of degrees of freedom of the * residual sum of squares; this reduces to the usual value of n-2 * when a least squares regression line is calculated. * stat[2] = generalized cross validation * stat[3] = mean square residual * stat[4] = estimate of the true mean square error at the data points * stat[5] = estimate of the error variance; chi^2/nu in the case * of linear regression * * If stat[0]==0 (rho==0) an interpolating natural cubic spline has been * calculated; if stat[0]==1 (rho==infinite) a least squares regression * line has been calculated. * * Returns stat[4], an estimate of the true rms error * * precision/hardware - double (originally VAX double) * * the number of arithmetic operations required by the subroutine is * proportional to n. The subroutine uses an algorithm developed by * M.F. Hutchinson and F.R. de Hoog, 'Smoothing Noisy Data with Spline * Functions', Numer. Math. 47 p.99 (1985) */ SmoothedSpline::SmoothedSpline( std::vector const& x, ///< points where function's specified; monotonic increasing std::vector const& f, ///< values of function at x std::vector const& df, ///< error in function at x double s, ///< desired chisq double *chisq, ///< final chisq (if non-NULL) std::vector *errs ///< error estimates, (if non-NULL). You'll need to delete it ) { float var = 1; // i.e. df is the absolute s.d. N.B. ADD GCV Variant with var=-1 int const n = x.size(); double const ratio = 2.0; double const tau = 1.618033989; /* golden ratio */ double avdf, avar, stat[6]; double p, q, delta, r1, r2, r3, r4; double gf1, gf2, gf3, gf4, avh, err; /* * allocate scratch space */ _allocateSpline(n); double *y = &_coeffs[0][0]; double *c[3]; c[0] = &_coeffs[1][0]; c[1] = &_coeffs[2][0]; c[2] = &_coeffs[3][0]; std::vector scratch(7*(n+2)); // scratch space double *r[3]; r[0] = &scratch[0] + 1; // we want indices -1..n r[1] = r[0] + (n + 2); r[2] = r[1] + (n + 2); double *t[2]; t[0] = r[2] + (n + 2); t[1] = t[0] + (n + 2); double *u = t[1] + (n + 2); double *v = u + (n + 2); /* * and so to work. */ std::vector sdf = df; // scaled values of df avdf = spint1(&x[0], &avh, &f[0], &sdf[0], n, y, c, r, t); avar = var; if (var > 0) { avar *= avdf*avdf; } if (var == 0) { /* simply find a natural cubic spline*/ r1 = 0; gf1 = spfit1(&x[0], avh, &sdf[0], n, r1, &p, &q, avar, stat, y, c, r, t, u, v); } else { /* Find local minimum of gcv or the expected mean square error */ r1 = 1; r2 = ratio*r1; gf2 = spfit1(&x[0], avh, &sdf[0], n, r2, &p, &q, avar, stat, y, c, r, t, u, v); bool set_r3 = false; // was r3 set? for (;;) { gf1 = spfit1(&x[0], avh, &sdf[0], n, r1, &p, &q, avar, stat, y, c, r, t, u,v); if (gf1 > gf2) { break; } if (p <= 0) { break; } r2 = r1; gf2 = gf1; r1 /= ratio; } if(p <= 0) { set_r3 = false; r3 = 0; /* placate compiler */ } else { r3 = ratio * r2; set_r3 = true; for (;;) { gf3 = spfit1(&x[0], avh, &sdf[0], n, r3, &p, &q, avar, stat, y, c, r, t, u, v); if (gf3 >= gf2) { break; } if (q <= 0) { break; } r2 = r3; gf2 = gf3; r3 = ratio*r3; } } if(p > 0 && q > 0) { assert (set_r3); r2 = r3; gf2 = gf3; delta = (r2 - r1) / tau; r4 = r1 + delta; r3 = r2 - delta; gf3 = spfit1(&x[0], avh, &sdf[0], n, r3, &p, &q, avar, stat, y, c, r, t, u, v); gf4 = spfit1(&x[0], avh, &sdf[0], n, r4, &p, &q, avar, stat, y, c, r, t, u, v); /* * Golden section search for local minimum */ do { if (gf3 <= gf4) { r2 = r4; gf2 = gf4; r4 = r3; gf4 = gf3; delta /= tau; r3 = r2 - delta; gf3 = spfit1(&x[0], avh, &sdf[0], n, r3, &p, &q, avar, stat, y, c, r, t, u, v); } else { r1 = r3; gf1 = gf3; r3 = r4; gf3 = gf4; delta /= tau; r4 = r1 + delta; gf4 = spfit1(&x[0], avh, &sdf[0], n, r4, &p, &q, avar, stat, y, c, r, t, u, v); } err = (r2 - r1) / (r1 + r2); } while(err*err + 1 > 1 && err > 1e-6); r1 = (r1 + r2) * .5; gf1 = spfit1(&x[0], avh, &sdf[0], n, r1, &p, &q, avar, stat, y, c, r, t, u,v); } } /* * Calculate spline coefficients */ spcof1(&x[0], avh, &f[0], &sdf[0], n, p, q, y, c, u, v); stat[2] /= avdf*avdf; /* undo scaling */ stat[3] /= avdf*avdf; stat[4] /= avdf*avdf; /* * Optionally calculate standard error estimates */ if(errs != NULL) { sperr1(&x[0], avh, &sdf[0], n, r, p, avar, errs); } /* * clean up */ if(chisq != NULL) { *chisq = n*stat[4]; } } /*****************************************************************************/ /* * initializes the arrays c, r and t for one dimensional cubic * smoothing spline fitting by subroutine spfit1. The values * df[i] are scaled so that the sum of their squares is n. * The average of the differences x[i+1] - x[i] is calculated * in avh in order to avoid underflow and overflow problems in spfit1. * * Return the initial rms value of dy. */ static double spint1(const double x[], double *avh, const double f[], double df[], int n, double a[], double *c[3], double *r[3], double *t[2]) { double avdf; double e, ff, g, h; int i; assert (n >= 3); /* * Get average x spacing in avh */ g = 0; for (i = 0; i < n - 1; ++i) { h = x[i + 1] - x[i]; assert (h > 0); g += h; } *avh = g/(n - 1); /* * Scale relative weights */ g = 0; for (int i = 0; i < n; ++i) { assert(df[i] > 0); g += df[i]*df[i]; } avdf = sqrt(g / n); for (i = 0; i < n; ++i) { df[i] /= avdf; } /* * Initialize h,f */ h = (x[1] - x[0])/(*avh); ff = (f[1] - f[0])/h; /* * Calculate a,t,r */ for (i = 1; i < n - 1; ++i) { g = h; h = (x[i + 1] - x[i])/(*avh); e = ff; ff = (f[i + 1] - f[i])/h; a[i] = ff - e; t[0][i] = (g + h) * 2./3.; t[1][i] = h / 3.; r[2][i] = df[i - 1]/g; r[0][i] = df[i + 1]/h; r[1][i] = -df[i]/g - df[i]/h; } /* * Calculate c = r'*r */ r[1][n-1] = 0; r[2][n-1] = 0; r[2][n] = 0; for (i = 1; i < n - 1; i++) { c[0][i] = r[0][i]*r[0][i] + r[1][i]*r[1][i] + r[2][i]*r[2][i]; c[1][i] = r[0][i]*r[1][i+1] + r[1][i]*r[2][i+1]; c[2][i] = r[0][i]*r[2][i+2]; } return(avdf); } /*****************************************************************************/ /* * Fits a cubic smoothing spline to data with relative * weighting dy for a given value of the smoothing parameter * rho using an algorithm based on that of C.H. Reinsch (1967), * Numer. Math. 10, 177-183. * * The trace of the influence matrix is calculated using an * algorithm developed by M.F.Hutchinson and F.R.De Hoog (numer. * math., 47 p.99 (1985)), enabling the generalized cross validation * and related statistics to be calculated in order n operations. * * The arrays a, c, r and t are assumed to have been initialized * by the routine spint1. overflow and underflow problems are * avoided by using p=rho/(1 + rho) and q=1/(1 + rho) instead of * rho and by scaling the differences x[i+1] - x[i] by avh. * * The values in dy are assumed to have been scaled so that the * sum of their squared values is n. the value in var, when it is * non-negative, is assumed to have been scaled to compensate for * the scaling of the values in dy. * * the value returned in fun is an estimate of the true mean square * when var is non-negative, and is the generalized cross validation * when var is negative. */ static double spfit1(const double x[], double avh, const double dy[], int n, double rho, double *pp, double *pq, double var, double stat[], const double a[], double *c[3], double *r[3], double *t[2], double u[], double v[]) { double const eps = std::numeric_limits::epsilon(); double e, f, g, h; double fun; int i; double p, q; /* == *pp, *pq */ /* * Use p and q instead of rho to prevent overflow or underflow */ if(fabs(rho) < eps) { p = 0; q = 1; } else if(fabs(1/rho) < eps) { p = 1; q = 0; } else { p = rho/(1 + rho); q = 1/(1 + rho); } /* * Rational Cholesky decomposition of p*c + q*t */ f = 0; g = 0; h = 0; r[0][-1] = r[0][0] = 0; for (int i = 1; i < n - 1; ++i) { r[2][i-2] = g*r[0][i - 2]; r[1][i-1] = f*r[0][i - 1]; { double tmp = p*c[0][i] + q*t[0][i] - f*r[1][i-1] - g*r[2][i-2]; if(tmp == 0.0) { r[0][i] = 1e30; } else { r[0][i] = 1/tmp; } } f = p*c[1][i] + q*t[1][i] - h*r[1][i-1]; g = h; h = p*c[2][i]; } /* * Solve for u */ u[-1] = u[0] = 0; for (int i = 1; i < n - 1; i++) { u[i] = a[i] - r[1][i-1]*u[i-1] - r[2][i-2]*u[i-2]; } u[n-1] = u[n] = 0; for (int i = n - 2; i > 0; i--) { u[i] = r[0][i]*u[i] - r[1][i]*u[i+1] - r[2][i]*u[i+2]; } /* * Calculate residual vector v */ e = h = 0; for (int i = 0; i < n - 1; i++) { g = h; h = (u[i + 1] - u[i])/((x[i+1] - x[i])/avh); v[i] = dy[i]*(h - g); e += v[i]*v[i]; } v[n-1] = -h*dy[n-1]; e += v[n-1]*v[n-1]; /* * Calculate upper three bands of inverse matrix */ r[0][n-1] = r[1][n-1] = r[0][n] = 0; for (i = n - 2; i > 0; i--) { g = r[1][i]; h = r[2][i]; r[1][i] = -g*r[0][i+1] - h*r[1][i+1]; r[2][i] = -g*r[1][i+1] - h*r[0][i+2]; r[0][i] = r[0][i] - g*r[1][i] - h*r[2][i]; } /* * Calculate trace */ f = g = h = 0; for (i = 1; i < n - 1; ++i) { f += r[0][i]*c[0][i]; g += r[1][i]*c[1][i]; h += r[2][i]*c[2][i]; } f += 2*(g + h); /* * Calculate statistics */ stat[0] = p; stat[1] = f*p; stat[2] = n*e/(f*f + 1e-20); stat[3] = e*p*p/n; stat[5] = e*p/((f < 0) ? f - 1e-10 : f + 1e-10); if (var >= 0) { fun = stat[3] - 2*var*stat[1]/n + var; stat[4] = fun; } else { stat[4] = stat[5] - stat[3]; fun = stat[2]; } *pp = p; *pq = q; return(fun); } /* * Calculates coefficients of a cubic smoothing spline from * parameters calculated by spfit1() */ static void spcof1(const double x[], double avh, const double y[], const double dy[], int n, double p, double q, double a[], double *c[3], double u[], const double v[]) { double h; int i; double qh; qh = q/(avh*avh); for (i = 0; i < n; ++i) { a[i] = y[i] - p * dy[i] * v[i]; u[i] = qh*u[i]; } /* * calculate c */ for (i = 0; i < n - 1; ++i) { h = x[i+1] - x[i]; c[2][i] = (u[i + 1] - u[i])/(3*h); c[0][i] = (a[i + 1] - a[i])/h - (h*c[2][i] + u[i])*h; c[1][i] = u[i]; } } /*****************************************************************************/ /* * Calculates Bayesian estimates of the standard errors of the fitted * values of a cubic smoothing spline by calculating the diagonal elements * of the influence matrix. */ static void sperr1(const double x[], double avh, const double dy[], int n, double *r[3], double p, double var, std::vector *se) { double f, g, h; int i; double f1, g1, h1; /* * Initialize */ h = avh/(x[1] - x[0]); (*se)[0] = 1 - p*dy[0]*dy[0]*h*h*r[0][1]; r[0][0] = r[1][0] = r[2][0] = 0; /* * Calculate diagonal elements */ for (i = 1; i < n - 1; ++i) { f = h; h = avh/(x[i+1] - x[i]); g = -(f + h); f1 = f*r[0][i-1] + g*r[1][i-1] + h*r[2][i-1]; g1 = f*r[1][i-1] + g*r[0][i] + h*r[1][i]; h1 = f*r[2][i-1] + g*r[1][i] + h*r[0][i+1]; (*se)[i] = 1 - p*dy[i]*dy[i]*(f*f1 + g*g1 + h*h1); } (*se)[n-1] = 1 - p*dy[n-1]*dy[n-1]*h*h*r[0][n-2]; /* * Calculate standard error estimates */ for (int i = 0; i < n; ++i) { double const tmp = (*se)[i]*var; (*se)[i] = (tmp >= 0) ? sqrt(tmp)*dy[i] : 0; } } /*****************************************************************************/ /* * * * Fit a taut spline to a set of data, forcing the resulting spline to * obey S(x) = +-S(-x). The input points must have tau[] >= 0. * * See TautSpline::TautSpline() for a discussion of the algorithm, and * the meaning of the parameter gamma * * This is done by duplicating the input data for -ve x, so consider * carefully before using this function on many-thousand-point datasets */ void TautSpline::calculateTautSplineEvenOdd(std::vector const& _tau, std::vector const& _gtau, double const gamma, bool const even // ensure Even symmetry ) { const double *tau = &_tau[0]; const double *gtau = &_gtau[0]; int const ntau = _tau.size(); // size of tau and gtau, must be >= 2 std::vector x, y; // tau and gtau, extended to -ve tau if(tau[0] == 0.0f) { int const np = 2*ntau - 1; x.resize(np); y.resize(np); x[ntau - 1] = tau[0]; y[ntau - 1] = gtau[0]; for (int i = 1; i != ntau; ++i) { if (even) { x[ntau - 1 + i] = tau[i]; y[ntau - 1 + i] = gtau[i]; x[ntau - 1 - i] = -tau[i]; y[ntau - 1 - i] = gtau[i]; } else { x[ntau - 1 + i] = tau[i]; y[ntau - 1 + i] = gtau[i]; x[ntau - 1 - i] = -tau[i]; y[ntau - 1 - i] = -gtau[i]; } } } else { int const np = 2*ntau; x.resize(np); y.resize(np); for (int i = 0; i != ntau; ++i) { if (even) { x[ntau + i] = tau[i]; y[ntau + i] = gtau[i]; x[ntau - 1 - i] = -tau[i]; y[ntau - 1 - i] = gtau[i]; } else { x[ntau + i] = tau[i]; y[ntau + i] = gtau[i]; x[ntau - 1 - i] = -tau[i]; y[ntau - 1 - i] = -gtau[i]; } } } TautSpline sp(x, y, gamma); // fit a taut spline to x, y /* * Now repackage that spline to reflect the original points */ int ii; for (ii = sp._knots.size() - 1; ii >= 0; --ii) { if(sp._knots[ii] < 0.0f) { break; } } int const i0 = ii + 1; int const nknot = sp._knots.size() - i0; _allocateSpline(nknot); for (int i = i0; i != static_cast(sp._knots.size()); ++i) { _knots[i - i0] = sp._knots[i]; for (int j = 0; j != 4; ++j) { _coeffs[j][i - i0] = sp._coeffs[j][i]; } } } /*****************************************************************************/ /* * returns index i of first element of x >= z; the input i is an initial guess * * N.b. we could use std::lower_bound except that we use i as an initial hint */ static int search_array(double z, double const *x, int n, int i) {
    1273 66ed4513 - register int lo, hi, mid;
    ? ---------
    1273 51a67dff + int lo, hi, mid;
    double xm; if(i < 0 || i >= n) { /* initial guess is useless */ lo = -1; hi = n; } else { unsigned int step = 1; /* how much to step up/down */ if(z > x[i]) { /* expand search upwards */ if(i == n - 1) { /* off top of array */ return(n - 1); } lo = i; hi = lo + 1; while(z >= x[hi]) { lo = hi; step += step; /* double step size */ hi = lo + step; if(hi >= n) { /* reached top of array */ hi = n - 1; break; } } } else { /* expand it downwards */ if(i == 0) { /* off bottom of array */ return(-1); } hi = i; lo = i - 1; while(z < x[lo]) { hi = lo; step += step; /* double step size */ lo = hi - step; if(lo < 0) { /* off bottom of array */ lo = -1; break; } } } } /* * perform bisection */ while(hi - lo > 1) { mid = (lo + hi)/2; xm = x[mid]; if(z <= xm) { hi = mid; } else { lo = mid; } } if(lo == -1) { /* off the bottom */ return(lo); } /* * If there's a discontinuity (many knots at same x-value), choose the * largest */ xm = x[lo]; while(lo < n - 1 && x[lo + 1] == xm) lo++; return(lo); } /*****************************************************************************/ /* * Move the roots that lie in the specified range [x0,x1) from newRoots to roots */ static void keep_valid_roots(std::vector& roots, std::vector& newRoots, double x0, double x1) { for (unsigned int i = 0; i != newRoots.size(); ++i) { if(newRoots[i] >= x0 && newRoots[i] < x1) { // keep this root roots.push_back(newRoots[i]); } } newRoots.clear(); } /*****************************************************************************/ /* * find the real roots of a quadratic ax^2 + bx + c = 0 */ namespace { void do_quadratic(double a, double b, double c, std::vector & roots) { if(::fabs(a) < std::numeric_limits::epsilon()) { if(::fabs(b) >= std::numeric_limits::epsilon()) { roots.push_back(-c/b); } } else { double const tmp = b*b - 4*a*c; if(tmp >= 0) { if (b >= 0) { roots.push_back((-b - sqrt(tmp))/(2*a)); } else { roots.push_back((-b + sqrt(tmp))/(2*a)); } roots.push_back(c/(a*roots[0])); /* * sort roots */ if(roots[0] > roots[1]) { double const tmp2 = roots[0]; roots[0] = roots[1]; roots[1] = tmp2; } } } } /*****************************************************************************/ /* * find the real roots of a cubic ax^3 + bx^2 + cx + d = 0 */ void do_cubic(double a, double b, double c, double d, std::vector & roots) { if (::fabs(a) < std::numeric_limits::epsilon()) { do_quadratic(b, c, d, roots); return; } b /= a; c /= a; d /= a; double const q = (b*b - 3*c)/9; double const r = (2*b*b*b - 9*b*c + 27*d)/54; /* * n.b. note that the test for the number of roots is carried out on the * same variables as are used in (e.g.) the acos, as it is possible for * r*r < q*q*q && r > sq*sq*sq due to rounding. */ double const sq = (q >= 0) ? sqrt(q) : -sqrt(-q); double const sq3 = sq*sq*sq; if(::fabs(r) < sq3) { // three real roots double const theta = ::acos(r/sq3); // sq3 cannot be zero roots.push_back(-2*sq*cos(theta/3) - b/3); roots.push_back(-2*sq*cos((theta + afwGeom::TWOPI)/3) - b/3); roots.push_back(-2*sq*cos((theta - afwGeom::TWOPI)/3) - b/3); /* * sort roots */ if(roots[0] > roots[1]) { std::swap(roots[0], roots[1]); } if(roots[1] > roots[2]) { std::swap(roots[1], roots[2]); } if(roots[0] > roots[1]) { std::swap(roots[0], roots[1]); } return; } else if(::fabs(r) == sq3) { /* no more than two real roots */ double const aa = -((r < 0) ? -::pow(-r,1.0/3.0) : ::pow(r,1.0/3.0)); if(::fabs(aa) < std::numeric_limits::epsilon()) { /* degenerate case; one real root */ roots.push_back(-b/3); return; } else { roots.push_back(2*aa - b/3); roots.push_back(-aa - b/3); if(roots[0] > roots[1]) { std::swap(roots[0], roots[1]); } return; } } else { /* only one real root */ double tmp = ::sqrt(r*r - (q > 0 ? sq3*sq3 : -sq3*sq3)); tmp = r + (r < 0 ? -tmp : tmp); double const aa = -((tmp < 0) ? -::pow(-tmp,1.0/3.0) : ::pow(tmp,1.0/3.0)); double const bb = (fabs(aa) < std::numeric_limits::epsilon()) ? 0 : q/aa; roots.push_back((aa + bb) - b/3); #if 0 roots.push_back(-(aa + bb)/2 - b/3); // the real roots.push_back(::sqrt(3)/2*(aa - bb)); // and imaginary parts of the complex roots #endif return; } } } /*****************************************************************************/ /* * * * Find the roots of * Spline - val = 0 * in the range [x0, x1). Return a vector of all the roots found */ std::vector Spline::roots(double const value, ///< desired value double a, ///< specify desired range is [a,b) double const b ///< specify desired range is [a,b) ) const { /* * Strategy: we know that the interpolant has the form * val = coef[0][i] +dx*(coef[1][i] + dx*(coef[2][i]/2 + dx*coef[3][i]/6)) * so we can use the usual analytic solution for a cubic. Note that the * cubic quoted above returns dx, the distance from the previous knot, * rather than x itself */ std::vector roots; /* the roots found */ double x0 = a; // lower end of current range double const x1 = b; int const nknot = _knots.size(); int i0 = search_array(x0, &_knots[0], nknot, -1); int const i1 = search_array(x1, &_knots[0], nknot, i0); assert (i1 >= i0 && i1 <= nknot - 1); std::vector newRoots; // the roots we find in some interval /* * Deal with special case that x0 may be off one end or the other of * the array of knots. */ if(i0 < 0) { /* off bottom */ i0 = 0; do_cubic(_coeffs[3][i0]/6, _coeffs[2][i0]/2, _coeffs[1][i0], _coeffs[0][i0] - value, newRoots); // // Could use // std::transform(newRoots.begin(), newRoots.end(), newRoots.begin(), // std::tr1::bind(std::plus(), _1, _knots[i0])); // but let's not // for (unsigned int j = 0; j != newRoots.size(); ++j) { newRoots[j] += _knots[i0]; } keep_valid_roots(roots, newRoots, x0, _knots[i0]); x0 = _knots[i0]; } else if(i0 >= nknot) { /* off top */ i0 = nknot - 1; assert (i0 >= 0); do_cubic(_coeffs[3][i0]/6, _coeffs[2][i0]/2, _coeffs[1][i0], _coeffs[0][i0] - value, newRoots); for (unsigned int j = 0; j != newRoots.size(); ++j) { newRoots[j] += _knots[i0]; } keep_valid_roots(roots, newRoots, x0, x1); return roots; } /* * OK, now search in main body of spline. Note that i1 may be nknot - 1, and * in any case the right hand limit of the last segment is at x1, not a knot */ for (int i = i0;i <= i1;i++) { do_cubic(_coeffs[3][i]/6, _coeffs[2][i]/2, _coeffs[1][i], _coeffs[0][i] - value, newRoots); for (unsigned int j = 0; j != newRoots.size(); ++j) { newRoots[j] += _knots[i]; } keep_valid_roots(roots, newRoots, ((i == i0) ? x0 : _knots[i]), ((i == i1) ? x1 : _knots[i + 1])); } return roots; } }}}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    66ed4513

    commit 66ed4513d2f8b9dd0faec6fedfa3403b844786b5
    Author: rhl 
    Date:   Thu Feb 17 22:52:59 2011 +0000
    
        Added Spline code from SDSS.  Needs to be integrated into Interpolate, but this is currently too explicitly gsl-based
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    51a67dff

    commit 51a67dff1f2d5067d66ad025fe1efee37aeca339
    Author: Russell Owen 
    Date:   Tue Oct 14 12:50:44 2014 -0700
    
        Remove use of deprecated C++ keyword "register"
    

    Return to list

    include/lsst/afw/table/io/InputArchive.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_IO_InputArchive_h_INCLUDED
                    #define AFW_TABLE_IO_InputArchive_h_INCLUDED
                    
                    #include 
                    
                    #include "lsst/base.h"
                    #include "lsst/afw/table/io/Persistable.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    class BaseRecord;
                    template  class CatalogT;
                    typedef CatalogT BaseCatalog;
                    
                    namespace io {
                    
                    class CatalogVector;
                    
                    /**
                     *  @brief A multi-catalog archive object used to load table::io::Persistable objects.
                     *
                     *  An InputArchive can be constructed directly from the catalogs produced by OutputArchive,
                     *  or more usefully, read from a multi-extension FITS file.
                     *
                     *  @sa OutputArchive
                     */
                    class InputArchive {
                    public:
                    
                        typedef std::map Map;
                    
                        /// Construct an empty InputArchive that contains no objects.
                        InputArchive();
                    
                        /// @brief Construct an archive from catalogs.
                        InputArchive(BaseCatalog const & index, CatalogVector const & dataCatalogs);
                    
                        /// Copy-constructor.  Does not deep-copy loaded Persistables.
                        InputArchive(InputArchive const & other);
                    
                        /// Assignment.  Does not deep-copy loaded Persistables.
                        InputArchive & operator=(InputArchive const & other);
                    
                        ~InputArchive();
                    
                        /**
                         *  @brief Load the Persistable with the given ID and return it.
                         *
                         *  If the object has already been loaded once, the same instance will be returned again.
                         */
                        PTR(Persistable) get(int id) const;
                    
                        /// @brief Load an object of the given type and ID with error checking.
                        template 
                        PTR(T) get(int id) const {
    
    57 3bb7d83b - return boost::dynamic_pointer_cast(get(id));
    ? ^^^^^^
    57 635b6290 + PTR(T) p = boost::dynamic_pointer_cast(get(id));
    ? ^^^^^^^^^^
    58 635b6290 + LSST_ARCHIVE_ASSERT(p || id == 0);
    59 635b6290 + return p;
    } /// Load and return all objects in the archive. Map const & getAll() const; /** * @brief Read an object from an already open FITS object. * * @param[in] fitsfile FITS object to read from, already positioned at the desired HDU. */ static InputArchive readFits(fits::Fits & fitsfile); private: class Impl; InputArchive(PTR(Impl) impl); PTR(Impl) _impl; }; }}}} // namespace lsst::afw::table::io #endif // !AFW_TABLE_IO_InputArchive_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3bb7d83b

    commit 3bb7d83b20e2f2f2005df2e205ba245abaed779c
    Author: Jim Bosch 
    Date:   Fri Mar 1 12:22:14 2013 +0900
    
        Print a big warning and attempt to fail gracefully when a PersistableFactory cannot be found because its module has not been imported.
        
        This is a temporary partial bugfix for #2696, which still needs a better solution.
    

    Commits in /Users/nate/repos_lsst/afw/

    635b6290

    commit 635b629019d391ec1ccbe0d859507206049a1061
    Author: Jim Bosch 
    Date:   Fri Dec 14 15:59:25 2012 -0500
    
        Add convenience methods to archive classes.
    

    Return to list

    src/math/Background.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    /**
                     * @file Background.cc
                     * @ingroup afw
                     * @brief Background estimation class code
                     * @author Steve Bickerton
                     * @date Jan 26, 2009
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    #include "lsst/utils/ieee.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/Interpolate.h"
                    #include "lsst/afw/math/Background.h"
                    #include "lsst/afw/math/Statistics.h"
                    
                    namespace lsst {
                    namespace ex = pex::exceptions;
                    
                    namespace afw {
                    namespace math {
                    
                    /**
                     * @brief Constructor for Background
                     *
                     * Estimate the statistical properties of the Image in a grid of cells;  we'll later call
                     * getImage() to interpolate those values, creating an image the same size as the original
                     *
                     * @note The old and deprecated API specified the interpolation style as part of the BackgroundControl
                     * object passed to this ctor.  This is still supported, but the work isn't done until the getImage()
                     * method is called
                     */
                    template
                    Background::Background(ImageT const& img,              ///< ImageT (or MaskedImage) whose properties we want
                                           BackgroundControl const& bgCtrl ///< Control how the Background is estimated
                                          ) :
                        lsst::daf::base::Citizen(typeid(this)),
                        _imgBBox(img.getBBox()),
    
    64 264e671e - _bctrl(new BackgroundControl(bgCtrl)),
    64 2915cbac + _bctrl(bgCtrl),
    _asUsedInterpStyle(Interpolate::UNKNOWN), _asUsedUndersampleStyle(THROW_EXCEPTION), _xcen(0), _ycen(0), _xorig(0), _yorig(0), _xsize(0), _ysize(0) { if (_imgBBox.isEmpty()) {
    70 2915cbac - throw LSST_EXCEPT(ex::InvalidParameterException, "Image contains no pixels");
    ? ^^^^^^ ^
    70 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError, "Image contains no pixels");
    ? ^^ ^ } // Check that an int's large enough to hold the number of pixels if (_imgBBox.getWidth()*static_cast(_imgBBox.getHeight()) > std::numeric_limits::max()) {
    75 c16ef84d - throw LSST_EXCEPT(lsst::pex::exceptions::OverflowErrorException,
    ? ---------
    75 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::OverflowError,
    str(boost::format("Image %dx%d has more pixels than fit in an int (%d)") % _imgBBox.getWidth() % _imgBBox.getHeight() % std::numeric_limits::max())); } _setCenOrigSize(_imgBBox.getWidth(), _imgBBox.getHeight(), bgCtrl.getNxSample(), bgCtrl.getNySample()); } /************************************************************************************************************/ /** * Create a Background without any values in it * * \note This ctor is mostly used to create a Background given its sample values, and that (in turn) * is mostly used to implement persistence. */ Background::Background(geom::Box2I const imageBBox, ///< Bounding box for image to be created by getImage() int const nx, ///< Number of samples in x-direction int const ny ///< Number of samples in y-direction ) : lsst::daf::base::Citizen(typeid(this)), _imgBBox(imageBBox),
    96 264e671e - _bctrl(new BackgroundControl(nx, ny)),
    96 2b4b80a5 + _bctrl(nx, ny),
    _asUsedInterpStyle(Interpolate::UNKNOWN), _asUsedUndersampleStyle(THROW_EXCEPTION), _xcen(0), _ycen(0), _xorig(0), _yorig(0), _xsize(0), _ysize(0) { if (_imgBBox.isEmpty()) {
    102 2b4b80a5 - throw LSST_EXCEPT(ex::InvalidParameterException, "Image contains no pixels");
    ? ^^^^^^ ^
    102 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError, "Image contains no pixels");
    ? ^^ ^ } // Check that an int's large enough to hold the number of pixels if (_imgBBox.getWidth()*static_cast(_imgBBox.getHeight()) > std::numeric_limits::max()) {
    107 c16ef84d - throw LSST_EXCEPT(lsst::pex::exceptions::OverflowErrorException,
    ? ---------
    107 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::OverflowError,
    str(boost::format("Image %dx%d has more pixels than fit in an int (%d)") % _imgBBox.getWidth() % _imgBBox.getHeight() % std::numeric_limits::max())); } _setCenOrigSize(_imgBBox.getWidth(), _imgBBox.getHeight(), nx, ny); } /************************************************************************************************************/ /** * Compute the centers, origins, and sizes of the patches used to compute image statistics * when estimating the Background */ void Background::_setCenOrigSize(int const width, int const height, int const nxSample, int const nySample) { _xcen.resize( nxSample); _ycen.resize(nySample); _xorig.resize(nxSample); _yorig.resize(nySample); _xsize.resize(nxSample), _ysize.resize(nySample); // Compute the centers and origins for the cells for (int iX = 0; iX < nxSample; ++iX) { const int endx = std::min(((iX+1)*width + nxSample/2)/nxSample, width); _xorig[iX] = (iX == 0) ? 0 : _xorig[iX-1] + _xsize[iX-1]; _xsize[iX] = endx - _xorig[iX]; _xcen [iX] = _xorig[iX] + (0.5 * _xsize[iX]) - 0.5; } for (int iY = 0; iY < nySample; ++iY) { const int endy = std::min(((iY+1)*height + nySample/2)/nySample, height); _yorig[iY] = (iY == 0) ? 0 : _yorig[iY-1] + _ysize[iY-1]; _ysize[iY] = endy - _yorig[iY]; _ycen [iY] = _yorig[iY] + (0.5 * _ysize[iY]) - 0.5; } } /************************************************************************************************************/ /** * @brief Conversion function to switch a string to an UndersampleStyle */ UndersampleStyle stringToUndersampleStyle(std::string const &style) { static std::map undersampleStrings; if (undersampleStrings.size() == 0) { undersampleStrings["THROW_EXCEPTION"] = THROW_EXCEPTION; undersampleStrings["REDUCE_INTERP_ORDER"] = REDUCE_INTERP_ORDER; undersampleStrings["INCREASE_NXNYSAMPLE"] = INCREASE_NXNYSAMPLE; } if (undersampleStrings.find(style) == undersampleStrings.end()) {
    157 2915cbac - throw LSST_EXCEPT(ex::InvalidParameterException, "Understample style not defined: "+style);
    ? ^^^^^^ ^
    157 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError, "Understample style not defined: "+style);
    ? ^^ ^ } return undersampleStrings[style]; }
    161 b4f73cbf + /// \cond
    /* * Explicit instantiations *
    164 3f3d5e23 - * \cond
    */ #define INSTANTIATE_BACKGROUND(TYPE) \ template Background::Background(image::Image const& img, \ BackgroundControl const& bgCtrl); \ template Background::Background(image::MaskedImage const& img, \ BackgroundControl const& bgCtrl); \ template PTR(image::Image) Background::getImage(Interpolate::Style const, \ UndersampleStyle const) const;
    175 fccddbab + INSTANTIATE_BACKGROUND(double)
    INSTANTIATE_BACKGROUND(float)
    177 fccddbab + INSTANTIATE_BACKGROUND(int)
    /// \endcond }}}
    179 2915cbac -

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    2b4b80a5

    commit 2b4b80a531b4f37ae62b237534c8142eb3450449
    Author: Robert Lupton the Good 
    Date:   Sat Mar 9 07:01:06 2013 +0900
    
        Make it possible to round-trip a list of Backgrounds via disk
        
        This involved adding a ctor to make a BackgroundMI from a statsImage
        and the full-resolution image bounding box (n.b. the origin is
        still ignored).   Because much task code still uses legacy API where
        the interpolation style is specified in the ctor, not as arguments to
        getImage where it's actually used, it seemed out of scope to expect
        the list to be of tuples (Background, interpStyle, undersampleStyle)
        so I use the values that were last used to get an Image.  This is
        probably safe, but is a little ugly.
    

    c16ef84d

    commit c16ef84dbc57a40a79480b3b277261cb6bbe22c6
    Author: Robert Lupton the Good 
    Date:   Wed Apr 3 16:45:18 2013 -0400
    
        Cleanups as proposed by REO in code review for #2732
    

    2915cbac

    commit 2915cbac8ebf464fe28a3c0f2752a8211d9be37b
    Author: Robert Lupton the Good 
    Date:   Tue Oct 16 13:19:16 2012 -0400
    
        Changed names of Background classes
        
        BackgroundBase -> Background
        Background     -> BackgroundMI
    

    264e671e

    commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
    Author: Steven Bickerton 
    Date:   Fri Oct 24 14:37:15 2014 +0900
    
        Use shared_ptr.  Add test.  Disable double,int backgrounds.
    

    3f3d5e23

    commit 3f3d5e23184916da9caf2bbd21eaf87513bb099c
    Author: rhl 
    Date:   Thu Jun 3 18:12:24 2010 +0000
    
        Changes to make doxygen a little less unhappy
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    2b4b80a5

    commit 2b4b80a531b4f37ae62b237534c8142eb3450449
    Author: Robert Lupton the Good 
    Date:   Sat Mar 9 07:01:06 2013 +0900
    
        Make it possible to round-trip a list of Backgrounds via disk
        
        This involved adding a ctor to make a BackgroundMI from a statsImage
        and the full-resolution image bounding box (n.b. the origin is
        still ignored).   Because much task code still uses legacy API where
        the interpolation style is specified in the ctor, not as arguments to
        getImage where it's actually used, it seemed out of scope to expect
        the list to be of tuples (Background, interpStyle, undersampleStyle)
        so I use the values that were last used to get an Image.  This is
        probably safe, but is a little ugly.
    

    b4f73cbf

    commit b4f73cbf3097165062c02aa04905ab10b06c6bec
    Author: Russell Owen 
    Date:   Mon Sep 8 16:05:52 2014 -0700
    
        First pass at DM-840
        Added UNDEFINED ImageOrigin enum value
        Made UNDEFINED the default for image constructors (which have lots of defaults,
        so I can't just delete the origin default).
        Eliminated the default value for ImageBase.getBBox.
        Modified all code that calls functions that accept an ImageOrigin argument to specify it explicitly.
    

    2915cbac

    commit 2915cbac8ebf464fe28a3c0f2752a8211d9be37b
    Author: Robert Lupton the Good 
    Date:   Tue Oct 16 13:19:16 2012 -0400
    
        Changed names of Background classes
        
        BackgroundBase -> Background
        Background     -> BackgroundMI
    

    fccddbab

    commit fccddbabb1a929463ba18c37488a204d4d6acf66
    Author: rhl 
    Date:   Fri Feb 19 17:32:31 2010 +0000
    
        Fix icc warnings, as per #1179
    

    Return to list

    doc/doxygen.conf.in

    Diff:

                    EXAMPLE_PATH = examples
    
    2 bde0ab27 + INPUT += examples/imageDisplay.ipynb
    EXCLUDE += include/lsst/afw/detection/FootprintArray.cc EXCLUDE += include/lsst/afw/detection/detail/dgPsf.cc EXCLUDE += src/math/Stack.cc EXCLUDE += src/image/Utils.cc EXCLUDE += src/image/TanWcs.cc EXCLUDE += src/math/FunctionLibrary.cc EXCLUDE += src/table EXCLUDE += src/geom EXCLUDE += src/geom/ellipses EXCLUDE += src/detection/Psf.cc EXCLUDE += src/detection/DoubleGaussianPsf.cc EXCLUDE += src/fits.cc EXCLUDE_SYMBOLS += _swig_property

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    bde0ab27

    commit bde0ab27a9add858f810563213c1424f9e63ddde
    Author: Robert Lupton the Good 
    Date:   Sun Apr 12 16:00:47 2015 -0300
    
        Implement RFC-42
        
        N.b. that you need display_ds9 to use the ds9 backend
        N.b. support frame only in cameraGeom.utils top-level routine, showCamera
    

    Return to list

    examples/spatialCellExample.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /*
                     * This C++ example does the same thing as SpatialCellExample.py.  The latter of the python version
                     * is that you can set display == True and see what's going on
                     */
                    #include 
                    #include "lsst/utils/Utils.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/daf/base.h"
                    #include "lsst/afw/detection.h"
                    #include "lsst/afw/image.h"
                    #include "lsst/afw/math.h"
                    #include "lsst/afw/geom.h"
                    
                    
                    #include "testSpatialCell.h"
                    
                    namespace afwDetect = lsst::afw::detection;
                    namespace afwImage = lsst::afw::image;
                    namespace afwMath = lsst::afw::math;
                    namespace afwGeom = lsst::afw::geom;
                    typedef float PixelT;
                    
                    std::pair::Ptr, PTR(afwDetect::FootprintSet)> readImage();
                    
                    /************************************************************************************************************/
                    /*
                     * A demonstration of the use of a SpatialCellSet
                     */
                    void SpatialCellSetDemo() {
                        afwImage::MaskedImage::Ptr im;
                        PTR(afwDetect::FootprintSet) fs;
                        boost::tie(im, fs) = readImage();
                        /*
                         * Create an (empty) SpatialCellSet
                         */
                        afwMath::SpatialCellSet cellSet(
    
    59 a754418c - im->getBBox(afwImage::PARENT),
    59 93994d54 + im->getBBox(),
    260, 200 ); /* * Populate the cellSet using the detected object in the FootprintSet */ for (afwDetect::FootprintSet::FootprintList::iterator ptr = fs->getFootprints()->begin(), end = fs->getFootprints()->end(); ptr != end; ++ptr) { afwGeom::Box2I const bbox = (*ptr)->getBBox(); float const xc = (bbox.getMinX() + bbox.getMaxX())/2.0; float const yc = (bbox.getMinY() + bbox.getMaxY())/2.0; ExampleCandidate::Ptr tc(new ExampleCandidate(xc, yc, im, bbox)); cellSet.insertCandidate(tc); } /* * OK, the SpatialCellList is populated. Let's do something with it */ ExampleCandidateVisitor visitor; cellSet.visitCandidates(&visitor); std::cout << boost::format("There are %d candidates\n") % visitor.getN(); /* * Now label too-small object as BAD */ for (unsigned int i = 0; i != cellSet.getCellList().size(); ++i) { afwMath::SpatialCell::Ptr cell = cellSet.getCellList()[i]; for (afwMath::SpatialCell::iterator candidate = cell->begin(), candidateEnd = cell->end(); candidate != candidateEnd; ++candidate) { afwGeom::Box2I box = dynamic_cast((*candidate).get())->getBBox(); #if 0 std::cout << boost::format("%d %5.2f %5.2f %d\n") % i % (*candidate)->getXCenter() % (*candidate)->getYCenter() % (w*h); #endif if (box.getArea() < 75) { (*candidate)->setStatus(afwMath::SpatialCellCandidate::BAD); } } } /* * Now count the good and bad candidates */ for (unsigned int i = 0; i != cellSet.getCellList().size(); ++i) { afwMath::SpatialCell::Ptr cell = cellSet.getCellList()[i]; cell->visitCandidates(&visitor); cell->setIgnoreBad(false); // include BAD in cell.size() std::cout << boost::format("%s nobj=%d N_good=%d NPix_good=%d\n") % cell->getLabel() % cell->size() % visitor.getN() % visitor.getNPix(); } cellSet.setIgnoreBad(true); // don't visit BAD candidates cellSet.visitCandidates(&visitor); std::cout << boost::format("There are %d good candidates\n") % visitor.getN(); } /* * Read an image and background subtract it */ std::pair::Ptr, PTR(afwDetect::FootprintSet)> readImage() { afwImage::MaskedImage::Ptr mi; try {
    125 b19da1e0 - std::string dataDir = lsst::utils::eups::productDir("afwdata");
    ? ^^^^^^^^^^ ^
    125 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
    ? + ^^^ ^^^^ std::string filename = dataDir + "/CFHT/D4/cal-53535-i-797722_1.fits"; afwGeom::Box2I bbox = afwGeom::Box2I( afwGeom::Point2I(270, 2530), afwGeom::Extent2I(512, 512) ); lsst::daf::base::PropertySet::Ptr md; mi.reset(new afwImage::MaskedImage(filename, md, bbox));
    137 b19da1e0 - } catch (lsst::pex::exceptions::NotFoundException &e) {
    ? ^^^^^^ ^
    137 21597d88 + } catch (lsst::pex::exceptions::NotFoundError &e) {
    ? ^^ ^ std::cerr << e << std::endl; exit(1); } /* * Subtract the background. We can't fix those pesky cosmic rays, as that's in a dependent product * (meas/algorithms) */ afwMath::BackgroundControl bctrl(afwMath::Interpolate::NATURAL_SPLINE); bctrl.setNxSample(mi->getWidth()/256 + 1); bctrl.setNySample(mi->getHeight()/256 + 1); bctrl.getStatisticsControl()->setNumSigmaClip(3.0); bctrl.getStatisticsControl()->setNumIter(2); afwImage::Image::Ptr im = mi->getImage(); try { *mi->getImage() -= *afwMath::makeBackground(*im, bctrl)->getImage(); } catch(std::exception &) { bctrl.setInterpStyle(afwMath::Interpolate::CONSTANT); *mi->getImage() -= *afwMath::makeBackground(*im, bctrl)->getImage(); } /* * Find sources */ afwDetect::Threshold threshold(5, afwDetect::Threshold::STDEV); int npixMin = 5; // we didn't smooth PTR(afwDetect::FootprintSet) fs(new afwDetect::FootprintSet(*mi, threshold, "DETECTED", npixMin)); int const grow = 1; bool const isotropic = false; PTR(afwDetect::FootprintSet) grownFs(new afwDetect::FootprintSet(*fs, grow, isotropic)); grownFs->setMask(mi->getMask(), "DETECTED"); return std::make_pair(mi, grownFs); } //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- /* * Run the example */ int main() { std::pair::Ptr, PTR(afwDetect::FootprintSet)> data = readImage(); assert (data.first != NULL); // stop compiler complaining about data being unused SpatialCellSetDemo(); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    a754418c

    commit a754418c1a518efba1baeab39ffbdaf2718edae8
    Author: Andy Becker 
    Date:   Mon Feb 27 10:22:58 2012 -0800
    
        Bug in coordinate system of Bbox.
    

    b19da1e0

    commit b19da1e0b23c5e44a2f5a8b372eb20fff27082ea
    Author: rhl 
    Date:   Fri Jan 1 16:34:27 2010 +0000
    
        Support SpatialCellSet.setIgnoreBad()
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    tests/warper.py

    Diff:

    1 93d69929 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """Basic test of Warp (the warping algorithm is thoroughly tested in lsst.afw.math) """ import os import unittest import warnings
    30 7cbb2bb9 + import lsst.utils
    29 93d69929 - import numpy
    30 93d69929 -
    31 93d69929 - import eups
    import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.image.utils as imageUtils import lsst.afw.image.testUtils as imageTestUtils import lsst.afw.math as afwMath import lsst.utils.tests as utilsTests import lsst.pex.logging as pexLog import lsst.pex.policy as pexPolicy VERBOSITY = 0 # increase to see trace pexLog.Debug("lsst.afw.math", VERBOSITY)
    45 02abeb98 - dataDir = os.path.join(eups.productDir("afwdata"), "data")
    46 93d69929 - if dataDir == None:
    44 7cbb2bb9 + try:
    45 7cbb2bb9 + afwDataDir = lsst.utils.getPackageDir("afwdata")
    46 7cbb2bb9 + except Exception:
    warnings.warn("skipping all tests because afwdata is not setup")
    48 93994d54 + dataDir = None
    else:
    50 93994d54 + dataDir = os.path.join(afwDataDir, "data")
    originalExposureName = "medexp.fits" originalExposurePath = os.path.join(dataDir, originalExposureName) subExposureName = "medsub.fits" subExposurePath = os.path.join(dataDir, originalExposureName) originalFullExposureName = os.path.join("CFHT", "D4", "cal-53535-i-797722_1.fits") originalFullExposurePath = os.path.join(dataDir, originalFullExposureName) class WarpExposureTestCase(unittest.TestCase): """Test case for Warp """ def testMatchSwarpLanczos2Exposure(self): """Test that warpExposure matches swarp using a lanczos2 warping kernel. """ self.compareToSwarp("lanczos2") def testMatchSwarpLanczos2SubExposure(self): """Test that warpExposure matches swarp using a lanczos2 warping kernel with a subexposure """ for useDeepCopy in (False, True): self.compareToSwarp("lanczos2", useSubregion=True, useDeepCopy=useDeepCopy) def testBBox(self): """Test that the default bounding box includes all warped pixels """ kernelName = "lanczos2" warper = afwMath.Warper(kernelName) originalExposure, swarpedImage, swarpedWcs = self.getSwarpedImage( kernelName=kernelName, useSubregion=True, useDeepCopy=False) filterPolicyFile = pexPolicy.DefaultPolicyFile("afw", "SdssFilters.paf", "tests") filterPolicy = pexPolicy.Policy.createPolicy(filterPolicyFile, filterPolicyFile.getRepositoryPath(), True) imageUtils.defineFiltersFromPolicy(filterPolicy, reset=True) originalFilter = afwImage.Filter("i") originalCalib = afwImage.Calib() originalCalib.setFluxMag0(1.0e5, 1.0e3) originalExposure.setFilter(originalFilter) originalExposure.setCalib(originalCalib) warpedExposure1 = warper.warpExposure(destWcs=swarpedWcs, srcExposure=originalExposure) # the default size must include all good pixels, so growing the bbox should not add any warpedExposure2 = warper.warpExposure(destWcs=swarpedWcs, srcExposure=originalExposure, border=1) # a bit of excess border is allowed, but surely not as much as 10 (in fact it is approx. 5) warpedExposure3 = warper.warpExposure(destWcs=swarpedWcs, srcExposure=originalExposure, border=-10) # assert that warpedExposure and warpedExposure2 have the same number of non-edge pixels # and that warpedExposure3 has fewer
    95 f76e1b8b - edgeMask = 1 << afwImage.MaskU.getMaskPlane("NO_DATA")
    ? ^^^ ^^^
    97 93d69929 + edgeMask = 1 << afwImage.MaskU.getMaskPlane("EDGE")
    ? ^ ^^ mask1Arr = warpedExposure1.getMaskedImage().getMask().getArray() mask2Arr = warpedExposure2.getMaskedImage().getMask().getArray() mask3Arr = warpedExposure3.getMaskedImage().getMask().getArray() nGood1 = (mask1Arr & edgeMask == 0).sum() nGood2 = (mask2Arr & edgeMask == 0).sum() nGood3 = (mask3Arr & edgeMask == 0).sum() self.assertEqual(nGood1, nGood2) self.assertTrue(nGood3 < nGood1) self.assertEquals(warpedExposure1.getFilter().getName(), originalFilter.getName()) self.assertEquals(warpedExposure1.getCalib().getFluxMag0(), originalCalib.getFluxMag0()) def testDestBBox(self): """Test that the destBBox argument works """ kernelName = "lanczos2" warper = afwMath.Warper(kernelName) originalExposure, swarpedImage, swarpedWcs = self.getSwarpedImage( kernelName=kernelName, useSubregion=True, useDeepCopy=False) bbox = afwGeom.Box2I(afwGeom.Point2I(100, 25), afwGeom.Extent2I(3, 7)) warpedExposure = warper.warpExposure( destWcs = swarpedWcs, srcExposure = originalExposure, destBBox = bbox, border = -2, # should be ignored maxBBox = afwGeom.Box2I(afwGeom.Point2I(1, 2), afwGeom.Extent2I(8, 9)), # should be ignored ) self.assertTrue(bbox == warpedExposure.getBBox(afwImage.PARENT)) def getSwarpedImage(self, kernelName, useSubregion=False, useDeepCopy=False): """ Inputs: - kernelName: name of kernel in the form used by afwImage.makeKernel - useSubregion: if True then the original source exposure (from which the usual test exposure was extracted) is read and the correct subregion extracted - useDeepCopy: if True then the copy of the subimage is a deep copy, else it is a shallow copy; ignored if useSubregion is False Returns: - originalExposure - swarpedImage - swarpedWcs """ if useSubregion: originalFullExposure = afwImage.ExposureF(originalExposurePath) # "medsub" is a subregion of med starting at 0-indexed pixel (40, 150) of size 145 x 200 bbox = afwGeom.Box2I(afwGeom.Point2I(40, 150), afwGeom.Extent2I(145, 200)) originalExposure = afwImage.ExposureF(originalFullExposure, bbox, useDeepCopy) swarpedImageName = "medsubswarp1%s.fits" % (kernelName,) else: originalExposure = afwImage.ExposureF(originalExposurePath) swarpedImageName = "medswarp1%s.fits" % (kernelName,) swarpedImagePath = os.path.join(dataDir, swarpedImageName) swarpedDecoratedImage = afwImage.DecoratedImageF(swarpedImagePath) swarpedImage = swarpedDecoratedImage.getImage() swarpedMetadata = swarpedDecoratedImage.getMetadata() swarpedWcs = afwImage.makeWcs(swarpedMetadata) return (originalExposure, swarpedImage, swarpedWcs) def compareToSwarp(self, kernelName, useSubregion=False, useDeepCopy=False, interpLength=10, cacheSize=100000, rtol=4e-05, atol=1e-2): """Compare warpExposure to swarp for given warping kernel. Note that swarp only warps the image plane, so only test that plane. Inputs: - kernelName: name of kernel in the form used by afwImage.makeKernel - useSubregion: if True then the original source exposure (from which the usual test exposure was extracted) is read and the correct subregion extracted - useDeepCopy: if True then the copy of the subimage is a deep copy, else it is a shallow copy; ignored if useSubregion is False - interpLength: interpLength argument for lsst.afw.math.warpExposure - cacheSize: cacheSize argument for lsst.afw.math.SeparableKernel.computeCache; 0 disables the cache 10000 gives some speed improvement but less accurate results (atol must be increased) 100000 gives better accuracy but no speed improvement in this test - rtol: relative tolerance as used by numpy.allclose - atol: absolute tolerance as used by numpy.allclose """ warper = afwMath.Warper(kernelName) originalExposure, swarpedImage, swarpedWcs = self.getSwarpedImage( kernelName=kernelName, useSubregion=useSubregion, useDeepCopy=useDeepCopy) maxBBox = afwGeom.Box2I( afwGeom.Point2I(swarpedImage.getX0(), swarpedImage.getY0()), afwGeom.Extent2I(swarpedImage.getWidth(), swarpedImage.getHeight()))
    186 93d69929 - # path for saved afw-warped image
    187 93d69929 - afwWarpedImagePath = "afwWarpedExposure1%s" % (kernelName,)
    # warning: this test assumes that the swarped image is smaller than it needs to be # to hold all of the warped pixels afwWarpedExposure = warper.warpExposure( destWcs = swarpedWcs, srcExposure = originalExposure, maxBBox = maxBBox, ) afwWarpedMaskedImage = afwWarpedExposure.getMaskedImage() afwWarpedMask = afwWarpedMaskedImage.getMask()
    199 f76e1b8b - edgeBitMask = afwWarpedMask.getPlaneBitMask("NO_DATA")
    ? ^^^ ^^^
    199 93d69929 + edgeBitMask = afwWarpedMask.getPlaneBitMask("EDGE")
    ? ^ ^^ if edgeBitMask == 0:
    201 f76e1b8b - self.fail("warped mask has no NO_DATA bit")
    ? ^^^ ^^^
    201 93d69929 + self.fail("warped mask has no EDGE bit")
    ? ^ ^^ afwWarpedImagArr = afwWarpedMaskedImage.getImage().getArray() afwWarpedMaskArr = afwWarpedMaskedImage.getMask().getArray()
    204 93d69929 -
    205 93d69929 - swarpedImageArr = swarpedImage.getArray()
    errStr = imageTestUtils.imagesDiffer(afwWarpedImagArr, swarpedImage.getArray(), skipMaskArr=afwWarpedMaskArr, rtol=rtol, atol=atol) if errStr: self.fail("afw and swarp %s-warped %s (ignoring bad pixels)" % (kernelName, errStr)) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """ Returns a suite containing all the test cases in this module. """ utilsTests.init() suites = [] suites += unittest.makeSuite(WarpExposureTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(doExit=False): """Run the tests""" if dataDir == None: return utilsTests.run(suite(), doExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f76e1b8b

    commit f76e1b8b233d1ae63f78ed29d2ad01b9b4b9be59
    Author: Paul Price 
    Date:   Thu May 22 15:03:31 2014 -0400
    
        tests: update warping to check new NO_DATA mask bit
        
        NO_DATA is now used in warping instead of EDGE.
    

    93d69929

    commit 93d69929172539e2c698b13759a6c6fdaa33b56b
    Author: rowen 
    Date:   Tue Mar 15 21:04:17 2011 +0000
    
        Move coadd_utils Warp here as afwMath.Warper
    

    02abeb98

    commit 02abeb988c388979f57dcda970fa14ccef0288ac
    Author: Paul Price 
    Date:   Fri Nov 18 17:06:39 2011 -0500
    
        Changed image directory.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    93d69929

    commit 93d69929172539e2c698b13759a6c6fdaa33b56b
    Author: rowen 
    Date:   Tue Mar 15 21:04:17 2011 +0000
    
        Move coadd_utils Warp here as afwMath.Warper
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/image/ImageSlice.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file ImageSlice.cc
                     * @brief Provide functions to operate on rows/columns of images
                     * @author Steve Bickerton
                     */
                    #include 
                    #include "boost/shared_ptr.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/image/ImageSlice.h"
                    
                    namespace afwImage      = lsst::afw::image;
                    namespace afwMath       = lsst::afw::math;
                    namespace ex            = lsst::pex::exceptions;
                    
                    
                    /**
                     * @brief Constructor for ImageSlice
                     *
                     */
                    template
                    afwImage::ImageSlice::ImageSlice(
                        image::Image const &img ///< The image to represent as a slice.
                                                            ) : 
                        afwImage::Image(img),
                        _sliceType(ROW)
                    {
                    
                        // verify the img is a slice (row or column)
                        if (img.getWidth() != 1 && img.getHeight() != 1) {
    
    55 418deefa - throw LSST_EXCEPT(ex::OutOfRangeException, "Input image must be a slice (width or height == 1)");
    ? ^^^^^^ ^
    55 21597d88 + throw LSST_EXCEPT(ex::OutOfRangeError, "Input image must be a slice (width or height == 1)");
    ? ^^ ^ } else if (img.getWidth() == 1 && img.getHeight() == 1) {
    57 418deefa - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    57 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "1x1 image ambiguous (could be row or column). " "Perhaps a constant would be better than a slice? "); } else if (img.getWidth() == 1 && img.getHeight() != 1) { _sliceType = COLUMN; } else if (img.getHeight() == 1 && img.getWidth() != 1) { _sliceType = ROW; } // what about 1xn images where a 1x1 row slice is desired? ... use a constant instead of a slice // what about nx1 images wehre a 1x1 column slice is desired? ... use a constant instead of a slice } /************************************************************************** * * column operators * **************************************************************************/ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // overload + /** * @brief Overload operator+() * * We require two of these, one for image+slice (this one) and one for slice+image (next one down) */ template typename afwImage::Image::Ptr afwImage::operator+( afwImage::Image const &img, ///< The Image afwImage::ImageSlice const &slc ///< The ImageSlice ) { typename afwImage::Image::Ptr retImg(new afwImage::Image(img, true)); *retImg += slc; return retImg; } /** * @brief Overload operator+() * * We require two of these, one for image+slice (previous one) and one for slice+image (this) */ template typename afwImage::Image::Ptr afwImage::operator+( afwImage::ImageSlice const &slc, ///< The ImageSlice afwImage::Image const &img ///< The Image ) { return afwImage::operator+(img, slc); } /** * @brief Overload operator+=() * * We'll only allow 'image += slice'. It doesn't make sense to add an image to a slice. */ template void afwImage::operator+=( afwImage::Image &img, ///< The Image afwImage::ImageSlice const &slc ///< The ImageSlice ) { afwImage::details::operate >(img, slc, slc.getImageSliceType()); } // ----------------------------------------------------------------- // overload - /** * @brief Overload operator-() * * We'll only allow 'image - slice', as 'slice - image' doesn't make sense. */ template typename afwImage::Image::Ptr afwImage::operator-( afwImage::Image const &img, ///< The Image afwImage::ImageSlice const &slc ///< The ImageSlice ) { typename afwImage::Image::Ptr retImg(new afwImage::Image(img, true)); *retImg -= slc; return retImg; } /** * @brief Overload operator-=() * * Only 'image -= slice' is defined. 'slice -= image' wouldn't make sense. */ template void afwImage::operator-=( afwImage::Image &img, ///< The Image afwImage::ImageSlice const &slc ///< The ImageSlice ) { details::operate >(img, slc, slc.getImageSliceType()); } // ****************************************************************** // overload * /** * @brief Overload operator*() * * We'll define both 'image*slice' (this one) and 'slice*image' (next one down). */ template typename afwImage::Image::Ptr afwImage::operator*( afwImage::Image const &img, ///< The Image afwImage::ImageSlice const &slc ///< The ImageSlice ) { typename afwImage::Image::Ptr retImg(new afwImage::Image(img, true)); *retImg *= slc; return retImg; } /** * @brief Overload operator*() * * We'll define both 'image*slice' (this one) and 'slice*image' (next one down). */ template typename afwImage::Image::Ptr afwImage::operator*( afwImage::ImageSlice const &slc, ///< The Image afwImage::Image const &img ///< The ImageSlice ) { return afwImage::operator*(img, slc); } /** * @brief Overload operator*=() * * Only 'image *= slice' is defined, as 'slice *= image' doesn't make sense. */ template void afwImage::operator*=( afwImage::Image &img, ///< The Image afwImage::ImageSlice const &slc ///< The ImageSlice ) { details::operate >(img, slc, slc.getImageSliceType()); } // /////////////////////////////////////////////////////////////////// // overload / /** * @brief Overload operator/() * * Only 'image / slice' is defined, as 'slice / image' doesn't make sense. */ template typename afwImage::Image::Ptr afwImage::operator/( afwImage::Image const &img, ///< The Image afwImage::ImageSlice const &slc ///< The ImageSlice ) { typename afwImage::Image::Ptr retImg(new afwImage::Image(img, true)); *retImg /= slc; return retImg; } /** * @brief Overload operator/=() * * Only 'image /= slice' is defined, as 'slice /= image' doesn't make sense. */ template void afwImage::operator/=( afwImage::Image &img, ///< The Image afwImage::ImageSlice const &slc ///< The ImageSlice ) { details::operate >(img, slc, slc.getImageSliceType()); } /* * Explicit Instantiations * */ /// \cond #define INSTANTIATE_SLICE_OP_SYM(TYPE, OP) \ template afwImage::Image::Ptr afwImage::operator OP(afwImage::Image const &img, \ afwImage::ImageSlice const &slc); \ template afwImage::Image::Ptr afwImage::operator OP(afwImage::ImageSlice const &slc, \ afwImage::Image const &img) #define INSTANTIATE_SLICE_OP_ASYM(TYPE, OP) \ template afwImage::Image::Ptr afwImage::operator OP(afwImage::Image const &img, \ afwImage::ImageSlice const &slc) #define INSTANTIATE_SLICE_OPEQ(TYPE, OP) \ template void afwImage::operator OP(afwImage::Image &img, \ afwImage::ImageSlice const &slc) #define INSTANTIATE_SLICES(TYPE) \ template afwImage::ImageSlice::ImageSlice(afwImage::Image const &image); \ INSTANTIATE_SLICE_OP_SYM(TYPE, +); \ INSTANTIATE_SLICE_OP_ASYM(TYPE, -); \ INSTANTIATE_SLICE_OP_SYM(TYPE, *); \ INSTANTIATE_SLICE_OP_ASYM(TYPE, /); \ INSTANTIATE_SLICE_OPEQ(TYPE, +=); \ INSTANTIATE_SLICE_OPEQ(TYPE, -=); \ INSTANTIATE_SLICE_OPEQ(TYPE, *=); \ INSTANTIATE_SLICE_OPEQ(TYPE, /=) INSTANTIATE_SLICES(double); INSTANTIATE_SLICES(float); /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    418deefa

    commit 418deefa69b3779ea56d07bfc517ece075932b89
    Author: bick 
    Date:   Tue Apr 13 00:08:13 2010 +0000
    
        #1135 Added doxygen, cleaned-up to conform to style.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/math/detail/KernelImagesForRegion.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file
                     *
                     * @brief Definition of KernelImagesForRegion class declared in detail/ConvolveImage.h
                     *
                     * @author Russell Owen
                     *
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/assign/list_of.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/image/ImageUtils.h"
                    #include "lsst/afw/math/detail/Convolve.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace pexLog = lsst::pex::logging;
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwImage = lsst::afw::image;
                    namespace mathDetail = lsst::afw::math::detail;
                    
                    /**
                     * Construct a KernelImagesForRegion
                     *
    
    57 d7d666c2 - * @throw lsst::pex::exceptions::InvalidParameterException if kernelPtr is null
    ? ^^^^^^ ^
    57 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernelPtr is null
    ? ^^ ^ */ mathDetail::KernelImagesForRegion::KernelImagesForRegion( KernelConstPtr kernelPtr, ///< kernel lsst::afw::geom::Box2I const &bbox, ///< bounding box of region of an image ///< for which we want to compute kernel images ///< (inclusive and relative to parent image) lsst::afw::geom::Point2I const &xy0, ///< xy0 of image for which we want to compute kernel images bool doNormalize) ///< normalize the kernel images? : lsst::daf::base::Citizen(typeid(this)), _kernelPtr(kernelPtr), _bbox(bbox), _xy0(xy0), _doNormalize(doNormalize), _imagePtrList(4) { if (!_kernelPtr) {
    75 d7d666c2 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "kernelPtr is null");
    ? ^^^^^^ ^
    75 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "kernelPtr is null");
    ? ^^ ^ } pexLog::TTrace<6>("lsst.afw.math.convolve", "KernelImagesForRegion(bbox(minimum=(%d, %d), extent=(%d, %d)), xy0=(%d, %d), doNormalize=%d, images...)", _bbox.getMinX(), _bbox.getMinY(), _bbox.getWidth(), _bbox.getHeight(), _xy0[0], _xy0[1], _doNormalize); } /** * Construct a KernelImagesForRegion with some or all corner images * * Null corner image pointers are ignored. * * @warning: if any images are incorrect you will get a mess. *
    89 d7d666c2 - * @throw lsst::pex::exceptions::InvalidParameterException if kernelPtr is null
    ? ^^^^^^ ^
    89 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernelPtr is null
    ? ^^ ^
    90 d7d666c2 - * @throw lsst::pex::exceptions::InvalidParameterException if an image has the wrong dimensions
    ? ^^^^^^ ^
    90 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if an image has the wrong dimensions
    ? ^^ ^ */ mathDetail::KernelImagesForRegion::KernelImagesForRegion( KernelConstPtr const kernelPtr, ///< kernel lsst::afw::geom::Box2I const &bbox, ///< bounding box of region of an image ///< for which we want to compute kernel images ///< (inclusive and relative to parent image) lsst::afw::geom::Point2I const &xy0, ///< xy0 of image bool doNormalize, ///< normalize the kernel images? ImagePtr bottomLeftImagePtr, ///< kernel image and sum at bottom left of region ImagePtr bottomRightImagePtr, ///< kernel image and sum at bottom right of region ImagePtr topLeftImagePtr, ///< kernel image and sum at top left of region ImagePtr topRightImagePtr) ///< kernel image and sum at top right of region : lsst::daf::base::Citizen(typeid(this)), _kernelPtr(kernelPtr), _bbox(bbox), _xy0(xy0), _doNormalize(doNormalize), _imagePtrList(4) { if (!_kernelPtr) {
    112 d7d666c2 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "kernelPtr is null");
    ? ^^^^^^ ^
    112 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "kernelPtr is null");
    ? ^^ ^ } _insertImage(BOTTOM_LEFT, bottomLeftImagePtr); _insertImage(BOTTOM_RIGHT, bottomRightImagePtr); _insertImage(TOP_LEFT, topLeftImagePtr); _insertImage(TOP_RIGHT, topRightImagePtr); pexLog::TTrace<6>("lsst.afw.math.convolve", "KernelImagesForRegion(bbox(minimum=(%d, %d), extent=(%d, %d)), xy0=(%d, %d), doNormalize=%d, images...)", _bbox.getMinX(), _bbox.getMinY(), _bbox.getWidth(), _bbox.getHeight(), _xy0[0], _xy0[1], _doNormalize); } /** * Return the image and sum at the specified location * * If the image has not yet been computed, it is computed at this time. */ mathDetail::KernelImagesForRegion::ImagePtr mathDetail::KernelImagesForRegion::getImage( Location location) ///< location of image const { if (_imagePtrList[location]) { return _imagePtrList[location]; } ImagePtr imagePtr(new Image(_kernelPtr->getDimensions())); _imagePtrList[location] = imagePtr; _computeImage(location); return imagePtr; } /** * Compute pixel index of a given location, relative to the parent image * (thus offset by bottom left corner of bounding box) */ lsst::afw::geom::Point2I mathDetail::KernelImagesForRegion::getPixelIndex( Location location) ///< location for which to return pixel index const { switch (location) { case BOTTOM_LEFT: return _bbox.getMin(); break; // paranoia case BOTTOM_RIGHT: return afwGeom::Point2I(_bbox.getMaxX() + 1, _bbox.getMinY()); break; // paranoia case TOP_LEFT: return afwGeom::Point2I(_bbox.getMinX(), _bbox.getMaxY() + 1); break; // paranoia case TOP_RIGHT: return afwGeom::Point2I(_bbox.getMaxX() + 1, _bbox.getMaxY() + 1); break; // paranoia default: { std::ostringstream os; os << "Bug: unhandled location = " << location;
    164 d5c921da - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    164 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } } } /** * @brief Compute next row of subregions * * For the first row call with a new RowOfKernelImagesForRegion (with the desired number of columns and rows). * Every subequent call updates the data in the RowOfKernelImagesForRegion. * * @return true if a new row was computed, false if supplied RowOfKernelImagesForRegion is for the last row. */ bool mathDetail::KernelImagesForRegion::computeNextRow( RowOfKernelImagesForRegion ®ionRow) ///< RowOfKernelImagesForRegion object const { if (regionRow.isLastRow()) { return false; } bool hasData = regionRow.hasData(); int startY; if (hasData) { startY = regionRow.front()->getBBox().getMaxY() + 1; } else { startY = this->_bbox.getMinY(); } int yInd = regionRow.incrYInd(); int remHeight = 1 + this->_bbox.getMaxY() - startY; int remYDiv = regionRow.getNY() - yInd; int height = _computeNextSubregionLength(remHeight, remYDiv); if (hasData) { // Move each region up one segment bool isFirst = true; for (RowOfKernelImagesForRegion::Iterator rgnIter = regionRow.begin(), rgnEnd = regionRow.end(); rgnIter != rgnEnd; ++rgnIter) { (*rgnIter)->_moveUp(isFirst, height); isFirst = false; } } else { ImagePtr blImagePtr = getImage(BOTTOM_LEFT); ImagePtr brImagePtr; ImagePtr tlImagePtr; ImagePtr const trImageNullPtr; afwGeom::Point2I blCorner = afwGeom::Point2I(this->_bbox.getMinX(), startY); int remWidth = this->_bbox.getWidth(); int remXDiv = regionRow.getNX(); for (RowOfKernelImagesForRegion::Iterator rgnIter = regionRow.begin(), rgnEnd = regionRow.end(); rgnIter != rgnEnd; ++rgnIter) { int width = _computeNextSubregionLength(remWidth, remXDiv); --remXDiv; remWidth -= width; KernelImagesForRegion::Ptr regionPtr(new KernelImagesForRegion( _kernelPtr, afwGeom::Box2I(blCorner, afwGeom::Extent2I(width, height)), _xy0, _doNormalize, blImagePtr, brImagePtr, tlImagePtr, trImageNullPtr)); *rgnIter = regionPtr; if (!tlImagePtr) { regionPtr->getImage(TOP_LEFT); } blCorner += afwGeom::Extent2I(width, 0); blImagePtr = regionPtr->getImage(BOTTOM_RIGHT); tlImagePtr = regionPtr->getImage(TOP_RIGHT); } } return true; } /** * Compute image at a particular location *
    248 eae9ad17 - * @throw lsst::pex::exceptions::NotFoundException if there is no pointer at that location
    ? ^^^^^^ ^
    248 21597d88 + * @throw lsst::pex::exceptions::NotFoundError if there is no pointer at that location
    ? ^^ ^ */ void mathDetail::KernelImagesForRegion::_computeImage(Location location) const { ImagePtr imagePtr = _imagePtrList[location]; if (!imagePtr) { std::ostringstream os; os << "Null imagePtr at location " << location;
    255 eae9ad17 - throw LSST_EXCEPT(pexExcept::NotFoundException, os.str());
    ? ^^^^^^ ^
    255 21597d88 + throw LSST_EXCEPT(pexExcept::NotFoundError, os.str());
    ? ^^ ^ } afwGeom::Point2I pixelIndex = getPixelIndex(location); _kernelPtr->computeImage( *imagePtr, _doNormalize, afwImage::indexToPosition(pixelIndex.getX() + _xy0[0]), afwImage::indexToPosition(pixelIndex.getY() + _xy0[1])); } /** * Compute length of each subregion for a region divided into nDivisions pieces of approximately equal * length. * * @return a list of subspan lengths *
    272 d7d666c2 - * @throw lsst::pex::exceptions::InvalidParameterException if nDivisions >= length
    ? ^^^^^^ ^
    272 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if nDivisions >= length
    ? ^^ ^ */ std::vector mathDetail::KernelImagesForRegion::_computeSubregionLengths( int length, ///< length of region int nDivisions) ///< number of divisions of region { if ((nDivisions > length) || (nDivisions < 1)) { std::ostringstream os; os << "nDivisions = " << nDivisions << " not in range [1, " << length << " = length]";
    281 d7d666c2 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    281 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } std::vector regionLengths; int remLength = length; for (int remNDiv = nDivisions; remNDiv > 0; --remNDiv) { int subLength = _computeNextSubregionLength(remLength, remNDiv); if (subLength < 1) { std::ostringstream os; os << "Bug! _computeSubregionLengths(length=" << length << ", nDivisions=" << nDivisions << ") computed sublength = " << subLength << " < 0; remLength = " << remLength;
    291 f379c09e - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, os.str());
    ? ---------
    291 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, os.str());
    } regionLengths.push_back(subLength); remLength -= subLength; } return regionLengths; } /** * @brief Move the region up one segment * * To avoid reallocating memory for kernel images, swap the top and bottom kernel image pointers * and recompute the top images. Actually, only does this to the right-hande images if isFirst is false * since it assumes the left images were already handled. * * Intended to support computeNextRow; as such assumes that a list of adjacent regions will be moved, * left to right. */ void mathDetail::KernelImagesForRegion::_moveUp( bool isFirst, ///< true if the first region in a row (or the only region you are moving) int newHeight) ///< new height of region { // move bbox up (this must be done before recomputing the top kernel images) _bbox = afwGeom::Box2I( afwGeom::Point2I(_bbox.getMinX(), _bbox.getMaxY() + 1), afwGeom::Extent2I(_bbox.getWidth(), newHeight)); // swap top and bottom image pointers _imagePtrList[BOTTOM_RIGHT].swap(_imagePtrList[TOP_RIGHT]); _imagePtrList[BOTTOM_LEFT].swap(_imagePtrList[TOP_LEFT]); // recompute top right, and if the first image also recompute top left _computeImage(TOP_RIGHT); if (isFirst) { _computeImage(TOP_LEFT); } } int const mathDetail::KernelImagesForRegion::_MinInterpolationSize = 10; /** * @brief Construct a RowOfKernelImagesForRegion */ mathDetail::RowOfKernelImagesForRegion::RowOfKernelImagesForRegion( int nx, ///< number of columns int ny) ///< number of rows : _nx(nx), _ny(ny), _yInd(-1), _regionList(nx) { if ((nx < 1) || (ny < 1)) { std::ostringstream os; os << "nx = " << nx << " and/or ny = " << ny << " < 1";
    347 0280a694 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    347 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ }; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d7d666c2

    commit d7d666c2df0fb12062dc69c1390aa702949f8908
    Author: rowen 
    Date:   Wed Apr 21 22:11:17 2010 +0000
    
        Mostly implemented. Still to do:
        - wire the new code up to the convolve or basicConvolve functions
        - implement brute force convolution case in convolveRegionWithRecursiveInterpolation
        - swig the new code
        - unit tests
    

    eae9ad17

    commit eae9ad175a79abc17b9939be5beb520d5e90dc1f
    Author: rowen 
    Date:   Sat Oct 16 00:21:41 2010 +0000
    
        Merge ticket #1469: further convolution speedups
    

    0280a694

    commit 0280a694c6c68ad7bf74b03d97d79d6cb98f13a8
    Author: rowen 
    Date:   Tue Sep 14 23:20:35 2010 +0000
    
        Improved memory usage when convolving with interpolation
        by computing of one row of kernel image regions at a time.
    

    f379c09e

    commit f379c09e5740ba9587bb1efa400d64f410861f69
    Author: rowen 
    Date:   Fri May 14 16:36:52 2010 +0000
    
        It works. To do: re-enable all tests, etc. Test list of shared pointer to KernelImagesForRegion.
    

    d5c921da

    commit d5c921dacdba3ba77095a6b1b65859e3347e05f5
    Author: rowen 
    Date:   Wed May 12 16:54:36 2010 +0000
    
        Added many unit tests. Fixed a few bugs. Added some trace messages.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/header.py

    Diff:

    1 7b66fd0c - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008-2013 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import numpy import unittest
    28 7b66fd0c - import lsst.daf.base as dafBase
    import lsst.afw.image as afwImage import lsst.utils.tests as utilsTests #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class HeaderTestCase(unittest.TestCase): """Test that headers round-trip""" def testHeaders(self): filename = "tests/header.fits" header = {"STR": "String", "INT": 12345, "FLOAT": 678.9, "NAN": numpy.nan, "PLUSINF": numpy.inf, "MINUSINF": -numpy.inf, "LONG": long(987654321), } exp = afwImage.ExposureI(0,0) metadata = exp.getMetadata() for k,v in header.items(): metadata.add(k, v) exp.writeFits(filename) exp = afwImage.ExposureI(filename) metadata = exp.getMetadata() for k,v in header.items(): self.assertTrue(metadata.exists(k)) if isinstance(v, float) and numpy.isnan(v): self.assertTrue(isinstance(metadata.get(k), float)) self.assertTrue(numpy.isnan(metadata.get(k))) else: self.assertEqual(metadata.get(k), v) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(HeaderTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7b66fd0c

    commit 7b66fd0cc3be626d6a87fe2b1c11b7cf25099e15
    Author: Paul Price 
    Date:   Sat May 25 13:40:34 2013 -0400
    
        add test of NAN,Inf in header (#2900)
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    src/formatters/ImageFormatter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    /** @file
                     * @brief Implementation of ImageFormatter class
                     *
                     * @author $Author: ktlim $
                     * @version $Revision: 2151 $
                     * @date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * @ingroup afw
                     */
                    
                    #ifndef __GNUC__
                    #  define __attribute__(x) /*NOTHING*/
                    #endif
                    static char const* SVNid __attribute__((unused)) = "$Id$";
                    
                    #include "boost/scoped_ptr.hpp"
                    #include "boost/serialization/shared_ptr.hpp"
                    #include "boost/serialization/binary_object.hpp"
                    #include "boost/serialization/nvp.hpp"
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/formatters/ImageFormatter.h"
                    #include "lsst/afw/image/Image.h"
                    
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.ImageFormatter", level, s);
                    }
                    
                    using boost::serialization::make_nvp;
                    using lsst::daf::base::Persistable;
                    using lsst::daf::persistence::BoostStorage;
                    using lsst::daf::persistence::XmlStorage;
                    using lsst::daf::persistence::FitsStorage;
                    using lsst::daf::persistence::Storage;
                    using lsst::afw::image::Image;
                    
                    namespace afwImg = lsst::afw::image;
                    namespace afwGeom = lsst::afw::geom;
                    
                    namespace lsst {
                    namespace afw {
                    namespace formatters {
                    
                    template 
                    class ImageFormatterTraits {
                    public:
                        static std::string name();
                    };
                    
                    template<> std::string ImageFormatterTraits::name() {
                        static std::string name = "ImageU";
                        return name;
                    }
                    template<> std::string ImageFormatterTraits::name() {
                        static std::string name = "ImageI";
                        return name;
                    }
                    template<> std::string ImageFormatterTraits::name() {
                        static std::string name = "ImageF";
                        return name;
                    }
                    template<> std::string ImageFormatterTraits::name() {
                        static std::string name = "ImageD";
                        return name;
                    }
                    template<> std::string ImageFormatterTraits::name() {
                        static std::string name = "ImageL";
                        return name;
                    }
                    
                    template 
                    lsst::daf::persistence::FormatterRegistration ImageFormatter::registration(
                        ImageFormatterTraits::name(),
                        typeid(Image),
                        createInstance);
                    
                    template 
                    ImageFormatter::ImageFormatter(
                            lsst::pex::policy::Policy::Ptr
                                                               )
                        :
                        lsst::daf::persistence::Formatter(typeid(this))
                    {
                    }
                    
                    template 
                    ImageFormatter::~ImageFormatter(void)
                    {
                    }
                    
                    namespace {
                    namespace dafBase = lsst::daf::base;
                    namespace afwImage = lsst::afw::image;
                    }
                    
                    template 
                    void ImageFormatter::write(
                        Persistable const* persistable,
                        Storage::Ptr storage,
                        lsst::daf::base::PropertySet::Ptr) {
                    
                        execTrace("ImageFormatter write start");
                        Image const* ip = dynamic_cast const*>(persistable);
                        if (ip == 0) {
    
    141 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Persisting non-Image");
    ? ---------
    141 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Persisting non-Image");
    } if (typeid(*storage) == typeid(BoostStorage)) { execTrace("ImageFormatter write BoostStorage"); BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & *ip; execTrace("ImageFormatter write end"); return; } else if (typeid(*storage) == typeid(XmlStorage)) { execTrace("ImageFormatter write XmlStorage"); XmlStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & make_nvp("img", *ip); execTrace("ImageFormatter write end"); return; } else if (typeid(*storage) == typeid(FitsStorage)) { execTrace("ImageFormatter write FitsStorage"); FitsStorage* fits = dynamic_cast(storage.get()); typedef Image Image; ip->writeFits(fits->getPath()); // \todo Do something with these fields? // int _X0; // int _Y0; execTrace("ImageFormatter write end"); return; }
    169 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Image");
    ? ---------
    169 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Image");
    } template Persistable* ImageFormatter::read(Storage::Ptr storage, lsst::daf::base::PropertySet::Ptr additionalData) { execTrace("ImageFormatter read start"); if (typeid(*storage) == typeid(BoostStorage)) { execTrace("ImageFormatter read BoostStorage"); BoostStorage* boost = dynamic_cast(storage.get()); Image* ip = new Image; boost->getIArchive() & *ip; execTrace("ImageFormatter read end"); return ip; } else if (typeid(*storage) == typeid(XmlStorage)) { execTrace("ImageFormatter read XmlStorage"); XmlStorage* boost = dynamic_cast(storage.get()); Image* ip = new Image; boost->getIArchive() & make_nvp("img", *ip); execTrace("ImageFormatter read end"); return ip; } else if(typeid(*storage) == typeid(FitsStorage)) { execTrace("ImageFormatter read FitsStorage"); FitsStorage* fits = dynamic_cast(storage.get());
    196 3263f939 - afwImg::ImageOrigin origin = afwImg::LOCAL;
    197 3263f939 - if(additionalData->exists("imageOrigin")){
    198 3263f939 - std::string originStr = additionalData->get("imageOrigin");
    199 3263f939 - if(originStr == "LOCAL") {
    200 3263f939 - origin = afwImg::LOCAL;
    201 3263f939 - } else if (originStr == "PARENT") {
    202 3263f939 - origin = afwImg::PARENT;
    203 3263f939 - } else {
    204 3263f939 - throw LSST_EXCEPT(
    205 3263f939 - lsst::pex::exceptions::RuntimeErrorException,
    206 3263f939 - (boost::format("Unknown ImageOrigin type %s specified in additional"
    207 3263f939 - "data for retrieving Image from fits")%originStr
    208 3263f939 -
    209 3263f939 - ).str()
    210 3263f939 - );
    211 3263f939 - }
    212 3263f939 - }
    geom::Box2I box; if (additionalData->exists("llcX")) { int llcX = additionalData->get("llcX"); int llcY = additionalData->get("llcY"); int width = additionalData->get("width"); int height = additionalData->get("height"); box = geom::Box2I( geom::Point2I(llcX, llcY), geom::Extent2I(width, height) ); }
    207 93994d54 + afwImg::ImageOrigin origin = afwImg::PARENT;
    208 b4f73cbf + if (additionalData->exists("imageOrigin")) {
    209 3263f939 + std::string originStr = additionalData->get("imageOrigin");
    210 b4f73cbf + if (originStr == "LOCAL") {
    211 3263f939 + origin = afwImg::LOCAL;
    212 3263f939 + } else if (originStr == "PARENT") {
    213 3263f939 + origin = afwImg::PARENT;
    214 3263f939 + } else {
    215 3263f939 + throw LSST_EXCEPT(
    216 21597d88 + lsst::pex::exceptions::RuntimeError,
    217 3263f939 + (boost::format("Unknown ImageOrigin type %s specified in additional"
    218 3263f939 + "data for retrieving Image from fits")%originStr
    219 3263f939 +
    220 3263f939 + ).str()
    221 3263f939 + );
    222 3263f939 + }
    223 358154bc + }
    lsst::daf::base::PropertySet::Ptr metadata; Image* ip = new Image( fits->getPath(), fits->getHdu(), lsst::daf::base::PropertySet::Ptr(), box, origin ); // \note We're throwing away the metadata // \todo Do something with these fields? // int _X0; // int _Y0; execTrace("ImageFormatter read end"); return ip; }
    238 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Image");
    ? ---------
    238 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Image");
    } template void ImageFormatter::update( Persistable*, Storage::Ptr, lsst::daf::base::PropertySet::Ptr) {
    246 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unexpected call to update for Image");
    ? ---------
    246 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unexpected call to update for Image");
    } template template void ImageFormatter::delegateSerialize( Archive& ar, int const, Persistable* persistable) { execTrace("ImageFormatter delegateSerialize start"); Image* ip = dynamic_cast*>(persistable); if (ip == 0) {
    255 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Serializing non-Image");
    ? ---------
    255 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Serializing non-Image");
    } int width, height; if (Archive::is_saving::value) { width = ip->getWidth(); height = ip->getHeight(); } ar & make_nvp("width", width) & make_nvp("height", height); if (Archive::is_loading::value) { boost::scoped_ptr > ni( new Image(geom::Extent2I(width, height)) ); typename Image::Array array = ni->getArray(); ar & make_nvp("array", boost::serialization::make_array(array.getData(), array.getNumElements())); ip->swap(*ni); } else { ndarray::Array array = ndarray::dynamic_dimension_cast<2>(ip->getArray()); if(array.empty()) array = ndarray::copy(ip->getArray()); ar & make_nvp("array", boost::serialization::make_array(array.getData(), array.getNumElements())); } } template lsst::daf::persistence::Formatter::Ptr ImageFormatter::createInstance( lsst::pex::policy::Policy::Ptr policy) { return lsst::daf::persistence::Formatter::Ptr(new ImageFormatter(policy)); } #define InstantiateFormatter(ImagePixelT) \ template class ImageFormatter; \ template void ImageFormatter::delegateSerialize(boost::archive::text_oarchive&, int const, Persistable*); \ template void ImageFormatter::delegateSerialize(boost::archive::text_iarchive&, int const, Persistable*); \ template void ImageFormatter::delegateSerialize(boost::archive::xml_oarchive&, int const, Persistable*); \ template void ImageFormatter::delegateSerialize(boost::archive::xml_iarchive&, int const, Persistable*); \ template void ImageFormatter::delegateSerialize(boost::archive::binary_oarchive&, int const, Persistable*); \ template void ImageFormatter::delegateSerialize(boost::archive::binary_iarchive&, int const, Persistable*); InstantiateFormatter(boost::uint16_t); InstantiateFormatter(int); InstantiateFormatter(float); InstantiateFormatter(double); InstantiateFormatter(boost::uint64_t); #undef InstantiateSerializer }}} // namespace lsst::afw::formatters

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    358154bc

    commit 358154bc06d9433da4f0d0c06d6cf9a04f303c9a
    Author: ktlim 
    Date:   Thu Mar 19 17:35:13 2009 +0000
    
        Enable subimage extraction in the ImageFormatter.
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    b4f73cbf

    commit b4f73cbf3097165062c02aa04905ab10b06c6bec
    Author: Russell Owen 
    Date:   Mon Sep 8 16:05:52 2014 -0700
    
        First pass at DM-840
        Added UNDEFINED ImageOrigin enum value
        Made UNDEFINED the default for image constructors (which have lots of defaults,
        so I can't just delete the origin default).
        Eliminated the default value for ImageBase.getBBox.
        Modified all code that calls functions that accept an ImageOrigin argument to specify it explicitly.
    

    Return to list

    tests/image.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    //  -*- lsst-c++ -*-
                    #include 
                    #include 
                    #include 
                    
                    #define BOOST_TEST_DYN_LINK
                    #define BOOST_TEST_MODULE Image
                    
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/test/unit_test.hpp"
                    #pragma clang diagnostic pop
                    #include "boost/test/floating_point_comparison.hpp"
                    
                    #include "lsst/afw/image/MaskedImage.h"
                    
                    namespace image = lsst::afw::image;
                    namespace geom = lsst::afw::geom;
                    
                    using namespace std;
                    
                    typedef float PixelT;
                    typedef unsigned short MaskPixelT;
                    typedef image::Image ImageT;
                    typedef image::Mask MaskT;
                    
                    /************************************************************************************************************/
                    
                    template 
                    void y_gradient(ImageT & src, ImageT & dst) {
                        assert(src.getDimensions() == dst.getDimensions());
                    
                    #define CONST 0
                    #if CONST
                        typedef typename ImageT::const_xy_locator xyl;
                    #else
                        typedef typename ImageT::xy_locator xyl;
                    #endif
                        xyl src_loc = src.xy_at(0, 1);
                    
                    #define USE_CACHE_LOCATION 1
                    #if USE_CACHE_LOCATION
                        typename xyl::cached_location_t above = src_loc.cache_location(0,  1);
                        typename xyl::cached_location_t below = src_loc.cache_location(0, -1);
                    #endif
                    
                        for (int r = 1; r < src.getHeight() - 1; ++r) {
                            for (typename ImageT::x_iterator dst_it = dst.row_begin(r);
                                dst_it != dst.row_end(r); ++dst_it, ++src_loc.x()) {
                    #if USE_CACHE_LOCATION                  // this version is faster
                                (*dst_it) = (src_loc[above] - src_loc[below])/2;
                    #else  // but this is possible too, and more general (but slower)
                                *dst_it = (src_loc(0, 1) - src_loc(0, -1))/2;
                    #endif
                            }
                            
                            src_loc += std::make_pair(-src.getWidth(), 1);
                        }
                    }
                    
                    /************************************************************************************************************/
                    
                    #define PRINT_IMAGE 0
                    #if PRINT_IMAGE
                    namespace {
                        void printImage(ImageT const& img, string const& title="") {
                            if (title != "") {
                                cout << title << endl;
                            }
                            
                            for (int i = img.getHeight() - 1; i >= 0; --i) {
                                for (ImageT::x_iterator ptr = img.row_begin(i), end = img.row_end(i); ptr != end; ++ptr) {
                                    cout << *ptr << " ";
                                }
                                cout << endl;
                            }
                        }
                    }
                    #endif
                    
                    ImageT make_image(int const width=5, int const height=6) {
                        ImageT img(geom::Extent2I(width, height));
                    
                        int i = 0;
                        for (ImageT::iterator ptr = img.begin(), end = img.end(); ptr != end; ++ptr, ++i) {
                            *ptr = i/img.getWidth() + 100*(i%img.getWidth());
                        }
                    
                        return img;
                    }
                    
                    /************************************************************************************************************/
                    
                    BOOST_AUTO_TEST_CASE(getset0) { /* parasoft-suppress  LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */
                        ImageT img = make_image();
                    
                        image::CheckIndices docheck(true);
                        // operator() as getter
                        BOOST_CHECK_EQUAL(img(3,3), 303);
                        BOOST_CHECK_EQUAL(*(img.x_at(3,3)), 303);
                        BOOST_CHECK_EQUAL(img(3,3, docheck), 303);
                        BOOST_CHECK_EQUAL(img(3,4), 304);
                        BOOST_CHECK_EQUAL(*(img.x_at(3,4)), 304);
                    
                        // operator() as setter
                        img(3,4) = 3004;
                        BOOST_CHECK_EQUAL(img(3,4), 3004);
                    
                        // get0 / set0 on a (0,0)-referenced image
                        img.set0(3,4, 3004);
                        BOOST_CHECK_EQUAL(img(3,4), 3004);
                        BOOST_CHECK_EQUAL(img.get0(3,4,docheck), 3004);
                        BOOST_CHECK_EQUAL(img.get0(3,4), 3004);
                        img.set0(3, 4, 304, docheck);
                        BOOST_CHECK_EQUAL(img(3,4), 304);
                        img.set0(3, 4, 3004, docheck);
                        BOOST_CHECK_EQUAL(img(3,4), 3004);
                        img.set0(3, 4, 304);
                        BOOST_CHECK_EQUAL(img(3,4), 304);
                    
                        // create a subimage:   x in [1,3], y in [2,4]
                        ImageT subimg(img, geom::Box2I(geom::Point2I(1,2), geom::Extent2I(3,3)));
                        BOOST_CHECK_EQUAL(subimg.getWidth(), 3);
                        BOOST_CHECK_EQUAL(subimg.getHeight(), 3);
                        BOOST_CHECK_EQUAL(subimg.getX0(), 1);
                        BOOST_CHECK_EQUAL(subimg.getY0(), 2);
                    
                        BOOST_CHECK_EQUAL(subimg(0,0), 102);
                        BOOST_CHECK_EQUAL(subimg(2,2), 304);
                        BOOST_CHECK_EQUAL(subimg.get0(1, 2, docheck), 102);
                        // (0,0) in the subimage is (1,2) in the parent image
                        BOOST_CHECK_EQUAL(subimg.get0(1, 2), 102);
                        // subimage can't reference parent coord 0,0
    
    156 b0e0d3fb - BOOST_CHECK_THROW(subimg.get0(0, 0, docheck), lsst::pex::exceptions::LengthErrorException);
    ? ---------
    156 21597d88 + BOOST_CHECK_THROW(subimg.get0(0, 0, docheck), lsst::pex::exceptions::LengthError);
    subimg.set0(3, 4, 1000000, docheck); BOOST_CHECK_EQUAL(subimg.get0(3, 4, docheck), 1000000); BOOST_CHECK_EQUAL(subimg(2,2), 1000000);
    161 b0e0d3fb - BOOST_CHECK_THROW(subimg.set0(0, 0, 1000000, docheck), lsst::pex::exceptions::LengthErrorException);
    ? ---------
    161 21597d88 + BOOST_CHECK_THROW(subimg.set0(0, 0, 1000000, docheck), lsst::pex::exceptions::LengthError);
    } BOOST_AUTO_TEST_CASE(setValues) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ ImageT img = make_image(); MaskT mask(geom::Extent2I(1, 1)); mask = 0x8; #if PRINT_IMAGE printImage(img, "Image"); #endif ImageT::x_iterator ptr = img.x_at(1, 1); MaskT::y_iterator mptr = mask.y_at(0, 0); BOOST_CHECK_EQUAL(*ptr, 101); BOOST_CHECK_EQUAL(*mptr, 0x8); *ptr /= 2; *mptr /= 2; BOOST_CHECK_EQUAL(*ptr, 50.5); BOOST_CHECK_EQUAL(*mptr, 0x4); *ptr *= 2; BOOST_CHECK_EQUAL(*ptr, 101); *ptr /= *ptr; BOOST_CHECK_EQUAL(*ptr, 1); ptr++; BOOST_CHECK_EQUAL(*ptr, 201); ImageT img2(img.getDimensions()); // make a deep copy img2 = 4; ImageT::x_iterator ptr2 = img2.x_at(0, 4); //ImageT::Pixel val2 = *ptr2; *ptr = 100; // sets *ptr to (100, 0, 0) BOOST_CHECK_EQUAL(*ptr, 100); *ptr *= *img2.x_at(0,4); // == ptr2 BOOST_CHECK_EQUAL(*ptr, 400); *ptr2 += 10; BOOST_CHECK_EQUAL(*ptr2, 14); *ptr2 -= 10; BOOST_CHECK_EQUAL(*ptr2, 4); img = 10; *ptr += *ptr2; BOOST_CHECK_EQUAL(*ptr, 14); *ptr -= *ptr2; BOOST_CHECK_EQUAL(*ptr, 10);
    221 f8edfe90 - typedef ImageT::SinglePixel SinglePixel;
    *ptr = *ptr + *ptr2; BOOST_CHECK_EQUAL(*ptr, 14);
    225 f8edfe90 - //*ptr += SinglePixel(36);
    *ptr += 36; *ptr = *ptr + 25; *ptr = 25 + *ptr; BOOST_CHECK_EQUAL(*ptr, 100); BOOST_CHECK_EQUAL(*ptr, *ptr); img = ImageT::Pixel(111); BOOST_CHECK_EQUAL(img(0,0), 111); mask = MaskT::Pixel(0x666); BOOST_CHECK_EQUAL(mask(0,0), 0x666); } /************************************************************************************************************/ // // Iterators // BOOST_AUTO_TEST_CASE(iterators) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ ImageT img = make_image(); // // Count the pixels between begin() and end() (using a fast iterator) // { int i = 0; for (ImageT::fast_iterator ptr = img.begin(true), end = img.end(true); ptr != end; ++ptr, ++i) { } BOOST_CHECK_EQUAL(i, img.getWidth()*img.getHeight()); } // // Count the pixels between begin() and end() (using a const_iterator) // { int i = 0; for (ImageT::const_iterator ptr = img.begin(), end = img.end(); ptr != end; ++ptr, ++i) { } BOOST_CHECK_EQUAL(i, img.getWidth()*img.getHeight()); } // // Count the pixels between begin() and end() backwards (there is no const_reverse_iterator) // { int i = 0; for (ImageT::reverse_iterator ptr = img.rbegin(), end = img.rend(); ptr != end; ++ptr, ++i) { } BOOST_CHECK_EQUAL(i, img.getWidth()*img.getHeight()); } // // Check begin() and our ability to increment it // { ImageT::iterator ptr = img.begin(); ptr += img.getWidth() + 1; // move to (1,1) BOOST_CHECK_EQUAL(*ptr, 101); } // // Check {col,row}_begin() and our ability to increment them // { ImageT::x_iterator rptr = img.row_begin(1); rptr += 1; // move to (1,1) BOOST_CHECK_EQUAL(*rptr, 101); BOOST_REQUIRE(img.getWidth() >= 4); ImageT::const_x_iterator at_ptr = img.x_at(3,2); BOOST_CHECK_EQUAL(*at_ptr, 302); } { ImageT::y_iterator cptr = img.col_begin(2); cptr += 1; // move to (2,1) BOOST_CHECK_EQUAL(*cptr, 201); BOOST_REQUIRE(img.getWidth() >= 4); ImageT::const_y_iterator at_ptr = img.y_at(3,2); BOOST_CHECK_EQUAL(*at_ptr, 302); } // // Test {col,row}_{begin,end} by finding the width and height // { int i = 0; for (ImageT::x_iterator ptr = img.row_begin(0), end = img.row_end(0); ptr != end; ++ptr) { ++i; } BOOST_CHECK_EQUAL(i, img.getWidth()); i = 0; for (ImageT::y_iterator ptr = img.col_begin(0), end = img.col_end(0); ptr != end; ++ptr) { ++i; } BOOST_CHECK_EQUAL(i, img.getHeight()); } // // Check that at() works too // { ImageT::const_iterator ptr = img.at(1,1); BOOST_CHECK_EQUAL(*ptr, 101); } // // Check that adding to the iterators works // { ImageT::x_iterator begin = img.row_begin(0), end = begin + img.getWidth(); BOOST_CHECK(begin != end); } { ImageT::y_iterator end = img.col_end(0), begin = end - img.getWidth(); BOOST_CHECK(!(begin == end)); } } /************************************************************************************************************/ // // Locators // BOOST_AUTO_TEST_CASE(locators) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ ImageT img = make_image(); { ImageT::xy_locator loc = img.xy_at(1,1); BOOST_CHECK_EQUAL(*loc, 101); BOOST_CHECK_EQUAL(loc(1,1), 202); loc += image::pair2I(-1, 1); // loc == img.xy_at(0, 2); BOOST_CHECK_EQUAL(*loc, 2); loc.x() += 2; ++loc.x(); // loc == img.xy_at(3, 2); loc.y() += 1; loc.y() += 1; // loc == img.xy_at(3, 4); BOOST_REQUIRE(img.getWidth() >= 4); BOOST_REQUIRE(img.getHeight() >= 5); BOOST_CHECK_EQUAL(*loc, 304); BOOST_CHECK_EQUAL(*loc.x(), 304); BOOST_CHECK_EQUAL(*loc.y(), 304); ++loc.x(); BOOST_CHECK_EQUAL(*loc.x(), 404); BOOST_CHECK_EQUAL(*loc, 404); } { ImageT::xy_locator loc = img.xy_at(1,1); ImageT::xy_locator::cached_location_t above = loc.cache_location(0, 1); ImageT::xy_locator::cached_location_t below = loc.cache_location(0, -1); BOOST_CHECK_EQUAL(loc[above], 102); BOOST_CHECK_EQUAL(loc[below], 100); } }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    b0e0d3fb

    commit b0e0d3fba6ab46c94f4f600a1f245e407ec0c5d7
    Author: Dustin Lang 
    Date:   Sun Dec 4 11:11:02 2011 -0500
    
        add get0(), set0() accessors + swig + tests
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/math/detail/CudaLanczosWrapper.h

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008 - 2012 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * @file
                     *
                     * @brief GPU accelerared image warping
                     *
                     * @author Kresimir Cosic
                     *
                     * @ingroup afw
                     */
                    #ifndef LSST_AFW_MATH_DETAIL_CUDALANCZOSWRAPPER_H
                    #define LSST_AFW_MATH_DETAIL_CUDALANCZOSWRAPPER_H
                    
    
    37 8a049406 - #include "lsst/afw/math/detail/SrcPosFunctor.h"
    ? ---
    37 624db730 + #include "lsst/afw/math/detail/PositionFunctor.h"
    ? +++++ #include "lsst/afw/math/warpExposure.h" namespace lsst { namespace afw { namespace math { namespace detail { namespace WarpImageGpuStatus { enum ReturnCode {OK, NO_GPU, KERNEL_TOO_LARGE, INTERP_LEN_TOO_SMALL}; } /** * \brief GPU accelerated image warping using Lanczos resampling * * \return a std::pair containing: * 1) the number of valid pixels in destImage (those that are not edge pixels). * 2) whether the warping was performed successfully, or error code * (if not OK, then the first value is not defined) * * This function requires a Lanczos warping kernel to perform the source value estimation. * * This function will not perform the warping if kernel size is too large. * (currently, when the order of the Lanczos kernel is >50) * If warping is not performed, the second elemnt of return value will not equal OK. * If forceProcessing is true: * - this function will throw exceptions if a GPU device cannot be selected or used * If forceProcessing is false: * - the warping will not be performed if the GPU code path is estimated to be slower * than the CPU code path. That might happen if interpLength is too small (less than 3). * - the warping will not be performed if a GPU device cannot be selected or used * * \pre maskWarpingKernel must not be greater in size than warpingKernel * * Also see lsst::afw::math::warpImage() * * \b Implementation: * Calculates values of the coordinate transform function at some points, which are spaced by interpLength intervals. * Calls CalculateInterpolationData() to calculate interpolation data from values of coordinate transformation fn. * Calls WarpImageGpuWrapper() to perform the wapring. *
    79 af8f5ebe - * \throw lsst::pex::exceptions::InvalidParameterException if interpLength < 1
    ? ^^^^^^ ^
    79 21597d88 + * \throw lsst::pex::exceptions::InvalidParameterError if interpLength < 1
    ? ^^ ^
    80 3b83215c - * \throw lsst::pex::exceptions::InvalidParameterException if maskWarpingKernel is neither Lanczos, bilinear
    ? ^^^^^^ ^
    80 21597d88 + * \throw lsst::pex::exceptions::InvalidParameterError if maskWarpingKernel is neither Lanczos, bilinear
    ? ^^ ^ * nor nearest neighbor
    82 af8f5ebe - * \throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    82 21597d88 + * \throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    83 af8f5ebe - * \throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    83 21597d88 + * \throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    84 af8f5ebe - * \throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    84 21597d88 + * \throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * */ template std::pair warpImageGPU( DestImageT &destImage, ///< remapped %image SrcImageT const &srcImage, ///< source %image lsst::afw::math::LanczosWarpingKernel const &warpingKernel, ///< warping kernel lsst::afw::math::SeparableKernel const &maskWarpingKernel, ///< mask warping kernel (can be the same as warping kernel)
    93 c31ebcf9 - SrcPosFunctor const &computeSrcPos, ///< Functor to compute source position
    ? ---
    93 624db730 + PositionFunctor const &computeSrcPos, ///< Functor to compute source position
    ? +++++ int const interpLength, ///< Distance over which WCS can be linearily interpolated ///< must be >0 typename DestImageT::SinglePixel padValue, ///< value to use for undefined pixels const bool forceProcessing=true ///< if true, this function will perform the warping even when ///< it is slower then the CPU code path ); }}}} // lsst::afw::math::detail #endif // !defined(LSST_AFW_MATH_DETAIL_CUDALANCZOSWRAPPER_H)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    8a049406

    commit 8a0494065e210e37d4f92d61b38f9d126372b7eb
    Author: Russell Owen 
    Date:   Wed Jun 27 17:09:10 2012 -0700
    
        Preparatory work to support warping the mask plane with a different kernel (e.g. bilinear):
         * Added a WarpingControl object that allows specifying a separate mask kernel
         * Added getCacheSize method to Kernel to support WarpingControl
         * Added new versions of the various warping functions that support this control object,
           and modified the old ones to internally make a control object
         * Moved SrcPosFunctor to its own header file and moved the AffineTransform version there,
           to keep company with the base and WCS versions and make everything easier to find.
    

    c31ebcf9

    commit c31ebcf91bbcbc4de7a046a83af1ac3f3da22545
    Merge: 46325ba 8e1872d
    Author: Kresimir Cosic 
    Date:   Sat Mar 3 10:10:28 2012 +0100
    
        Fixed conflicts, adapted to changes
    

    3b83215c

    commit 3b83215c66c72971e2581dd61fcb21c26d5ef987
    Author: Kresimir Cosic 
    Date:   Tue Aug 28 19:54:36 2012 +0200
    
        Applying fixes as indicated in the review: using 'TYPE const', fixed spelling of neighbor
    

    af8f5ebe

    commit af8f5ebef4f524d96fa4c824d3c8eb1cf11a6869
    Author: Kresimir Cosic 
    Date:   Mon Feb 27 03:39:36 2012 +0100
    
        Added afw::gpu namespace, reorganized files and interfaces to use this namespace
    

    Commits in /Users/nate/repos_lsst/afw/

    624db730

    commit 624db730b18aee1cfa2bed9d4b6c64a67da00a26
    Author: Steven Bickerton 
    Date:   Tue Feb 18 18:24:47 2014 +0900
    
        renamed SrcPosFunctor -> PositionFunctor
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/geom/ellipses/Separable.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    %{
                    #include "lsst/afw/geom/ellipses/radii.h"
                    #include "lsst/afw/geom/ellipses/ConformalShear.h"
                    #include "lsst/afw/geom/ellipses/ReducedShear.h"
                    #include "lsst/afw/geom/ellipses/Distortion.h"
                    #include "lsst/afw/geom/ellipses/Separable.h"
                    %}
                    
                    %include "std_complex.i"
                    
                    %declareNumPyConverters(lsst::afw::geom::ellipses::EllipticityBase::Jacobian);
                    
                    %rename(assign) lsst::afw::geom::ellipses::DeterminantRadius::operator=;
                    %rename(assign) lsst::afw::geom::ellipses::TraceRadius::operator=;
                    %rename(assign) lsst::afw::geom::ellipses::LogDeterminantRadius::operator=;
                    %rename(assign) lsst::afw::geom::ellipses::LogTraceRadius::operator=;
                    
                    %rename(assign) lsst::afw::geom::ellipses::Distortion::operator=;
                    %rename(assign) lsst::afw::geom::ellipses::ConformalShear::operator=;
                    %rename(assign) lsst::afw::geom::ellipses::ReducedShear::operator=;
                    %ignore lsst::afw::geom::ellipses::detail::EllipticityBase::getComplex;
                    
                    %define %Radius_POSTINCLUDE(RADIUS)
                    %extend lsst::afw::geom::ellipses::RADIUS {
                        double __float__() const {
                            return static_cast(*self);
                        }
                        double getValue() const {
                            return static_cast(*self);
                        }
                        void setValue(double value) {
                            static_cast(*self) = value;
                        }
    
    58 ec20f809 - %pythoncode {
    58 81c3bd10 + %pythoncode %{
    ? + def __str__(self): return str(float(self)) def __repr__(self): return "%s(%g)" % (self.getName(), float(self))
    63 ec20f809 - }
    63 81c3bd10 + %}
    ? + } %enddef %define %Ellipticity_POSTINCLUDE(ELLIPTICITY) %extend lsst::afw::geom::ellipses::ELLIPTICITY { %feature("shadow") _getComplex %{ def getComplex(self): return $action(self) %} std::complex _getComplex() const { return self->getComplex(); } void setComplex(std::complex other) { self->getComplex() = other; }
    79 8130b1bb - %pythoncode {
    79 81c3bd10 + %pythoncode %{
    ? + def __str__(self): return "(%g, %g)" % (self.getE1(), self.getE2()) def __repr__(self): return "%s(%g, %g)" % (self.getName(), self.getE1(), self.getE2())
    84 8130b1bb - }
    84 81c3bd10 + %}
    ? + } %enddef %include "lsst/afw/geom/ellipses/radii.h" %include "lsst/afw/geom/ellipses/EllipticityBase.h" %include "lsst/afw/geom/ellipses/Distortion.h" %include "lsst/afw/geom/ellipses/ConformalShear.h" %include "lsst/afw/geom/ellipses/ReducedShear.h" %Ellipticity_POSTINCLUDE(Distortion); %Ellipticity_POSTINCLUDE(ConformalShear); %Ellipticity_POSTINCLUDE(ReducedShear); %Radius_POSTINCLUDE(TraceRadius); %Radius_POSTINCLUDE(DeterminantRadius); %Radius_POSTINCLUDE(LogTraceRadius); %Radius_POSTINCLUDE(LogDeterminantRadius); %ignore lsst::afw::geom::ellipses::Separable::writeParameters; %ignore lsst::afw::geom::ellipses::Separable::readParameters; %rename(assign) lsst::afw::geom::ellipses::Separable::operator=; %define %Separable_PREINCLUDE(ELLIPTICITY, RADIUS) %shared_ptr( lsst::afw::geom::ellipses::Separable< lsst::afw::geom::ellipses::ELLIPTICITY, lsst::afw::geom::ellipses::RADIUS > ); %rename(assign) lsst::afw::geom::ellipses::Separable< lsst::afw::geom::ellipses::ELLIPTICITY, lsst::afw::geom::ellipses::RADIUS >::operator=; %enddef %define %Separable_POSTINCLUDE(ELLIPTICITY, RADIUS) %template(Separable ## ELLIPTICITY ## RADIUS) lsst::afw::geom::ellipses::Separable< lsst::afw::geom::ellipses::ELLIPTICITY, lsst::afw::geom::ellipses::RADIUS >; %enddef %Separable_PREINCLUDE(Distortion, DeterminantRadius); %Separable_PREINCLUDE(Distortion, TraceRadius); %Separable_PREINCLUDE(Distortion, LogDeterminantRadius); %Separable_PREINCLUDE(Distortion, LogTraceRadius); %Separable_PREINCLUDE(ConformalShear, DeterminantRadius); %Separable_PREINCLUDE(ConformalShear, TraceRadius); %Separable_PREINCLUDE(ConformalShear, LogDeterminantRadius); %Separable_PREINCLUDE(ConformalShear, LogTraceRadius); %Separable_PREINCLUDE(ReducedShear, DeterminantRadius); %Separable_PREINCLUDE(ReducedShear, TraceRadius); %Separable_PREINCLUDE(ReducedShear, LogDeterminantRadius); %Separable_PREINCLUDE(ReducedShear, LogTraceRadius); %include "lsst/afw/geom/ellipses/Separable.h" %extend lsst::afw::geom::ellipses::Separable { %feature("shadow") _transform %{ def transform(self, t): return $action(self, t) %} %feature("shadow") _transformInPlace %{ def transformInPlace(self, t): $action(self, t) %} %feature("shadow") _convolve %{ def convolve(self, t): return $action(self, t) %} %feature("shadow") _getGridTransform %{ def getGridTransform(self): return $action(self) %} lsst::afw::geom::ellipses::Separable::Ptr _transform( lsst::afw::geom::LinearTransform const & t ) { return boost::static_pointer_cast >( self->transform(t).copy() ); } void _transformInPlace(lsst::afw::geom::LinearTransform const & t) { self->transform(t).inPlace(); } lsst::afw::geom::ellipses::Separable::Ptr _convolve( lsst::afw::geom::ellipses::BaseCore const & other ) { return boost::static_pointer_cast >( self->convolve(other).copy() ); } lsst::afw::geom::LinearTransform _getGridTransform() { return self->getGridTransform(); } static lsst::afw::geom::ellipses::Separable::Ptr cast( lsst::afw::geom::ellipses::BaseCore::Ptr const & p ) { return boost::dynamic_pointer_cast >(p); }
    191 3b0e9527 - %pythoncode {
    191 81c3bd10 + %pythoncode %{
    ? + def __repr__(self): return "Separable(%r, %r)" % (self.getEllipticity(), self.getRadius()) def __str__(self): return "(%s, %s)" % (self.getEllipticity(), self.getRadius())
    196 3b0e9527 - }
    196 81c3bd10 + %}
    ? + } %Separable_POSTINCLUDE(Distortion, DeterminantRadius); %Separable_POSTINCLUDE(Distortion, TraceRadius); %Separable_POSTINCLUDE(Distortion, LogDeterminantRadius); %Separable_POSTINCLUDE(Distortion, LogTraceRadius); %Separable_POSTINCLUDE(ConformalShear, DeterminantRadius); %Separable_POSTINCLUDE(ConformalShear, TraceRadius); %Separable_POSTINCLUDE(ConformalShear, LogDeterminantRadius); %Separable_POSTINCLUDE(ConformalShear, LogTraceRadius); %Separable_POSTINCLUDE(ReducedShear, DeterminantRadius); %Separable_POSTINCLUDE(ReducedShear, TraceRadius); %Separable_POSTINCLUDE(ReducedShear, LogDeterminantRadius); %Separable_POSTINCLUDE(ReducedShear, LogTraceRadius);

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ec20f809

    commit ec20f8097a5b2aa832ae06a64a5ff1d18e88a24a
    Author: jbosch 
    Date:   Fri Apr 1 20:21:59 2011 +0000
    
        afw #1556 - added __str__ and __float__ to ellipse radius classes in Python
    

    3b0e9527

    commit 3b0e9527db8456ec69bbbc04fc51e5c64ab75490
    Author: dubcovsky 
    Date:   Sun Feb 6 06:37:31 2011 +0000
    
        #1556 *ahem* actually added the updated swig wrappers for lsst::afw::geom::ellipses
    

    8130b1bb

    commit 8130b1bbe4b0312ab20dfebbcf862d497c2eb8b6
    Author: jbosch 
    Date:   Fri Apr 1 19:13:39 2011 +0000
    
        afw #1556 - added ReducedShear, changed LogShear to ConformalShear (with a change in definition by a factor of 2); ellipticity types now match the most common ellipticities in the weak lensing literature.
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    include/lsst/afw/table/io/Reader.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_IO_Reader_h_INCLUDED
                    #define AFW_TABLE_IO_Reader_h_INCLUDED
                    
                    #include "lsst/base.h"
                    
                    namespace lsst { namespace afw { namespace table { 
                    
                    class BaseTable;
                    
                    namespace io {
                    
                    /**
                     *  @brief A base class for code that reads table/record data from another source.
                     *
                     *  An instance of Reader is associated with a particular file or other data source,
                     *  and can be invoked simply by calling read() with no arguments and a template parameter
                     *  that corresponds to the specialized container into which records will be loaded.
                     *
                     *  Reader provides driver code that should work for most input operations and record containers,
                     *  and delegates the real work to its protected member functions.  Reader does not specify how it
                     *  will be constructed.
                     */ 
                    class Reader {
                    public:
                    
                        /**
                         *  @brief Load an on-disk table into a container.
                         *
                         *  The container must be a specialized table container (like CatalogT):
                         *   - It must be constructable from a single table shared_ptr argument.
                         *   - It must have an insert member function that takes an position
                         *     iterator and a record shared_ptr.
                         */
                        template 
                        ContainerT read() {
                    #if 1
                            // Work around a clang++ version 3.0 (tags/Apple/clang-211.12) bug with shared_ptr reference counts
                            PTR(typename ContainerT::Table) table;
                            {
                                PTR(BaseTable) tmpTable = _readTable();
                                table = boost::dynamic_pointer_cast(tmpTable);
                            }
                    #else
                            PTR(typename ContainerT::Table) table 
                                = boost::dynamic_pointer_cast(_readTable());
                    #endif
                            if (!table) {
                                throw LSST_EXCEPT(
    
    50 dbc20e58 - lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    50 21597d88 + lsst::pex::exceptions::RuntimeError,
    "Container's table type is not compatible with on-disk table type." ); } ContainerT container(table); PTR(BaseRecord) record = _readRecord(table); while (record) { container.insert( container.end(), boost::static_pointer_cast(record) ); record = _readRecord(table); } return container; } virtual ~Reader() {} protected: /** * @brief Create a new table of the appropriate type. * * The result may be an instance of a subclass of BaseTable. */ virtual PTR(BaseTable) _readTable() = 0; /** * @brief Read an individual record, creating it with the given table. * * The result may be an instance of a subclass of BaseRecord. The table will have just been loaded * with _readSchema; these are separated in order to allow subclasses to delegate to base * class implementations more effectively. */ virtual PTR(BaseRecord) _readRecord(PTR(BaseTable) const & table) = 0; }; }}}} // namespace lsst::afw::table::io #endif // !AFW_TABLE_IO_Reader_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    dbc20e58

    commit dbc20e585ec07b70b8c9dc3bbf9707ee3c200480
    Author: Jim Bosch 
    Date:   Wed Jan 25 20:07:49 2012 -0500
    
        lots of shuffling code around.  FITS table support now much better organized
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/table/Exposure.cc

    Diff:

                    // -*- lsst-c++ -*-
                    #include 
                    
                    #include "lsst/afw/table/io/FitsWriter.h"
                    #include "lsst/afw/table/Exposure.h"
                    #include "lsst/afw/table/detail/Access.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/table/io/InputArchive.h"
                    #include "lsst/afw/image/Wcs.h"
                    #include "lsst/afw/image/Calib.h"
    
    11 18d4b1ff - #include "lsst/afw/image/ApCorrMap.h"
    #include "lsst/afw/detection/Psf.h"
    13 fd15d1dd - #include "lsst/afw/geom/polygon/Polygon.h"
    namespace lsst { namespace afw { namespace table { //----------------------------------------------------------------------------------------------------------- //----- Private ExposureTable/Record classes --------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------- // These private derived classes are what you actually get when you do ExposureTable::make; like the // private classes in BaseTable.cc, it's more convenient to have an extra set of trivial derived // classes than to do a lot of friending. namespace { class ExposureTableImpl; class ExposureRecordImpl : public ExposureRecord { public: explicit ExposureRecordImpl(PTR(ExposureTable) const & table) : ExposureRecord(table) { // Want to make default bbox empty, not a single pixel at 0,0 this->set(ExposureTable::getBBoxMaxKey(), geom::Point2I(-1,-1)); } }; class ExposureTableImpl : public ExposureTable { public: explicit ExposureTableImpl(Schema const & schema) : ExposureTable(schema) {} ExposureTableImpl(ExposureTableImpl const & other) : ExposureTable(other) {} private: virtual PTR(BaseTable) _clone() const { return boost::make_shared(*this); } virtual PTR(BaseRecord) _makeRecord() { return boost::make_shared(getSelf()); } }; // Schema prepended when saving an Exposure table struct PersistenceSchema : private boost::noncopyable { Schema schema;
    63 18d4b1ff - int version;
    Key wcs; Key psf; Key calib;
    67 18d4b1ff - Key apCorrMap;
    68 fd15d1dd - Key validPolygon;
    70 fd15d1dd - static PersistenceSchema const & get(int version=2) {
    ? -------------
    65 ad63680a + static PersistenceSchema const & get() {
    71 18d4b1ff - static PersistenceSchema const instance0(0);
    ? ----
    66 ad63680a + static PersistenceSchema const instance;
    72 18d4b1ff - static PersistenceSchema const instance1(1);
    73 fd15d1dd - static PersistenceSchema const instance2(2);
    74 18d4b1ff - switch (version) {
    75 18d4b1ff - case 0:
    76 18d4b1ff - return instance0;
    ? ---- -
    67 ad63680a + return instance;
    77 18d4b1ff - case 1:
    78 18d4b1ff - return instance1;
    79 fd15d1dd - case 2:
    80 fd15d1dd - return instance2;
    81 18d4b1ff - default:
    82 18d4b1ff - assert(false);
    83 18d4b1ff - }
    ? ----
    68 ad63680a + }
    84 18d4b1ff - }
    86 18d4b1ff - static PersistenceSchema const & getMatching(Schema const & schema) {
    87 fd15d1dd - if (schema.contains(PersistenceSchema::get(2).schema)) {
    88 fd15d1dd - return PersistenceSchema::get(2);
    89 fd15d1dd - } else if (schema.contains(PersistenceSchema::get(1).schema)) {
    90 18d4b1ff - return PersistenceSchema::get(1);
    91 18d4b1ff - } else if (schema.contains(PersistenceSchema::get(0).schema)) {
    92 18d4b1ff - return PersistenceSchema::get(0);
    93 18d4b1ff - }
    94 18d4b1ff - throw LSST_EXCEPT(
    95 18d4b1ff - afw::table::io::PersistenceError,
    96 18d4b1ff - "Unrecognized schema for ExposureCatalog"
    97 18d4b1ff - );
    98 ad63680a - }
    99 ad63680a -
    100 fd15d1dd - // Create a SchemaMapper that maps an ExposureRecord to a BaseRecord
    70 ad63680a + // Create a SchemaMapper that maps an ExposureRecord to a BaseRecord with IDs for Psf and Wcs.
    ? +++++++++++++++++++++++++
    101 fd15d1dd - // with IDs for Psf and Wcs and ValidPolygon.
    SchemaMapper makeWriteMapper(Schema const & inputSchema) const {
    103 fd15d1dd - assert(version > 1); // should only be writing version 2 catalogs
    std::vector inSchemas; inSchemas.push_back(PersistenceSchema::get().schema); inSchemas.push_back(inputSchema);
    107 ad63680a - return SchemaMapper::join(inSchemas).back(); // don't need front; it's an identity mapper
    75 f1760fcb + // don't need front; it's an identity mapper
    76 f1760fcb + SchemaMapper result = SchemaMapper::join(inSchemas).back();
    77 f1760fcb + result.editOutputSchema().setAliasMap(inputSchema.getAliasMap());
    78 f1760fcb + return result;
    } // Create a SchemaMapper that maps a BaseRecord with IDs for Psf and Wcs to an ExposureRecord SchemaMapper makeReadMapper(Schema const & inputSchema) const {
    112 18d4b1ff - if (!inputSchema.contains(schema)) {
    113 18d4b1ff - throw LSST_EXCEPT(
    114 18d4b1ff - pex::exceptions::LogicErrorException,
    115 18d4b1ff - "Cannot read ExposureCatalog instances written with an older version of the pipeline"
    116 18d4b1ff - );
    117 18d4b1ff - }
    118 ad63680a - return SchemaMapper::removeMinimalSchema(inputSchema, schema);
    ? ^^^
    83 f1760fcb + SchemaMapper result = SchemaMapper::removeMinimalSchema(inputSchema, schema);
    ? +++++++++++++ +++ ^^
    84 f1760fcb + result.editOutputSchema().setAliasMap(inputSchema.getAliasMap());
    85 f1760fcb + return result;
    } // Convert an ExposureRecord to a BaseRecord with IDs for Psf and Wcs. template void writeRecord( ExposureRecord const & input, BaseRecord & output, SchemaMapper const & mapper, OutputArchiveIsh & archive, bool permissive ) const {
    128 fd15d1dd - assert(version > 1); // should only be writing version 2 catalogs
    output.assign(input, mapper); output.set(psf, archive.put(input.getPsf(), permissive)); output.set(wcs, archive.put(input.getWcs(), permissive)); output.set(calib, archive.put(input.getCalib(), permissive));
    133 18d4b1ff - output.set(apCorrMap, archive.put(input.getApCorrMap(), permissive));
    134 fd15d1dd - output.set(validPolygon, archive.put(input.getValidPolygon(), permissive));
    } void readRecord( BaseRecord const & input, ExposureRecord & output, SchemaMapper const & mapper, io::InputArchive const & archive ) const { output.assign(input, mapper); output.setPsf(archive.get(input.get(psf))); output.setWcs(archive.get(input.get(wcs))); output.setCalib(archive.get(input.get(calib)));
    145 18d4b1ff - if (version > 0) {
    146 18d4b1ff - output.setApCorrMap(archive.get(input.get(apCorrMap)));
    147 18d4b1ff - }
    148 fd15d1dd - if (version > 1) {
    149 fd15d1dd - output.setValidPolygon(archive.get(input.get(validPolygon)));
    150 fd15d1dd - }
    } private:
    154 18d4b1ff -
    155 18d4b1ff - PersistenceSchema(int version_) :
    ? ------------
    112 ad63680a + PersistenceSchema() :
    schema(),
    157 18d4b1ff - version(version_),
    wcs(schema.addField("wcs", "archive ID for Wcs object")), psf(schema.addField("psf", "archive ID for Psf object")), calib(schema.addField("calib", "archive ID for Calib object")) {
    162 18d4b1ff - if (version > 0) {
    163 18d4b1ff - apCorrMap = schema.addField("apCorrMap", "archive ID for ApCorrMap object");
    164 18d4b1ff - }
    165 fd15d1dd - if (version > 1) {
    166 fd15d1dd - validPolygon = schema.addField("validPolygon", "archive ID for Polygon object");
    167 fd15d1dd - }
    schema.getCitizen().markPersistent(); }
    170 18d4b1ff -
    }; } // anonymous //----------------------------------------------------------------------------------------------------------- //----- ExposureFitsWriter --------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------- // A custom FitsWriter for Exposure - this just sets the AFW_TYPE key to EXPOSURE, which should ensure // we use ExposureFitsReader to read it. namespace { class ExposureFitsWriter : public io::FitsWriter { public: ExposureFitsWriter(Fits * fits, PTR(io::OutputArchive) archive, int flags) : io::FitsWriter(fits, flags), _doWriteArchive(false), _archive(archive) { if (!_archive) { _doWriteArchive = true; _archive.reset(new io::OutputArchive()); } } protected: virtual void _writeTable(CONST_PTR(BaseTable) const & table, std::size_t nRows); virtual void _writeRecord(BaseRecord const & r); virtual void _finish() { if (_doWriteArchive) _archive->writeFits(*_fits); } bool _doWriteArchive; PTR(io::OutputArchive) _archive; PTR(BaseRecord) _record; SchemaMapper _mapper; }; void ExposureFitsWriter::_writeTable(CONST_PTR(BaseTable) const & t, std::size_t nRows) { CONST_PTR(ExposureTable) inTable = boost::dynamic_pointer_cast(t); if (!inTable) { throw LSST_EXCEPT(
    217 ad63680a - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    166 21597d88 + lsst::pex::exceptions::LogicError,
    "Cannot use a ExposureFitsWriter on a non-Exposure table." ); } _mapper = PersistenceSchema::get().makeWriteMapper(inTable->getSchema()); PTR(BaseTable) outTable = BaseTable::make(_mapper.getOutputSchema()); io::FitsWriter::_writeTable(outTable, nRows); _fits->writeKey("AFW_TYPE", "EXPOSURE", "Tells lsst::afw to load this as an Exposure table."); _record = outTable->makeRecord(); } void ExposureFitsWriter::_writeRecord(BaseRecord const & r) { ExposureRecord const & record = static_cast(r); PersistenceSchema::get().writeRecord(record, *_record, _mapper, *_archive, false); io::FitsWriter::_writeRecord(*_record); } } // anonymous //----------------------------------------------------------------------------------------------------------- //----- ExposureFitsReader --------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------- // A custom FitsReader for ExposureTable/Record - this gets registered with name EXPOSURE, so it should get // used whenever we read a table with AFW_TYPE set to that value. namespace { class ExposureFitsReader : public io::FitsReader { public: explicit ExposureFitsReader(Fits * fits, PTR(io::InputArchive) archive, int flags) :
    249 18d4b1ff - io::FitsReader(fits, archive, flags), _archive(archive), _helper(NULL)
    ? ---------------
    198 ef7ca945 + io::FitsReader(fits, archive, flags), _archive(archive)
    { if (!_archive) { int oldHdu = _fits->getHdu(); _fits->setHdu(oldHdu + 1); _archive.reset(new io::InputArchive(io::InputArchive::readFits(*_fits))); _fits->setHdu(oldHdu); } } protected: virtual PTR(BaseTable) _readTable(); virtual PTR(BaseRecord) _readRecord(PTR(BaseTable) const & table); PTR(BaseTable) _inTable; PTR(io::InputArchive) _archive; SchemaMapper _mapper;
    268 18d4b1ff - PersistenceSchema const * _helper;
    }; PTR(BaseTable) ExposureFitsReader::_readTable() { PTR(daf::base::PropertyList) metadata = boost::make_shared(); _fits->readMetadata(*metadata, true); Schema schema(*metadata, true); _inTable = BaseTable::make(schema);
    276 18d4b1ff - _helper = &PersistenceSchema::getMatching(schema);
    ? ^^^ - ^^^^^^
    224 ad63680a + _mapper = PersistenceSchema::get().makeReadMapper(schema);
    ? ^^^ +++++++++++ ^^^^
    277 18d4b1ff - _mapper = _helper->makeReadMapper(schema);
    PTR(ExposureTable) table = ExposureTable::make(_mapper.getOutputSchema());
    226 ad63680a + table->setMetadata(metadata);
    _startRecords(*table);
    280 ad63680a - if (metadata->exists("AFW_TYPE")) metadata->remove("AFW_TYPE");
    281 ad63680a - table->setMetadata(metadata);
    return table; } PTR(BaseRecord) ExposureFitsReader::_readRecord(PTR(BaseTable) const & t) { PTR(ExposureRecord) record; PTR(ExposureTable) table = boost::static_pointer_cast(t); PTR(BaseRecord) inRecord = io::FitsReader::_readRecord(_inTable); if (inRecord) { record = table->makeRecord();
    291 18d4b1ff - _helper->readRecord(*inRecord, *record, _mapper, *_archive);
    ? ^ ^^ ^^^
    237 ad63680a + PersistenceSchema::get().readRecord(*inRecord, *record, _mapper, *_archive);
    ? ^^^^^^^^^^^^^ ^^^^^ ^^^^ } return record; } // registers the reader so FitsReader::make can use it. static io::FitsReader::FactoryT referenceFitsReaderFactory("EXPOSURE"); } // anonymous //----------------------------------------------------------------------------------------------------------- //----- ExposureTable/Record member function implementations ----------------------------------------------- //----------------------------------------------------------------------------------------------------------- geom::Box2I ExposureRecord::getBBox() const { return geom::Box2I(get(ExposureTable::getBBoxMinKey()), get(ExposureTable::getBBoxMaxKey())); } void ExposureRecord::setBBox(geom::Box2I const & bbox) { set(ExposureTable::getBBoxMinKey(), bbox.getMin()); set(ExposureTable::getBBoxMaxKey(), bbox.getMax()); }
    314 74a95535 - bool ExposureRecord::contains(Coord const & coord, bool includeValidPolygon) const {
    ? --------------------------
    260 ad63680a + bool ExposureRecord::contains(Coord const & coord) const {
    if (!getWcs()) { throw LSST_EXCEPT(
    317 ad63680a - pex::exceptions::LogicErrorException,
    ? ---------
    263 21597d88 + pex::exceptions::LogicError,
    "ExposureRecord does not have a Wcs; cannot call contains()" ); }
    321 74a95535 - // If there is no valid polygon set to false
    322 74a95535 - if (includeValidPolygon && !getValidPolygon()) includeValidPolygon = false;
    323 74a95535 -
    try { geom::Point2D point = getWcs()->skyToPixel(coord);
    326 74a95535 - if (includeValidPolygon) return (geom::Box2D(getBBox()).contains(point) &&
    327 74a95535 - getValidPolygon()->contains(point));
    328 74a95535 - else return geom::Box2D(getBBox()).contains(point);
    ? -----
    269 c45a9af7 + return geom::Box2D(getBBox()).contains(point);
    329 c45a9af7 - } catch (pex::exceptions::DomainErrorException &) {
    ? ---------
    270 21597d88 + } catch (pex::exceptions::DomainError &) {
    // Wcs can throw if the given coordinate is outside the region // where the Wcs is valid. return false; } }
    336 74a95535 - bool ExposureRecord::contains(geom::Point2D const & point, image::Wcs const & wcs, bool includeValidPolygon) const {
    ? --------------------------
    277 ad63680a + bool ExposureRecord::contains(geom::Point2D const & point, image::Wcs const & wcs) const {
    337 74a95535 - return contains(*wcs.pixelToSky(point), includeValidPolygon);
    ? ---------------------
    278 ad63680a + return contains(*wcs.pixelToSky(point));
    } ExposureRecord::ExposureRecord(PTR(ExposureTable) const & table) : BaseRecord(table) {} void ExposureRecord::_assign(BaseRecord const & other) { try { ExposureRecord const & s = dynamic_cast(other); _psf = s._psf; _wcs = s._wcs; _calib = s._calib;
    348 54c7f704 - _apCorrMap = s._apCorrMap;
    349 fd15d1dd - _validPolygon = s._validPolygon;
    } catch (std::bad_cast&) {} } PTR(ExposureTable) ExposureTable::make(Schema const & schema) { if (!checkSchema(schema)) { throw LSST_EXCEPT(
    356 ad63680a - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    295 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Schema for Exposure must contain at least the keys defined by makeMinimalSchema()." ); } return boost::make_shared(schema); } ExposureTable::ExposureTable(Schema const & schema) : BaseTable(schema) {} ExposureTable::ExposureTable(ExposureTable const & other) : BaseTable(other) {} ExposureTable::MinimalSchema::MinimalSchema() { id = schema.addField("id", "unique ID"); bboxMin = schema.addField< Point >("bbox.min", "bbox minimum point", "pixels"); bboxMax = schema.addField< Point >("bbox.max", "bbox maximum point", "pixels"); schema.getCitizen().markPersistent(); } ExposureTable::MinimalSchema & ExposureTable::getMinimalSchema() { static MinimalSchema it; return it; } PTR(io::FitsWriter) ExposureTable::makeFitsWriter(fits::Fits * fitsfile, int flags) const { return boost::make_shared(fitsfile, PTR(io::OutputArchive)(), flags); } PTR(io::FitsWriter) ExposureTable::makeFitsWriter(fits::Fits * fitsfile, PTR(io::OutputArchive) archive, int flags) const { return boost::make_shared(fitsfile, archive, flags); } //----------------------------------------------------------------------------------------------------------- //----- ExposureCatalogT member function implementations ---------------------------------------------------- //----------------------------------------------------------------------------------------------------------- template void ExposureCatalogT::writeToArchive(io::OutputArchiveHandle & handle, bool permissive) const { SchemaMapper mapper = PersistenceSchema::get().makeWriteMapper(this->getSchema()); BaseCatalog outputCat = handle.makeCatalog(mapper.getOutputSchema()); outputCat.reserve(this->size()); for (const_iterator i = this->begin(); i != this->end(); ++i) { PersistenceSchema::get().writeRecord(*i, *outputCat.addNew(), mapper, handle, permissive); } handle.saveCatalog(outputCat); } template ExposureCatalogT ExposureCatalogT::readFromArchive( io::InputArchive const & archive, BaseCatalog const & catalog ) {
    410 f1f94fe5 - PersistenceSchema const & helper = PersistenceSchema::getMatching(catalog.getSchema());
    411 f1f94fe5 - SchemaMapper mapper = helper.makeReadMapper(catalog.getSchema());
    ? ^^ ^
    349 ad63680a + SchemaMapper mapper = PersistenceSchema::get().makeReadMapper(catalog.getSchema());
    ? +++++++++++++ ^^^^^ ^^^ ExposureCatalogT result(mapper.getOutputSchema()); result.reserve(catalog.size()); for (BaseCatalog::const_iterator i = catalog.begin(); i != catalog.end(); ++i) {
    415 f1f94fe5 - helper.readRecord(*i, *result.addNew(), mapper, archive);
    ? ^^ ^
    353 ad63680a + PersistenceSchema::get().readRecord(*i, *result.addNew(), mapper, archive);
    ? +++++++++++++ ^^^^^ ^^^ } return result; } template ExposureCatalogT
    422 74a95535 - ExposureCatalogT::subsetContaining(Coord const & coord, bool includeValidPolygon) const {
    ? --------------------------
    360 38ad08ad + ExposureCatalogT::subsetContaining(Coord const & coord) const {
    ExposureCatalogT result(this->getTable()); for (const_iterator i = this->begin(); i != this->end(); ++i) {
    425 74a95535 - if (i->contains(coord, includeValidPolygon)) result.push_back(i);
    ? ---------------------
    363 ad63680a + if (i->contains(coord)) result.push_back(i);
    } return result; } template ExposureCatalogT
    370 38ad08ad + ExposureCatalogT::subsetContaining(geom::Point2D const & point, image::Wcs const & wcs) const {
    432 74a95535 - ExposureCatalogT::subsetContaining(
    433 74a95535 - geom::Point2D const & point, image::Wcs const & wcs, bool includeValidPolygon
    434 74a95535 - ) const {
    ExposureCatalogT result(this->getTable()); for (const_iterator i = this->begin(); i != this->end(); ++i) {
    437 74a95535 - if (i->contains(point, wcs,includeValidPolygon)) result.push_back(i);
    ? --------------------
    373 ad63680a + if (i->contains(point, wcs)) result.push_back(i);
    } return result; } //----------------------------------------------------------------------------------------------------------- //----- Explicit instantiation ------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------- template class CatalogT; template class CatalogT; template class SortedCatalogT; template class SortedCatalogT; template class ExposureCatalogT; template class ExposureCatalogT; }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f1f94fe5

    commit f1f94fe57da7971df557f8e42addb76e030a5688
    Author: Jim Bosch 
    Date:   Mon Sep 8 14:14:16 2014 -0400
    
        Fix backwards compatibility in CoaddPsf FITS I/O
    

    c45a9af7

    commit c45a9af77b7d9d62bdd055da9cf5e4f5e79b4231
    Author: Jim Bosch 
    Date:   Thu Feb 28 15:52:22 2013 +0900
    
        Catch out-of-range errors from Wcs in ExposureRecord::contains, and treat them as points that don't overlap the exposure with that Wcs.
    

    fd15d1dd

    commit fd15d1dd03c8a1d1b06864fe90ad7d962bc7e567
    Author: Bob Armstrong 
    Date:   Mon Sep 15 08:34:26 2014 -0400
    
        Exposure: Add a Polygon object to Exposure.
        
        Polygons will be used to define valid regions for each CCD to
        reject vignetted regions when building the Coadd Psf.
    

    74a95535

    commit 74a95535fc9f08c3cc5dc04a9467ddd33428ebb2
    Author: Bob Armstrong 
    Date:   Mon Sep 15 15:09:35 2014 -0400
    
        Exposure: Add includeValidPolygon option to contains function to check in valid region.
    

    18d4b1ff

    commit 18d4b1ff87ba59ac01d68d655548a78c2a04ac9f
    Author: Jim Bosch 
    Date:   Tue Jun 3 18:05:37 2014 -0400
    
        Add ApCorrMap to ExposureRecord
    

    ad63680a

    commit ad63680a28ce16e98b156f40c8c0e3474ac65410
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:50:27 2013 -0500
    
        Add ExposureTable/Record/Catalog.
    

    54c7f704

    commit 54c7f704047202b376e827b11eb6571d359347c5
    Author: Paul Price 
    Date:   Mon Sep 15 16:57:08 2014 -0400
    
        ExposureRecord: include aperture correction in assignment.
    

    Commits in /Users/nate/repos_lsst/afw/

    38ad08ad

    commit 38ad08ad2101e9cc2f59a107b39c5baad77c1c82
    Author: Jim Bosch 
    Date:   Thu Feb 28 12:52:12 2013 +0900
    
        Minor fixes to reflect code review for #2467.
        
        Removed trailing whitespace.
        Renamed ExposureCatalog::findContains to subsetContaining.
        Miscellaneous doc fixes.
        Added check on input sizes in SchemaMapper::join.
        OutputArchive::put overloads needed to forward permissive flag when delegating.
    

    c45a9af7

    commit c45a9af77b7d9d62bdd055da9cf5e4f5e79b4231
    Author: Jim Bosch 
    Date:   Thu Feb 28 15:52:22 2013 +0900
    
        Catch out-of-range errors from Wcs in ExposureRecord::contains, and treat them as points that don't overlap the exposure with that Wcs.
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    ad63680a

    commit ad63680a28ce16e98b156f40c8c0e3474ac65410
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:50:27 2013 -0500
    
        Add ExposureTable/Record/Catalog.
    

    ef7ca945

    commit ef7ca945ae2afe9c10d45649c5c25ca0c05e2dba
    Author: Jim Bosch 
    Date:   Tue Jun 18 18:55:36 2013 -0600
    
        Add currently-unspecified flags argument to catalog FITS I/O
    

    f1760fcb

    commit f1760fcb7952e5dbf1baf526b40e502027f30491
    Author: Jim Bosch 
    Date:   Tue Apr 14 19:09:13 2015 -0400
    
        Make transfer of aliases in SchemaMapper optional.
        
        The previous change to always transfer aliases in SchemaMapper
        broke existing code; this change reverts to the original behavior,
        with an easy option for to transfer aliases if desired (which is now
        used by SourceTable and ExposureTable).
    

    Return to list

    python/lsst/afw/math/GaussianProcess.i

    Diff:

                    
                    %{
                    #include "lsst/afw/math/GaussianProcess.h"
                    %}
    
    5 315e1869 -
    6 b8ec84fb - // Enable ndarray's NumPy typemaps; types are declared in %included files.
    7 b8ec84fb - %{
    8 b8ec84fb - #define PY_ARRAY_UNIQUE_SYMBOL LSST_AFW_MATH_NUMPY_ARRAY_API
    9 b8ec84fb - #include "numpy/arrayobject.h"
    10 b8ec84fb - #include "ndarray/swig.h"
    11 b8ec84fb - #include "ndarray/swig/eigen.h"
    12 b8ec84fb - %}
    13 b8ec84fb - %init %{
    14 b8ec84fb - import_array();
    15 b8ec84fb - %}
    16 b8ec84fb - %include "ndarray.i"
    17 b8ec84fb -
    %define %declarePTR(TYPE) %shared_ptr(lsst::afw::math::Covariogram); %shared_ptr(lsst::afw::math::SquaredExpCovariogram); %shared_ptr(lsst::afw::math::NeuralNetCovariogram); %enddef %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %define %declareGP(TYPE,SUFFIX) %template(KdTree##SUFFIX) lsst::afw::math::KdTree; %template(GaussianProcess##SUFFIX) lsst::afw::math::GaussianProcess; %template(Covariogram##SUFFIX) lsst::afw::math::Covariogram; %template(SquaredExpCovariogram##SUFFIX) lsst::afw::math::SquaredExpCovariogram; %template(NeuralNetCovariogram##SUFFIX) lsst::afw::math::NeuralNetCovariogram; %enddef %declarePTR(double); %include "lsst/afw/math/GaussianProcess.h" %declareGP(double,D);

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    315e1869

    commit 315e1869e8eaf4559ba46720fc02c8b11c2c5d80
    Author: danielsf 
    Date:   Thu Jan 31 15:37:05 2013 -0800
    
        added .i file
    

    b8ec84fb

    commit b8ec84fb3d85ee56c4379c1a1c23e3d215e696a7
    Author: danielsf 
    Date:   Fri Feb 8 16:45:35 2013 -0800
    
        gaussian process compiles and passes my first test
    

    Commits in /Users/nate/repos_lsst/afw/

    Return to list

    include/lsst/afw/math/Approximate.h

    Diff:

                    // -*- LSST-C++ -*-
                    #if !defined(LSST_AFW_MATH_APPROXIMATE_H)
                    #define LSST_AFW_MATH_APPROXIMATE_H
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include "lsst/base.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace geom {
                        class Box2I;
                    }
                    namespace image {
                    template class Image;
                    template class MaskedImage;
                    }
                    namespace math {
                    template class Approximate;
                    
                     /**
                      * @brief Control how to make an approximation
                      *
                      * \note the x- and y-order must be the same, due to a limitation of Chebyshev1Function2
                      *
                      * @ingroup afw
                      */
                    class ApproximateControl {
                    public:
                        /// \brief Choose the type of approximation to use
                        enum Style {
                            UNKNOWN = -1,
                            CHEBYSHEV,                      ///< Use a 2-D Chebyshev polynomial
                            NUM_STYLES
                        };
                    
    
    56 6a6e2e21 - ApproximateControl(Style style, int orderX, int orderY=-1);
    56 83a9a5f5 + ApproximateControl(Style style, int orderX, int orderY=-1, bool weighting=true);
    ? +++++++++++++++++++++ /// Return the Style Style getStyle() const { return _style; }
    59 264e671e - void setStyle(Style const style) { _style = style; }
    /// Return the order of approximation to use in the x-direction int getOrderX() const { return _orderX; }
    62 264e671e - void setOrderX(int const orderX) { _orderX = orderX; }
    /// Return the order of approximation to use in the y-direction int getOrderY() const { return _orderY; }
    65 264e671e - void setOrderY(int const orderY) { _orderY = orderY; }
    63 83a9a5f5 + /// Return whether inverse variance weighting will be used in calculation
    64 83a9a5f5 + bool getWeighting() const { return _weighting; }
    private:
    67 264e671e - Style _style;
    66 ce54f373 + Style const _style;
    ? ++++++
    68 264e671e - int _orderX;
    67 ce54f373 + int const _orderX;
    ? ++++++
    69 264e671e - int _orderY;
    68 ce54f373 + int const _orderY;
    ? ++++++
    69 83a9a5f5 + bool const _weighting;
    }; /** * @brief Construct a new Approximate object, inferring the type from the type of the given MaskedImage. */ template PTR(Approximate) makeApproximate(std::vector const &x, std::vector const &y, image::MaskedImage const& im, geom::Box2I const& bbox, ApproximateControl const& ctrl); /** * @brief Approximate values for a MaskedImage * @ingroup afw */ template class Approximate { public: typedef float OutPixelT; ///< The pixel type of returned images friend PTR(Approximate) makeApproximate<>(std::vector const &x, std::vector const &y, image::MaskedImage const& im, geom::Box2I const& bbox, ApproximateControl const& ctrl); /// \brief dtor virtual ~Approximate() {} /// \brief Return the approximate %image as a Image PTR(image::Image) getImage(int orderX=-1, int orderY=-1) const { return doGetImage(orderX, orderY); } /// \brief Return the approximate %image as a MaskedImage PTR(image::MaskedImage) getMaskedImage(int orderX=-1, int orderY=-1) const { return doGetMaskedImage(orderX, orderY); } protected: /** * \brief Base class ctor */ Approximate(std::vector const &x, ///< the x-values of points std::vector const &y, ///< the y-values of points geom::Box2I const& bbox, ///< Range where approximation should be valid ApproximateControl const& ctrl ///< desired approximation algorithm ) : _xVec(x), _yVec(y), _bbox(bbox), _ctrl(ctrl) {} std::vector const _xVec; ///< the x-values of points std::vector const _yVec; ///< the y-values of points geom::Box2I const _bbox; ///< Domain for approximation ApproximateControl const _ctrl; ///< desired approximation algorithm private: Approximate(Approximate const&); Approximate& operator=(Approximate const&); virtual PTR(image::Image) doGetImage(int orderX, int orderY) const = 0; virtual PTR(image::MaskedImage) doGetMaskedImage(int orderX, int orderY) const = 0; }; }}} #endif // LSST_AFW_MATH_APPROXIMATE_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6a6e2e21

    commit 6a6e2e214d3044bc5fab10ea449043107f6935ae
    Author: Robert Lupton the Good 
    Date:   Sun Oct 21 18:34:01 2012 -0400
    
        0 is a valid interpolation order
    

    264e671e

    commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
    Author: Steven Bickerton 
    Date:   Fri Oct 24 14:37:15 2014 +0900
    
        Use shared_ptr.  Add test.  Disable double,int backgrounds.
    

    Commits in /Users/nate/repos_lsst/afw/

    83a9a5f5

    commit 83a9a5f539b538b0cf4d5b67d8844a057d2401bc
    Author: Paul Price 
    Date:   Tue Jul 29 17:56:38 2014 -0500
    
        Approximate: make inverse-variance weighting configurable (#2411)
        
        If the input MaskedImage has identically zero variance (which
        occurs when approximating a BackgroundMI._statsImage constructed
        from a constant image; this occurs during testing with artificial
        images) then inverse variance weighting produces NANs.  Added an
        additional element in ApproximateControl to disable this behaviour.
    

    ce54f373

    commit ce54f373a160b8a69ca1f446780505ba649df8be
    Author: Robert Lupton the Good 
    Date:   Sat Oct 20 21:17:52 2012 -0400
    
        Compiles and runs (using temporary C++ test case)
    

    Return to list

    src/math/SpatialCell.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file
                     *
                     * @brief Implementation of SpatialCell class
                     *
                     * @ingroup afw
                     */
                    #include 
                    
                    #include "lsst/afw/image/ImageUtils.h"
                    #include "lsst/afw/image/Utils.h"
                    
                    #include "lsst/pex/exceptions/Exception.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/math/SpatialCell.h"
                    
                    namespace image = lsst::afw::image;
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    
                    namespace {
                        struct CandidatePtrMore : public std::binary_function {
                            bool operator()(SpatialCellCandidate::Ptr a, SpatialCellCandidate::Ptr b) {
                                return a->getCandidateRating() > b->getCandidateRating();
                            }
                        };
                    }
                    
                    /// Unique identifier for candidates; useful for preserving current candidate following insertion
                    int SpatialCellCandidate::_CandidateId = 0;
                    
                    /// Set the candidate's status
                    void SpatialCellCandidate::setStatus(Status status) {
                        switch (status) {
                          case GOOD:
                          case UNKNOWN:
                            _status = status;
                            return;
                          case BAD:
                            _status = status;
                            return;
                        }
                        
    
    72 6fc337ad - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    72 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Saw unknown status %d") % status).str()); } /************************************************************************************************************/ /** * Ctor */ SpatialCell::SpatialCell(std::string const& label, ///< string representing "name" of cell geom::Box2I const& bbox, ///< Bounding box of cell in overall image CandidateList const& candidateList ///< list of candidates to represent this cell ) : _label(label), _bbox(bbox), _candidateList(candidateList), _ignoreBad(true) { lsst::pex::logging::TTrace<3>("lsst.afw.math.SpatialCell", "Cell %s : created with %d candidates", this->_label.c_str(), this->_candidateList.size()); sortCandidates(); } /************************************************************************************************************/ /// /// Rearrange the candidates to reflect their current ratings /// void SpatialCell::sortCandidates() { sort(_candidateList.begin(), _candidateList.end(), CandidatePtrMore()); } /************************************************************************************************************/ /** * Add a candidate to the list, preserving ranking */ void SpatialCell::insertCandidate(SpatialCellCandidate::Ptr candidate) { CandidateList::iterator pos = std::lower_bound(_candidateList.begin(), _candidateList.end(), candidate, CandidatePtrMore()); _candidateList.insert(pos, candidate); } void SpatialCell::removeCandidate(SpatialCellCandidate::Ptr candidate) { CandidateList::iterator pos = std::find(_candidateList.begin(), _candidateList.end(), candidate); if (pos == _candidateList.end()) {
    118 b6bc9c01 - throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    118 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("Unable to find candidate with ID == %d") % candidate->getId()).str()); } _candidateList.erase(pos); } /** * Determine if cell has no usable candidates */ bool SpatialCell::empty() const { // Cast away const; end is only non-const as it provides access to the Candidates // and we don't (yet) have SpatialCellCandidateConstIterator SpatialCell *mthis = const_cast(this); for (SpatialCellCandidateIterator ptr = mthis->begin(), end = mthis->end(); ptr != end; ++ptr) { if (!(_ignoreBad && (*ptr)->isBad())) { // found a good candidate, or don't care return false; } } return true; } /** * Return number of usable candidates in Cell */ size_t SpatialCell::size() const { // Cast away const; begin/end is only non-const as they provide access to the Candidates // and we don't (yet) have SpatialCellCandidateConstIterator SpatialCell *mthis = const_cast(this); return mthis->end() - mthis->begin(); } /************************************************************************************************************/ /** * Return the SpatialCellCandidate with the specified id *
    157 0a476497 - * @throw lsst::pex::exceptions::NotFoundException if no candidate matches the id
    ? ^^^^^^ ^
    157 21597d88 + * @throw lsst::pex::exceptions::NotFoundError if no candidate matches the id
    ? ^^ ^ */ SpatialCellCandidate::Ptr SpatialCell::getCandidateById(int id, ///< The desired ID bool noThrow ///< Return NULL in case of error ) { for (SpatialCellCandidateIterator ptr = begin(), end = this->end(); ptr != end; ++ptr) { if ((*ptr)->getId() == id) { return *ptr; } } if (noThrow) { return SpatialCellCandidate::Ptr(); } else {
    171 0a476497 - throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    171 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("Unable to find object with ID == %d") % id).str()); } } /** * Call the visitor's processCandidate method for each Candidate in the SpatialCell * * @note This is obviously similar to the Design Patterns (Go4) Visitor pattern, but we've simplified the * double dispatch (i.e. we don't call a virtual method on SpatialCellCandidate that in turn calls * processCandidate(*this), but can be re-defined) */ void SpatialCell::visitCandidates(CandidateVisitor *visitor, ///< Pass this object to every Candidate int const nMaxPerCell, ///< Visit no more than ///< this many Candidates (<= 0: all) bool const ignoreExceptions, ///< Ignore any exceptions thrown by ///< the processing bool const reset ///< Reset visitor before passing it around ) { if (reset) { visitor->reset(); } int i = 0; for (SpatialCell::iterator candidate = begin(), candidateEnd = end(); candidate != candidateEnd; ++candidate, ++i) { if (nMaxPerCell > 0 && i == nMaxPerCell) { // we've processed all the candidates we want return; } try { visitor->processCandidate((*candidate).get()); } catch(lsst::pex::exceptions::Exception &e) { if (ignoreExceptions) { ; } else { LSST_EXCEPT_ADD(e, "Visiting candidate"); throw e; } } } } /** * Call the visitor's processCandidate method for each Candidate in the SpatialCell (const version) * * This is the const version of SpatialCellSet::visitCandidates * * @todo This is currently implemented via a const_cast (arghhh). The problem is that * SpatialCell::begin() const isn't yet implemented */ void SpatialCell::visitCandidates( CandidateVisitor * visitor, ///< Pass this object to every Candidate int const nMaxPerCell, ///< Visit no more than this many Candidates (-ve: all) bool const ignoreExceptions, ///< Ignore any exceptions thrown by the processing bool const reset ///< Reset visitor before passing it around ) const { #if 1 // // This const_cast must go! // SpatialCell *mthis = const_cast(this); mthis->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, reset); #else int i = 0; for (SpatialCell::const_iterator candidate = (*cell)->begin(), candidateEnd = (*cell)->end(); candidate != candidateEnd; ++candidate, ++i) { if (i == nMaxPerCell) { // we've processed all the candidates we want return; } try { visitor->processCandidate((*candidate).get());
    244 7f098229 - } catch(lsst::pex::exceptions::LengthErrorException &e) {
    ? ---------
    244 21597d88 + } catch(lsst::pex::exceptions::LengthError &e) {
    if (ignoreExceptions) { ; } else { LSST_EXCEPT_ADD(e, "Visiting candidate"); throw e; } } } #endif } /** * Call the visitor's processCandidate method for every Candidate in the SpatialCell * * @sa visitCandidates */ void SpatialCell::visitAllCandidates(CandidateVisitor *visitor, ///< Pass this object to every Candidate bool const ignoreExceptions, ///< Ignore any exceptions thrown by bool const reset ///< Reset visitor before passing it around ) { if (reset) { visitor->reset(); } int i = 0; for (SpatialCell::iterator candidate = begin(false), candidateEnd = end(false); candidate != candidateEnd; ++candidate, ++i) { try { visitor->processCandidate((*candidate).get());
    274 e98ebc6f - } catch(lsst::pex::exceptions::LengthErrorException &e) {
    ? ---------
    274 21597d88 + } catch(lsst::pex::exceptions::LengthError &e) {
    if (ignoreExceptions) { ; } else { LSST_EXCEPT_ADD(e, "Visiting candidate"); throw e; } } } } /** * Call the visitor's processCandidate method for each Candidate in the SpatialCell (const version) * * This is the const version of SpatialCellSet::visitAllCandidates * * @todo This is currently implemented via a const_cast (arghhh). The problem is that * SpatialCell::begin() const isn't yet implemented */ void SpatialCell::visitAllCandidates( CandidateVisitor * visitor, ///< Pass this object to every Candidate bool const ignoreExceptions, ///< Ignore any exceptions thrown by the processing bool const reset ///< Reset visitor before passing it around ) const { #if 1 // // This const_cast must go! // SpatialCell *mthis = const_cast(this); mthis->visitAllCandidates(visitor, ignoreExceptions, reset); #else int i = 0; for (SpatialCell::const_iterator candidate = (*cell)->begin(false), candidateEnd = (*cell)->end(false); candidate != candidateEnd; ++candidate, ++i) { try { visitor->processCandidate((*candidate).get());
    310 e98ebc6f - } catch(lsst::pex::exceptions::LengthErrorException &e) {
    ? ---------
    310 21597d88 + } catch(lsst::pex::exceptions::LengthError &e) {
    if (ignoreExceptions) { ; } else { LSST_EXCEPT_ADD(e, "Visiting candidate"); throw e; } } } #endif } /************************************************************************************************************/ /// ctor; designed to be used to pass begin to SpatialCellCandidateIterator SpatialCellCandidateIterator::SpatialCellCandidateIterator( CandidateList::iterator iterator, ///< Where this iterator should start CandidateList::iterator end, ///< One-past-the-end of iterator's range bool ignoreBad ///< Should we pass over bad Candidates? ) : _iterator(iterator), _end(end), _ignoreBad(ignoreBad) { for (; _iterator != _end; ++_iterator) { (*_iterator)->instantiate(); if (!(_ignoreBad && (*_iterator)->isBad())) { // found a good candidate, or don't care return; } } } /// ctor; designed to be used to pass end to SpatialCellCandidateIterator SpatialCellCandidateIterator::SpatialCellCandidateIterator( CandidateList::iterator, ///< start of of iterator's range; not used CandidateList::iterator end, ///< Where this iterator should start bool ignoreBad, ///< Should we pass over bad Candidates? bool ) : _iterator(end), _end(end), _ignoreBad(ignoreBad) { if (ignoreBad) { // We could decrement end if there are bad Candidates at the end of the list, but it's probably // not worth the trouble } } /** * Advance the iterator, maybe skipping over candidates labelled BAD */ void SpatialCellCandidateIterator::operator++() { if (_iterator != _end) { ++_iterator; } for (; _iterator != _end; ++_iterator) { (*_iterator)->instantiate(); if (!(_ignoreBad && (*_iterator)->isBad())) { // found a good candidate, or don't care return; } } } /** * Return the number of candidate between this and rhs */ size_t SpatialCellCandidateIterator::operator-(SpatialCellCandidateIterator const& rhs) const { size_t n = 0; for (SpatialCellCandidateIterator ptr = rhs; ptr != *this; ++ptr) { if (!(_ignoreBad && (*ptr)->isBad())) { // found a good candidate, or don't care ++n; } } return n; } /** * Dereference the iterator to return the Candidate (if there is one) *
    387 0a476497 - * @throw lsst::pex::exceptions::NotFoundException if no candidate is available
    ? ^^^^^^ ^
    387 21597d88 + * @throw lsst::pex::exceptions::NotFoundError if no candidate is available
    ? ^^ ^ */ SpatialCellCandidate::ConstPtr SpatialCellCandidateIterator::operator*() const { if (_iterator == _end) {
    391 4194637c - throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundException, "Iterator points to end");
    ? ^^^^^^ ^
    391 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Iterator points to end");
    ? ^^ ^ } return *_iterator; } /// Return the CellCandidate::Ptr SpatialCellCandidate::Ptr SpatialCellCandidateIterator::operator*() { if (_iterator == _end) {
    400 4194637c - throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundException, "Iterator points to end");
    ? ^^^^^^ ^
    400 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Iterator points to end");
    ? ^^ ^ } return *_iterator; } /************************************************************************************************************/ /** * Constructor *
    411 4023160c - * @throw lsst::pex::exceptions::LengthErrorException if nx or ny is non-positive
    ? ---------
    411 21597d88 + * @throw lsst::pex::exceptions::LengthError if nx or ny is non-positive
    */ SpatialCellSet::SpatialCellSet(geom::Box2I const& region, ///< Bounding box for %image int xSize, ///< size of cells in the column direction int ySize ///< size of cells in the row direction (0: == xSize) ) : _region(region), _cellList(CellList()) { if (ySize == 0) { ySize = xSize; } if (xSize <= 0 || ySize <= 0) {
    423 4023160c - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    423 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Please specify cells that contain pixels, not %dx%d") % xSize % ySize).str()); } int nx = region.getWidth()/xSize; if (nx*xSize != region.getWidth()) { nx++; } int ny = region.getHeight()/ySize; if (ny*ySize != region.getHeight()) { ny++; } // // N.b. the SpatialCells will be sorted in y at the end of this // int y0 = region.getMinY(); for (int y = 0; y < ny; ++y) { // ny may not be a factor of height int const y1 = (y == ny - 1) ? region.getMaxY() : y0 + ySize - 1; int x0 = region.getMinX(); for (int x = 0; x < nx; ++x) { // nx may not be a factor of width int const x1 = (x == nx - 1) ? region.getMaxX() : x0 + xSize - 1; geom::Box2I bbox(geom::Point2I(x0, y0), geom::Point2I(x1, y1)); std::string label = (boost::format("Cell %dx%d") % x % y).str(); _cellList.push_back(SpatialCell::Ptr(new SpatialCell(label, bbox))); x0 = x1 + 1; } y0 = y1 + 1; } } /************************************************************************************************************/ namespace { struct CellContains : public std::unary_function { CellContains(SpatialCellCandidate::Ptr candidate) : _candidate(candidate) {} bool operator()(SpatialCell::Ptr cell) { return cell->getBBox().contains(geom::Point2I(image::positionToIndex(_candidate->getXCenter()), image::positionToIndex(_candidate->getYCenter()))); } private: SpatialCellCandidate::Ptr _candidate; }; } /** * Insert a candidate into the correct cell */ void SpatialCellSet::insertCandidate(SpatialCellCandidate::Ptr candidate) { CellList::iterator pos = std::find_if(_cellList.begin(), _cellList.end(), CellContains(candidate)); if (pos == _cellList.end()) {
    482 4023160c - throw LSST_EXCEPT(lsst::pex::exceptions::OutOfRangeException,
    ? ^^^^^^ ^
    482 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::OutOfRangeError,
    ? ^^ ^ (boost::format("Unable to insert a candidate at (%.2f, %.2f)") % candidate->getXCenter() % candidate->getYCenter()).str()); } (*pos)->insertCandidate(candidate); } /************************************************************************************************************/ /// /// Rearrange the Candidates in all SpatialCells to reflect their current ratings /// void SpatialCellSet::sortCandidates() { for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) { (*cell)->sortCandidates(); } } /************************************************************************************************************/ /** * Call the visitor's processCandidate method for each Candidate in the SpatialCellSet * * @note This is obviously similar to the Design Patterns (Go4) Visitor pattern, but we've simplified the * double dispatch (i.e. we don't call a virtual method on SpatialCellCandidate that in turn calls * processCandidate(*this), but can be re-defined) */ void SpatialCellSet::visitCandidates( CandidateVisitor *visitor, ///< Pass this object to every Candidate int const nMaxPerCell, ///< Visit no more than this many Candidates (<= 0: all) bool const ignoreExceptions ///< Ignore any exceptions thrown by the processing ) { visitor->reset(); for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) { (*cell)->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, false); } } /** * Call the visitor's processCandidate method for each Candidate in the SpatialCellSet (const version) * * This is the const version of SpatialCellSet::visitCandidates */ void SpatialCellSet::visitCandidates( CandidateVisitor *visitor, ///< Pass this object to every Candidate int const nMaxPerCell, ///< Visit no more than this many Candidates (-ve: all) bool const ignoreExceptions ///< Ignore any exceptions thrown by the processing ) const { visitor->reset(); for (CellList::const_iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) { SpatialCell const *ccell = cell->get(); // the SpatialCellSet's SpatialCells should be const too ccell->visitCandidates(visitor, nMaxPerCell, ignoreExceptions, false); } } /************************************************************************************************************/ /** * Call the visitor's processCandidate method for every Candidate in the SpatialCellSet * * @sa visitCandidates */ void SpatialCellSet::visitAllCandidates( CandidateVisitor *visitor, ///< Pass this object to every Candidate bool const ignoreExceptions ///< Ignore any exceptions thrown by the processing ) { visitor->reset(); for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) { (*cell)->visitAllCandidates(visitor, ignoreExceptions, false); } } /** * Call the visitor's processCandidate method for every Candidate in the SpatialCellSet (const version) * * This is the const version of SpatialCellSet::visitAllCandidates */ void SpatialCellSet::visitAllCandidates( CandidateVisitor *visitor, ///< Pass this object to every Candidate bool const ignoreExceptions ///< Ignore any exceptions thrown by the processing ) const { visitor->reset(); for (CellList::const_iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) { SpatialCell const *ccell = cell->get(); // the SpatialCellSet's SpatialCells should be const too ccell->visitAllCandidates(visitor, ignoreExceptions, false); } } /************************************************************************************************************/ /** * Return the SpatialCellCandidate with the specified id *
    578 0a476497 - * @throw lsst::pex::exceptions::NotFoundException if no candidate matches the id (unless noThrow
    ? ^^^^^^ ^
    578 21597d88 + * @throw lsst::pex::exceptions::NotFoundError if no candidate matches the id (unless noThrow
    ? ^^ ^ * is true, in which case a Ptr(NULL) is returned */ SpatialCellCandidate::Ptr SpatialCellSet::getCandidateById(int id, ///< The desired ID bool noThrow ///< Return NULL in case of error ) { for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) { SpatialCellCandidate::Ptr cand = (*cell)->getCandidateById(id, true); if (cand) { return cand; } } if (noThrow) { return SpatialCellCandidate::Ptr(); } else {
    595 0a476497 - throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    595 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("Unable to find object with ID == %d") % id).str()); } } /// Set whether we should omit BAD candidates from candidate list when traversing void SpatialCellSet::setIgnoreBad(bool ignoreBad) { for (CellList::iterator cell = _cellList.begin(), end = _cellList.end(); cell != end; ++cell) { (*cell)->setIgnoreBad(ignoreBad); } } }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0a476497

    commit 0a476497955b44e2cf971712345df0d09f57dc08
    Author: rhl 
    Date:   Fri Oct 23 19:49:18 2009 +0000
    
        Add getCandidateById; #993
    

    6fc337ad

    commit 6fc337adb1018165c9ff6f94042335462f891015
    Author: rhl 
    Date:   Sun Mar 8 06:20:31 2009 +0000
    
        Implemented a visitor for the Candidates in SpatialCells
    

    4023160c

    commit 4023160c92a3f2e7a1520562110db2b78fe0ada3
    Author: rhl 
    Date:   Sun Mar 1 19:11:37 2009 +0000
    
        Implemented SpatialCellList
    

    4194637c

    commit 4194637c5379bf25666c138cc8683860295f51ae
    Author: rhl 
    Date:   Thu Mar 5 22:05:02 2009 +0000
    
        Rework SpatialCell to present an iterator-based view of lists of candidates
    

    b6bc9c01

    commit b6bc9c011896f1c2196b0b7e7a29d440746b38cb
    Author: Paul Price 
    Date:   Thu May 31 16:57:25 2012 -0400
    
        Allow a candidate to be removed from the cell.
    

    e98ebc6f

    commit e98ebc6fdb69187b6af7338ec959f3c78532c4b3
    Author: rhl 
    Date:   Sat Apr 17 23:59:28 2010 +0000
    
        Added visitAllCandidates to visit every candidate, good or bad
    

    7f098229

    commit 7f09822926b0747b1c1ced7c089fb9c65bc1e679
    Author: rhl 
    Date:   Wed Dec 30 22:30:52 2009 +0000
    
        Added ability of visit all the candidates in a SpatialCell (not just a SpatialCellSet);  started working on an example to be part of the documentation
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/detection/FootprintFunctor.h

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #if !defined(LSST_DETECTION_FOOTPRINT_FUNCTOR_H)
                    #define LSST_DETECTION_FOOTPRINT_FUNCTOR_H
                    
                    #include "lsst/afw/detection/Footprint.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    
                    namespace lsst {
                    namespace afw { 
                    namespace detection {
                    /************************************************************************************************************/
                    /**
                     * \brief A functor class to allow users to process all the pixels in a Footprint
                     *
                     * There's an annotated example of a FootprintFunctor in action
                     * \link FootprintFunctorsExample FootprintFunctors here\endlink
                     */
                    template 
                    class FootprintFunctor {
                    public:
                        FootprintFunctor(ImageT const& image    ///< The image that the Footprint lives in
                                        ) : _image(image) {}
                    
                        virtual ~FootprintFunctor() = 0;
                    
                        /**
                         * A function that's called at the beginning of apply; useful if apply
                         * calculates a per-footprint quantity
                         */
                        virtual void reset() {}
                        virtual void reset(Footprint const&) {}
                    
                        /**
                         * \brief Apply operator() to each pixel in the Footprint
                         */
                        void apply(Footprint const& foot,   ///< The Footprint in question
                                   int const margin=0       ///< The required margin from the edge of the image
                                  ) {
                            reset();
                            reset(foot);
                    
                            if (foot.getSpans().empty()) {
                                return;
                            }
                    
                            geom::Box2I const bbox = foot.getBBox();
                            geom::Box2I region = foot.getRegion();
                            if (!region.isEmpty() &&
                                (!region.contains(bbox.getMin()) || !region.contains(bbox.getMax()))) {
                                throw LSST_EXCEPT(
    
    72 17d1d529 - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    72 21597d88 + lsst::pex::exceptions::LengthError,
    (boost::format("Footprint with BBox (%d,%d) -- (%dx%d)" "doesn't fit in image with BBox (%d,%d) -- (%dx%d)" ) % bbox.getMinX() % bbox.getMinY() % bbox.getMaxX() % bbox.getMaxY() % region.getMinX() % region.getMinY() % region.getMaxX() % region.getMaxY() ).str() ); } // Current position of the locator (in the SpanList loop) int ox1 = 0, oy = 0; int const x0 = _image.getX0(); int const y0 = _image.getY0(); typename ImageT::xy_locator loc = _image.xy_at(-x0, -y0); // Origin of the Image's pixels int const width = _image.getWidth(); int const height = _image.getHeight(); for (Footprint::SpanList::const_iterator siter = foot.getSpans().begin(); siter != foot.getSpans().end(); siter++) { Span::Ptr const span = *siter; int const y = span->getY(); if (y - y0 < margin || y - y0 >= height - margin) { continue; } int sx0 = span->getX0(); int sx1 = span->getX1(); if (sx0 - x0 < margin) { sx0 = margin + x0; } if (sx1 - x0 >= width - margin) { sx1 = width + x0 - margin - 1; } loc += lsst::afw::image::pair2I(sx0 - ox1, y - oy); for (int x = sx0; x <= sx1; ++x, ++loc.x()) { operator()(loc, x, y); } ox1 = sx1 + 1; oy = y; } } /// Return the image ImageT const& getImage() const { return _image; } /// The operator to be applied to each pixel in the Footprint. /// /// N.b. the coordinates (x, y) are relative to the origin of the image's parent /// if it exists (i.e. they obey getX0/getY0) virtual void operator()(typename ImageT::xy_locator loc, int x, int y) = 0; private: ImageT const _image; // The image that the Footprints live in }; /// /// Although FootprintFunctor is pure virtual, this is needed by subclasses /// /// It wasn't defined in the class body as I want swig to know that the class is pure virtual /// template FootprintFunctor::~FootprintFunctor() {} }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    17d1d529

    commit 17d1d529ed63e98f98e5d1a7a7da4811e95fc26c
    Author: dubcovsky 
    Date:   Tue Feb 15 00:00:43 2011 +0000
    
        #1556 Split Footprint.h into Threshold.h, FootprintSet.h, and FootprintFunctor.h, to correspond with class names. Added a constructors to Footprint which use geom objects (BoxI and Ellipse) to construct footprints. Footprints now exclusively use geom::PointI and geom::BoxI internally. (but still accept image::PointI and image::BBox for backwards compatibility wherever possible). FootprintArray.h contains a static functions to flatten and expand ndarrays using a Footprint to map between 2-d and 1-d indices.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/image/Filter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    //
                    //##====----------------                                ----------------====##/
                    //
                    //! \file
                    //! \brief  Implements looking up a filter identifier by name.
                    //
                    //##====----------------                                ----------------====##/
                    
                    #include "boost/format.hpp"
                    #include "boost/algorithm/string/trim.hpp"
                    #include "lsst/pex/exceptions.h"
                    
                    #include "lsst/afw/image/Filter.h"
                    
                    namespace pexEx = lsst::pex::exceptions;
                    
                    namespace lsst { namespace afw { namespace image {
                    
                    FilterProperty::PropertyMap *FilterProperty::_propertyMap = NULL;
                    
                    FilterProperty::FilterProperty(
                        std::string const& name, ///< name of filter
                        lsst::daf::base::PropertySet const& prop, ///< values describing the Filter
                        bool force        ///< Allow this name to replace a previous one
                        ) : _name(name), _lambdaEff(-1)
                    {
                        if (prop.exists("lambdaEff")) {
                            _lambdaEff = prop.getAsDouble("lambdaEff");
                        }
                        _insert(force);
                    }
                    
                    
                    /**
                     * Create a new FilterProperty, setting values from a Policy
                     */
                    FilterProperty::FilterProperty(std::string const& name, ///< name of filter
                                                   lsst::pex::policy::Policy const& pol, ///< values describing the Filter
                                                   bool force        ///< Allow this name to replace a previous one
                                                  ) : _name(name), _lambdaEff(-1)
                    {
                        if (pol.exists("lambdaEff")) {
                            _lambdaEff = pol.getDouble("lambdaEff");
                        }
                        _insert(force);
                    }
                    
                    /**
                     * Insert FilterProperty into registry
                     */
                    void FilterProperty::_insert(
                        bool force                   ///< Allow this name to replace a previous one?
                        )
                    {
                        if (!_propertyMap) {
                            _initRegistry();
                        }
                    
                        PropertyMap::iterator keyVal = _propertyMap->find(getName());
                    
                        if (keyVal != _propertyMap->end()) {
                            if (keyVal->second == *this) {
                                return;                     // OK, a redefinition with identical values
                            }
                    
                            if (!force) {
    
    91 72fa3478 - throw LSST_EXCEPT(pexEx::RuntimeErrorException, "Filter " + getName() + " is already defined");
    ? ---------
    91 21597d88 + throw LSST_EXCEPT(pexEx::RuntimeError, "Filter " + getName() + " is already defined");
    } _propertyMap->erase(keyVal); } _propertyMap->insert(std::make_pair(getName(), *this)); } /** * Return true iff two FilterProperties are identical */ bool FilterProperty::operator==(FilterProperty const& rhs ///< Object to compare with this ) const { return (_lambdaEff == rhs._lambdaEff); } /** * Initialise the Filter registry */ void FilterProperty::_initRegistry() { if (_propertyMap) { delete _propertyMap; } _propertyMap = new PropertyMap; } /** * Lookup the properties of a filter "name" */ FilterProperty const& FilterProperty::lookup(std::string const& name ///< name of desired filter ) { if (!_propertyMap) { _initRegistry(); } PropertyMap::iterator keyVal = _propertyMap->find(name); if (keyVal == _propertyMap->end()) {
    134 c0a261f9 - throw LSST_EXCEPT(pexEx::NotFoundException, "Unable to find filter " + name);
    ? ^^^^^^ ^
    134 21597d88 + throw LSST_EXCEPT(pexEx::NotFoundError, "Unable to find filter " + name);
    ? ^^ ^ } return keyVal->second; } /************************************************************************************************************/ namespace { std::string const unknownFilter = "_unknown_"; } /** * Create a Filter from a PropertySet (e.g. a FITS header) */ Filter::Filter(CONST_PTR(lsst::daf::base::PropertySet) metadata, ///< Metadata to process (e.g. a IFITS header) bool const force ///< Allow us to construct an unknown Filter ) { std::string const key = "FILTER"; if( metadata->exists(key) ) { std::string filterName = boost::algorithm::trim_right_copy(metadata->getAsString(key)); _id = _lookup(filterName, force); _name = filterName; } } namespace detail { /** * Remove Filter-related keywords from the metadata * * \return Number of keywords stripped */ int stripFilterKeywords(PTR(lsst::daf::base::PropertySet) metadata ///< Metadata to be stripped ) { int nstripped = 0; std::string key = "FILTER"; if (metadata->exists(key)) { metadata->remove(key); nstripped++; } return nstripped; } } /** * Return a list of known filters */ std::vector Filter::getNames() { if (!_nameMap) { _initRegistry(); } std::vector names; for (NameMap::const_iterator ptr = _nameMap->begin(), end = _nameMap->end(); ptr != end; ++ptr) { if (ptr->first != unknownFilter) { names.push_back(ptr->first); } } std::sort(names.begin(), names.end()); return names; } /** * Are two filters identical? */ bool Filter::operator==(Filter const& rhs) const { return _id != UNKNOWN && _id == rhs._id; } /************************************************************************************************************/ /** * Initialise the Filter registry */ void Filter::_initRegistry() { _id0 = UNKNOWN; delete _aliasMap; delete _nameMap; delete _idMap; _aliasMap = new AliasMap; _nameMap = new NameMap; _idMap = new IdMap; define(FilterProperty(unknownFilter, lsst::pex::policy::Policy(), true)); } /************************************************************************************************************/ int Filter::_id0 = Filter::UNKNOWN; Filter::AliasMap *Filter::_aliasMap = NULL; // dynamically allocated as that avoids an intel bug with static // variables in dynamic libraries Filter::NameMap *Filter::_nameMap = NULL; // dynamically allocated as that avoids an intel bug with static // variables in dynamic libraries Filter::IdMap *Filter::_idMap = NULL; // dynamically allocated as that avoids an intel bug with static // variables in dynamic libraries /** * Define a filter name to have the specified id * * If id == Filter::AUTO a value will be chosen for you. * * It is an error to attempt to change a name's id (unless you specify force) */ int Filter::define(FilterProperty const& fp, int id, bool force) { if (!_nameMap) { _initRegistry(); } std::string const& name = fp.getName(); NameMap::iterator keyVal = _nameMap->find(name); if (keyVal != _nameMap->end()) { int oid = keyVal->second; if (id == oid || id == AUTO) { return oid; // OK, same value as before } if (!force) {
    262 c0a261f9 - throw LSST_EXCEPT(pexEx::RuntimeErrorException, "Filter " + name + " is already defined");
    ? ---------
    262 21597d88 + throw LSST_EXCEPT(pexEx::RuntimeError, "Filter " + name + " is already defined");
    } _nameMap->erase(keyVal); _idMap->erase(oid); } if (id == AUTO) { id = _id0; ++_id0; } _nameMap->insert(std::make_pair(name, id)); _idMap->insert(std::make_pair(id, name)); return id; } /** * Define an alias for a filter */ int Filter::defineAlias(std::string const& oldName, ///< old name for Filter std::string const& newName, ///< new name for Filter bool force ///< force an alias even if newName is already in use ) { if (!_nameMap) { _initRegistry(); } // Lookup oldName NameMap::iterator keyVal = _nameMap->find(oldName); if (keyVal == _nameMap->end()) {
    294 523afe02 - throw LSST_EXCEPT(pexEx::NotFoundException, "Unable to find filter " + oldName);
    ? ^^^^^^ ^
    294 21597d88 + throw LSST_EXCEPT(pexEx::NotFoundError, "Unable to find filter " + oldName);
    ? ^^ ^ } int const id = keyVal->second; // Lookup oldName in aliasMap AliasMap::iterator aliasKeyVal = _aliasMap->find(newName); if (aliasKeyVal != _aliasMap->end()) { if (aliasKeyVal->second == oldName) { return id; // OK, same value as before } if (!force) {
    306 523afe02 - throw LSST_EXCEPT(pexEx::NotFoundException, "Filter " + newName + " is already defined");
    ? ^^^^^^ ^
    306 21597d88 + throw LSST_EXCEPT(pexEx::NotFoundError, "Filter " + newName + " is already defined");
    ? ^^ ^ } _aliasMap->erase(aliasKeyVal); } _aliasMap->insert(std::make_pair(newName, oldName)); return id; } /** * Lookup the ID associated with a name */ int Filter::_lookup(std::string const& name, // Name of filter bool const force // return an invalid ID, but don't throw, if name is unknown ) { if (!_nameMap) { _initRegistry(); } NameMap::iterator keyVal = _nameMap->find(name); if (keyVal == _nameMap->end()) { AliasMap::iterator aliasKeyVal = _aliasMap->find(name); if (aliasKeyVal != _aliasMap->end()) { return _lookup(aliasKeyVal->second); } if (force) { return UNKNOWN; } else {
    338 523afe02 - throw LSST_EXCEPT(pexEx::NotFoundException, "Unable to find filter " + name);
    ? ^^^^^^ ^
    338 21597d88 + throw LSST_EXCEPT(pexEx::NotFoundError, "Unable to find filter " + name);
    ? ^^ ^ } } return keyVal->second; } /** * Lookup the name associated with an ID */ std::string const& Filter::_lookup(int id) { if (!_idMap) { _initRegistry(); } IdMap::iterator keyVal = _idMap->find(id); if (keyVal == _idMap->end()) {
    357 c0a261f9 - throw LSST_EXCEPT(pexEx::NotFoundException, (boost::format("Unable to find filter %d") % id).str());
    ? ^^^^^^ ^
    357 21597d88 + throw LSST_EXCEPT(pexEx::NotFoundError, (boost::format("Unable to find filter %d") % id).str());
    ? ^^ ^ } return keyVal->second; } /** * Return a Filter's FilterProperty */ FilterProperty const& Filter::getFilterProperty() const { // // Map name to its ID and back to resolve aliases // int const id = _lookup(_name, true); std::string const& name = (id == UNKNOWN) ? _name : _lookup(id); return FilterProperty::lookup(name); } }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    72fa3478

    commit 72fa34789b0b5a2c1b6d677f9e3d45684d565518
    Author: Paul Price 
    Date:   Fri Jan 20 16:15:51 2012 -0500
    
        Support Filter with pex_config.
    

    c0a261f9

    commit c0a261f94bf77d4fe5cfdcf40fa259d5a2486a3e
    Author: rhl 
    Date:   Thu Apr 1 18:07:05 2010 +0000
    
        Rewrite Filter class to be independent of the DB
    

    523afe02

    commit 523afe0228eb898987ab8881925146f4e04091e0
    Author: rhl 
    Date:   Wed Apr 28 21:02:15 2010 +0000
    
        Allow a Filter to be created with an unknown name (if you set force=true), but you can't use it for anything but recovering its name; allow filter aliases in the .paf files
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/table/tableLib.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define tableLib_DOCSTRING
                    "
                    Python interface to lsst::afw::table classes
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.table", docstring=tableLib_DOCSTRING) tableLib
                    
                    #pragma SWIG nowarn=389                 // operator[]  ignored
                    #pragma SWIG nowarn=503                 // comparison operators ignored
                    #pragma SWIG nowarn=520                 // base class not similarly marked as smart pointer
                    #pragma SWIG nowarn=401                 // nothing known about base class
                    #pragma SWIG nowarn=302                 // redefine identifier (SourceSet<> -> SourceSet)
                    
                    %include "lsst/p_lsstSwig.i"
                    
    
    40 853c5734 + %initializeNumPy(afw_table)
    41 853c5734 + %{
    42 853c5734 + #include "ndarray/swig.h"
    43 853c5734 + #include "ndarray/swig/eigen.h"
    44 853c5734 + %}
    45 853c5734 + %include "ndarray.i"
    46 853c5734 +
    %lsst_exceptions() %include "Base.i" %include "Simple.i"
    51 fbe6dc40 + %include "aggregates.i"
    %include "Source.i" %include "Match.i" %include "Exposure.i"
    55 5046e7f3 + %include "AmpInfo.i"
    56 f9fa5877 + %include "arrays.i"

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    fbe6dc40

    commit fbe6dc4041a65f8b7fb0d57c1bd7e3d24a2b57c1
    Author: pgee 
    Date:   Mon Jul 21 08:14:14 2014 -0700
    
        Fix problem with SWIG types when Source.h routines return functorKeys.  Also, remove extra /* from a previous checkin.
    

    5046e7f3

    commit 5046e7f3f0a4f8591e21a396b1e1ee0dd205f659
    Author: Russell Owen 
    Date:   Thu Feb 13 17:35:58 2014 -0800
    
        Got the basics of AmpInfo catalogs working.
        However, I don't know how to SWIG-wrap ConstAmpInfoCatalog, and it looks messy,
        so I will try making Detector's constructor take a non-const catalog
        and copying that internally to a const catalog. (I should then test that
        changing the original catalog does not change the one inside Detector).
    

    f9fa5877

    commit f9fa5877d27976c5bbec22173b33e1337aa420fa
    Author: Jim Bosch 
    Date:   Thu Sep 18 17:21:34 2014 -0400
    
        Add FunctorKey for arrays
    

    853c5734

    commit 853c5734ee13f55fd35e9e18ed5ac69a0073b97f
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:18:28 2015 -0400
    
        Utilize new numeric scalar typemaps and NumPy import macro.
    

    Return to list

    python/lsst/afw/geom/Box.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    %{
                    #include "lsst/afw/geom/Box.h"
                    %}
                    
                    %ignore lsst::afw::geom::Box2I::getSlices;
                    %rename(set) lsst::afw::geom::Box2I::operator=;
                    %useValueEquality(lsst::afw::geom::Box2I);
                    %copyctor lsst::afw::geom::Box2I;
                    %rename(set) lsst::afw::geom::Box2D::operator=;
                    %useValueEquality(lsst::afw::geom::Box2D);
                    %copyctor lsst::afw::geom::Box2D;
                    
                    %include "lsst/afw/geom/Box.h"
                    
                    %extend lsst::afw::geom::Box2I {             
    
    39 a8e2a7e9 - %pythoncode {
    39 81c3bd10 + %pythoncode %{
    ? + Extent = Extent2I Point = Point2I def __repr__(self): return "Box2I(%r, %r)" % (self.getMin(), self.getDimensions()) def __reduce__(self): return (Box2I, (self.getMin(), self.getMax())) def __str__(self): return "Box2I(%s, %s)" % (self.getMin(), self.getMax()) def getSlices(self): return (slice(self.getBeginY(), self.getEndY()), slice(self.getBeginX(), self.getEndX()))
    53 386a4b71 - def getCorners(self):
    54 386a4b71 - return (
    55 386a4b71 - self.getMin(),
    56 386a4b71 - self.Point(self.getMaxX(), self.getMinY()),
    57 386a4b71 - self.getMax(),
    58 386a4b71 - self.Point(self.getMinX(), self.getMaxY())
    59 386a4b71 - )
    60 4e875d59 -
    61 a8e2a7e9 - }
    53 81c3bd10 + %}
    ? + } %extend lsst::afw::geom::Box2D {
    65 a8e2a7e9 - %pythoncode {
    57 81c3bd10 + %pythoncode %{
    ? + Extent = Extent2D Point = Point2D def __repr__(self): return "Box2D(%r, %r)" % (self.getMin(), self.getDimensions()) def __reduce__(self): return (Box2D, (self.getMin(), self.getDimensions())) def __str__(self): return "Box2D(%s, %s)" % (self.getMin(), self.getMax())
    76 3c729db1 - def getCorners(self):
    77 3c729db1 - return (
    78 3c729db1 - self.getMin(),
    79 3c729db1 - self.Point(self.getMaxX(), self.getMinY()),
    80 3c729db1 - self.getMax(),
    81 3c729db1 - self.Point(self.getMinX(), self.getMaxY())
    82 3c729db1 - )
    83 3c729db1 -
    84 a8e2a7e9 - }
    68 81c3bd10 + %}
    ? + }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    386a4b71

    commit 386a4b71d974d9e5672fe8690d0db3e56c9fb40f
    Author: Jim Bosch 
    Date:   Thu May 24 14:35:39 2012 -0400
    
        added corners accessor to Box (#2100)
    

    4e875d59

    commit 4e875d592fd797dd905148c1b1482da089714d5a
    Merge: 086a11c 4b0a64c
    Author: Steven Bickerton 
    Date:   Tue Jun 12 09:18:46 2012 -0500
    
        merged in master on tickets/2128
    

    a8e2a7e9

    commit a8e2a7e9666f30c2384ae6bb3557181f65684db7
    Author: jbosch 
    Date:   Mon Dec 21 23:37:41 2009 +0000
    
        afw/#1095 - swig wrappers, some tests for BoxI and BoxD.
    

    3c729db1

    commit 3c729db15e2ae7c5a653610e08262554d6d42fd9
    Author: Jim Bosch 
    Date:   Fri Jun 29 15:43:20 2012 -0400
    
        fix for #2185 (Box2D.getCorners() is broken)
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    src/math/LinearCombinationKernel.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/format.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/FunctionLibrary.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/KernelPersistenceHelper.h"
                    #include "lsst/afw/geom.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace afwMath = lsst::afw::math;
                    namespace afwImage = lsst::afw::image;
                    namespace afwGeom = lsst::afw::geom;
                    
                    afwMath::LinearCombinationKernel::LinearCombinationKernel()
                    :
                        Kernel(),
                        _kernelList(),
                        _kernelImagePtrList(),
                        _kernelSumList(),
                        _kernelParams(),
                        _isDeltaFunctionBasis(false)
                    { }
                    
                    afwMath::LinearCombinationKernel::LinearCombinationKernel(
                        KernelList const &kernelList,
                        std::vector const &kernelParameters
                    ) :
                        Kernel(kernelList[0]->getWidth(), kernelList[0]->getHeight(), kernelList.size()),
                        _kernelList(),
                        _kernelImagePtrList(),
                        _kernelSumList(),
                        _kernelParams(kernelParameters),
                        _isDeltaFunctionBasis(false)
                    {
                        if (kernelList.size() != kernelParameters.size()) {
                            std::ostringstream os;
                            os << "kernelList.size() = " << kernelList.size()
                                << " != " << kernelParameters.size() << " = " << "kernelParameters.size()";
    
    67 d7b24982 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    67 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } checkKernelList(kernelList); _setKernelList(kernelList); } afwMath::LinearCombinationKernel::LinearCombinationKernel( KernelList const &kernelList, Kernel::SpatialFunction const &spatialFunction ) : Kernel(kernelList[0]->getWidth(), kernelList[0]->getHeight(), kernelList.size(), spatialFunction), _kernelList(), _kernelImagePtrList(), _kernelSumList(), _kernelParams(std::vector(kernelList.size())), _isDeltaFunctionBasis(false) { checkKernelList(kernelList); _setKernelList(kernelList); } afwMath::LinearCombinationKernel::LinearCombinationKernel( KernelList const &kernelList, std::vector const &spatialFunctionList ) : Kernel(kernelList[0]->getWidth(), kernelList[0]->getHeight(), spatialFunctionList), _kernelList(), _kernelImagePtrList(), _kernelSumList(), _kernelParams(std::vector(kernelList.size())), _isDeltaFunctionBasis(false) { if (kernelList.size() != spatialFunctionList.size()) { std::ostringstream os; os << "kernelList.size() = " << kernelList.size() << " != " << spatialFunctionList.size() << " = " << "spatialFunctionList.size()";
    103 d7b24982 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    103 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } checkKernelList(kernelList); _setKernelList(kernelList); } PTR(afwMath::Kernel) afwMath::LinearCombinationKernel::clone() const { PTR(Kernel) retPtr; if (this->isSpatiallyVarying()) { retPtr.reset(new afwMath::LinearCombinationKernel(this->_kernelList, this->_spatialFunctionList)); } else { retPtr.reset(new afwMath::LinearCombinationKernel(this->_kernelList, this->_kernelParams)); } retPtr->setCtr(this->getCtr()); return retPtr; } void afwMath::LinearCombinationKernel::checkKernelList(const KernelList &kernelList) const { if (kernelList.size() < 1) {
    122 1b384e16 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "kernelList has no elements");
    ? ^^^^^^ ^
    122 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "kernelList has no elements");
    ? ^^ ^ } afwGeom::Extent2I const dim0 = kernelList[0]->getDimensions(); afwGeom::Point2I const ctr0 = kernelList[0]->getCtr(); for (unsigned int ii = 0; ii < kernelList.size(); ++ii) { if (kernelList[ii]->getDimensions() != dim0) {
    130 1b384e16 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    130 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ (boost::format("kernel %d has different size than kernel 0") % ii).str()); } if (kernelList[ii]->getCtr() != ctr0) {
    134 65c3fa0d - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    134 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ (boost::format("kernel %d has different center than kernel 0") % ii).str()); } if (kernelList[ii]->isSpatiallyVarying()) {
    138 1b384e16 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    138 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ (boost::format("kernel %d is spatially varying") % ii).str()); } } } afwMath::KernelList const & afwMath::LinearCombinationKernel::getKernelList() const { return _kernelList; } std::vector afwMath::LinearCombinationKernel::getKernelSumList() const { return _kernelSumList; } std::vector afwMath::LinearCombinationKernel::getKernelParameters() const { return _kernelParams; } PTR(afwMath::Kernel) afwMath::LinearCombinationKernel::refactor() const { if (!this->isSpatiallyVarying()) { return PTR(Kernel)(); } Kernel::SpatialFunctionPtr const firstSpFuncPtr = this->_spatialFunctionList[0]; if (!firstSpFuncPtr->isLinearCombination()) { return PTR(Kernel)(); } typedef lsst::afw::image::Image KernelImage; typedef boost::shared_ptr KernelImagePtr; typedef std::vector KernelImageList; // create kernel images for new refactored basis kernels int const nSpatialParameters = this->getNSpatialParameters(); KernelImageList newKernelImagePtrList; newKernelImagePtrList.reserve(nSpatialParameters); for (int i = 0; i < nSpatialParameters; ++i) { KernelImagePtr kernelImagePtr(new KernelImage(this->getDimensions())); newKernelImagePtrList.push_back(kernelImagePtr); } KernelImage kernelImage(this->getDimensions()); std::vector::const_iterator spFuncPtrIter = this->_spatialFunctionList.begin(); afwMath::KernelList::const_iterator kIter = _kernelList.begin(); afwMath::KernelList::const_iterator const kEnd = _kernelList.end(); for ( ; kIter != kEnd; ++kIter, ++spFuncPtrIter) { if (typeid(**spFuncPtrIter) != typeid(*firstSpFuncPtr)) { return PTR(Kernel)(); } (**kIter).computeImage(kernelImage, false); for (int i = 0; i < nSpatialParameters; ++i) { double spParam = (*spFuncPtrIter)->getParameter(i); newKernelImagePtrList[i]->scaledPlus(spParam, kernelImage); } } // create new kernel; the basis kernels are fixed kernels computed above // and the corresponding spatial model is the same function as the original kernel, // but with all coefficients zero except coeff_i = 1.0 afwMath::KernelList newKernelList; newKernelList.reserve(nSpatialParameters); KernelImageList::iterator newKImPtrIter = newKernelImagePtrList.begin(); KernelImageList::iterator const newKImPtrEnd = newKernelImagePtrList.end(); for ( ; newKImPtrIter != newKImPtrEnd; ++newKImPtrIter) { newKernelList.push_back(PTR(Kernel)(new afwMath::FixedKernel(**newKImPtrIter))); } std::vector newSpFunctionPtrList; for (int i = 0; i < nSpatialParameters; ++i) { std::vector newSpParameters(nSpatialParameters, 0.0); newSpParameters[i] = 1.0; SpatialFunctionPtr newSpFunctionPtr = firstSpFuncPtr->clone(); newSpFunctionPtr->setParameters(newSpParameters); newSpFunctionPtrList.push_back(newSpFunctionPtr); } PTR(LinearCombinationKernel) refactoredKernel( new LinearCombinationKernel(newKernelList, newSpFunctionPtrList)); refactoredKernel->setCtr(this->getCtr()); return refactoredKernel; } std::string afwMath::LinearCombinationKernel::toString(std::string const& prefix) const { std::ostringstream os; os << prefix << "LinearCombinationKernel:" << std::endl; os << prefix << "..Kernels:" << std::endl; for (KernelList::const_iterator i = _kernelList.begin(); i != _kernelList.end(); ++i) { os << (*i)->toString(prefix + "\t"); } os << "..parameters: [ "; for (std::vector::const_iterator i = _kernelParams.begin(); i != _kernelParams.end(); ++i) { if (i != _kernelParams.begin()) os << ", "; os << *i; } os << " ]" << std::endl; os << Kernel::toString(prefix + "\t"); return os.str(); } // // Protected Member Functions // double afwMath::LinearCombinationKernel::doComputeImage( afwImage::Image &image, bool doNormalize ) const { image = 0.0; double imSum = 0.0; std::vector)>::const_iterator kImPtrIter = _kernelImagePtrList.begin(); std::vector::const_iterator kSumIter = _kernelSumList.begin(); std::vector::const_iterator kParIter = _kernelParams.begin(); for ( ; kImPtrIter != _kernelImagePtrList.end(); ++kImPtrIter, ++kSumIter, ++kParIter) { image.scaledPlus(*kParIter, **kImPtrIter); imSum += (*kSumIter) * (*kParIter); } if (doNormalize) { if (imSum == 0) {
    254 92570c02 - throw LSST_EXCEPT(pexExcept::OverflowErrorException, "Cannot normalize; kernel sum is 0");
    ? ---------
    254 21597d88 + throw LSST_EXCEPT(pexExcept::OverflowError, "Cannot normalize; kernel sum is 0");
    } image /= imSum; imSum = 1; } return imSum; } void afwMath::LinearCombinationKernel::setKernelParameter(unsigned int ind, double value) const { this->_kernelParams[ind] = value; } // // Private Member Functions // void afwMath::LinearCombinationKernel::_setKernelList(KernelList const &kernelList) { _kernelSumList.clear(); _kernelImagePtrList.clear(); _kernelList.clear(); _isDeltaFunctionBasis = true; for (KernelList::const_iterator kIter = kernelList.begin(), kEnd = kernelList.end(); kIter != kEnd; ++kIter) { PTR(Kernel) basisKernelPtr = (*kIter)->clone(); if (dynamic_cast(&(*basisKernelPtr)) == 0) { _isDeltaFunctionBasis = false; } _kernelList.push_back(basisKernelPtr); PTR(afwImage::Image) kernelImagePtr(new afwImage::Image(this->getDimensions())); _kernelSumList.push_back(basisKernelPtr->computeImage(*kernelImagePtr, false)); _kernelImagePtrList.push_back(kernelImagePtr); } } // ------ Persistence --------------------------------------------------------------------------------------- namespace lsst { namespace afw { namespace math { namespace { struct LinearCombinationKernelPersistenceHelper : public Kernel::PersistenceHelper { table::Key< table::Array > amplitudes; table::Key< table::Array > components; LinearCombinationKernelPersistenceHelper(int nComponents, bool isSpatiallyVarying) : Kernel::PersistenceHelper(isSpatiallyVarying ? nComponents : 0), components( schema.addField< table::Array >("components", "archive IDs of component kernel", nComponents) ) { if (!isSpatiallyVarying) { amplitudes = schema.addField< table::Array >("amplitudes", "amplitudes component kernel", nComponents); } } LinearCombinationKernelPersistenceHelper(table::Schema const & schema_) : Kernel::PersistenceHelper(schema_), components(schema["components"]) { if (!spatialFunctions.isValid()) { amplitudes = schema["amplitudes"]; LSST_ARCHIVE_ASSERT(amplitudes.getSize() == components.getSize()); } else { LSST_ARCHIVE_ASSERT(spatialFunctions.getSize() == components.getSize()); } } }; } // anonymous class LinearCombinationKernel::Factory : public afw::table::io::PersistableFactory { public: virtual PTR(afw::table::io::Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const { LSST_ARCHIVE_ASSERT(catalogs.size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); LinearCombinationKernelPersistenceHelper const keys(catalogs.front().getSchema()); afw::table::BaseRecord const & record = catalogs.front().front(); geom::Extent2I dimensions(record.get(keys.dimensions)); std::vector componentList(keys.components.getSize()); for (std::size_t i = 0; i < componentList.size(); ++i) { componentList[i] = archive.get(record[keys.components[i]]); } PTR(LinearCombinationKernel) result; if (keys.spatialFunctions.isValid()) { std::vector spatialFunctionList = keys.readSpatialFunctions(archive, record); result.reset(new LinearCombinationKernel(componentList, spatialFunctionList)); } else { std::vector kernelParameters(keys.amplitudes.getSize()); for (std::size_t i = 0; i < kernelParameters.size(); ++i) { kernelParameters[i] = record[keys.amplitudes[i]]; } result.reset(new LinearCombinationKernel(componentList, kernelParameters)); } LSST_ARCHIVE_ASSERT(result->getDimensions() == dimensions); result->setCtr(record.get(keys.center)); return result; } explicit Factory(std::string const & name) : afw::table::io::PersistableFactory(name) {} }; namespace { std::string getLinearCombinationKernelPersistenceName() { return "LinearCombinationKernel"; } LinearCombinationKernel::Factory registration(getLinearCombinationKernelPersistenceName()); } // anonymous std::string LinearCombinationKernel::getPersistenceName() const { return getLinearCombinationKernelPersistenceName(); } void LinearCombinationKernel::write(OutputArchiveHandle & handle) const { bool isVarying = isSpatiallyVarying(); LinearCombinationKernelPersistenceHelper const keys(getNBasisKernels(), isVarying); PTR(afw::table::BaseRecord) record = keys.write(handle, *this); if (isVarying) { for (int n = 0; n < keys.components.getSize(); ++n) { record->set(keys.components[n], handle.put(_kernelList[n])); record->set(keys.spatialFunctions[n], handle.put(_spatialFunctionList[n])); } } else { for (int n = 0; n < keys.components.getSize(); ++n) { record->set(keys.components[n], handle.put(_kernelList[n])); record->set(keys.amplitudes[n], _kernelParams[n]); } } } }}} // namespace lsst::afw::math

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    1b384e16

    commit 1b384e16d216bee5f7469b444891b97da3b64621
    Author: rowen 
    Date:   Wed Sep 30 20:04:20 2009 +0000
    
        Moved the typedef for KernelList from lsst::afw::math::LinearCombinationKernel
        to lsst::afw::math. This will improve compatibility with most existing C++ code.
        (Previously it was available in both namespaces, but that seems excessive).
        
        Changed getKernelSumList from inline to a normal function.
    

    92570c02

    commit 92570c02a059d1547b68e84d8a7326f68938b71b
    Author: Russell Owen 
    Date:   Tue May 7 10:23:10 2013 -0700
    
        Implement ticket #2620: computeImage should set xy0.
        Removed the ability to pass a smaller image to LinearCombinationKernel::computeImage.
        AnalyticKernel::computeImage can still be called with an image of any dimensions,
        but only on that class; if you try to do this on a pointer or reference to Kernel
        then Kernel::computeImage is called,which rejects images whose dimensions do not match that of Kernel
        (Jim Bosch and I consider this a feature).
        Added a unit test to tests/kernel.py that exercises the dimension checking code.
        Moved some boilerplate code for computeImage into a protected member function doComputeImage
        and made Kernel::computeImage nonvirtual.
    

    65c3fa0d

    commit 65c3fa0d21bea8d0b795d34724611e6d7edf60d1
    Author: rowen 
    Date:   Tue Oct 27 22:42:01 2009 +0000
    
        Modified LinearCombinationKernel to clone its basis kernels.
        Add a test to verify this new behavior.
    

    d7b24982

    commit d7b24982db8562dc77c4bcc33c84107c65fd686d
    Author: rowen 
    Date:   Thu Oct 29 00:15:47 2009 +0000
    
        Fixed ticket #1000 by adding a missing test to a LinearCombinationKernel constructor.
        Updated tests/Kernel.cc as suggested by Serge so it would not trigger the problem.
        Updated many exceptions in kernel constructors to print more details.
        Added unit tests for the exceptions in kernel methods.
        
        Note: the current code has a swig warning about a shadowed constructor in LinearCombinationKernel.
        This should be resolved before committing the changes to the trunk. See my email to lsst-data.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/math/Function.h

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #ifndef LSST_AFW_MATH_FUNCTION_H
                    #define LSST_AFW_MATH_FUNCTION_H
                    /**
                     * @file
                     *
                     * @brief Define the basic Function classes.
                     *
                     * @author Russell Owen
                     *
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/format.hpp"
                    #include "boost/serialization/nvp.hpp"
                    #include "boost/serialization/vector.hpp"
                    #include "boost/serialization/void_cast.hpp"
                    #include "boost/serialization/export.hpp"
                    
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/pex/exceptions.h"
                    
                    #include "lsst/afw/table/io/Persistable.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    
                    #ifndef SWIG
                    using boost::serialization::make_nvp;
                    #endif
                    
                        /**
                         * @brief Basic Function class.
                         *
                         * Function objects are functions whose parameters may be read and changed using
                         * getParameters and setParameters. They were designed for use with the Kernel class.
                         *
                         * These are simple functors with the restrictions that:
                         * - Function arguments and parameters are double precision
                         * - The return type is templated
                         *
                         * To create a function for a particular equation, subclass Function
                         * or (much more likely) Function1 or Function2. Your subclass must:
                         * - Have one or more constructors, all of which must initialize _params
                         * - Define operator() with code to compute the function
                         *   using this->_params or this->getParams() to reference the parameters
                         * - If the function is a linear combination of parameters then override the function isLinearCombination.
                         *
                         * If you wish to cache any information you may use the _isCacheValid flag;
                         * this is automatically set false whenever parameters are changed.
                         *
                         * Design Notes:
                         * The reason these functions exist (rather than using a pre-existing function class,
                         * such as Functor in VisualWorkbench) is because the Kernel class requires function
                         * objects with a standard interface for setting and getting function parameters.
                         *
                         * The reason isLinearCombination exists is to support refactoring LinearCombinationKernels.
                         *
                         * @ingroup afw
                         */
                        template
                        class Function : public lsst::daf::base::Citizen,
                                         public afw::table::io::PersistableFacade< Function >,
                                         public afw::table::io::Persistable
                        {
                        public:
                            /**
                             * @brief Construct a Function given the number of function parameters.
                             *
                             * The function parameters are initialized to 0.
                             */
                            explicit Function(
                                unsigned int nParams)   ///< number of function parameters
                            :
                                lsst::daf::base::Citizen(typeid(this)),
                                _params(nParams),
                                _isCacheValid(false)
                            {}
                    
                            /**
                             * @brief Construct a Function given the function parameters.
                             */
                            explicit Function(
                                std::vector const ¶ms)   ///< function parameters
                            :
                                lsst::daf::base::Citizen(typeid(this)),
                                _params(params),
                                _isCacheValid(false)
                            {}
                            
                            virtual ~Function() {}
                        
                            /**
                             * @brief Return the number of function parameters
                             *
                             * @return the number of function parameters
                             */
                            unsigned int getNParameters() const {
                                return _params.size();
                            }
                            
                            /**
                             * @brief Get one function parameter without range checking
                             *
                             * @return the specified function parameter
                             */
                            virtual double getParameter(
                                unsigned int ind)    ///< index of parameter
                            const {
                                return _params[ind];
                            }
                            
                            /**
                             * @brief Return all function parameters
                             *
                             * @return the function parameters as a vector
                             */
                            std::vector const &getParameters() const {
                                return _params;
                            }
                    
                            /**
                             * @brief Is the function a linear combination of its parameters?
                             *
                             * @return true if the function can be expressed as: sum over i of parameter_i * function_i(args)
                             *
                             * @warning: subclasses must override if true.
                             */
                            virtual bool isLinearCombination() const { return false; }
                            
                            /**
                             * @brief Set one function parameter without range checking
                             */
                            void setParameter(
                                unsigned int ind,   ///< index of parameter
                                double newValue)    ///< new value for parameter
                            {
                                _isCacheValid = false;
                                _params[ind] = newValue;
                            }
                            
                            /**
                             * @brief Set all function parameters
                             *
    
    172 3771b5eb - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    172 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * if the wrong number of parameters is supplied. */ void setParameters( std::vector const ¶ms) ///< vector of function parameters { if (_params.size() != params.size()) {
    179 f16aaf07 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    179 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ (boost::format("params has %d entries instead of %d") % \ params.size() % _params.size()).str()); } _isCacheValid = false; _params = params; } /** * @brief Return a string representation of the function * * @return a string representation of the function */ virtual std::string toString(std::string const&) const { std::stringstream os; os << "parameters: [ "; for (std::vector::const_iterator i = _params.begin(); i != _params.end(); ++i) { if (i != _params.begin()) os << ", "; os << *i; } os << " ]"; return os.str(); } protected: std::vector _params; mutable bool _isCacheValid; virtual std::string getPythonModule() const { return "lsst.afw.math"; } /* Default constructor: intended only for serialization */ explicit Function() : lsst::daf::base::Citizen(typeid(this)), _params(0), _isCacheValid(false) {} private: // serialization support friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("params", _params); } }; /** * @brief A Function taking one argument. * * Subclass and override operator() to do useful work. * * @ingroup afw */ template class Function1 : public afw::table::io::PersistableFacade< Function1 >, public Function { public: typedef boost::shared_ptr > Ptr; /** * @brief Construct a Function1 given the number of function parameters. * * The function parameters are initialized to 0. */ explicit Function1( unsigned int nParams) ///< number of function parameters : Function(nParams) {} /** * @brief Construct a Function1 given the function parameters. */ explicit Function1( std::vector const ¶ms) ///< function parameters : Function(params) {} virtual ~Function1() {} /** * @brief Return a pointer to a deep copy of this function * * This function exists instead of a copy constructor * so one can obtain a copy of an actual function * instead of a useless copy of the base class. * * Every concrete subclass must override this method. * * @return a pointer to a deep copy of the function */ virtual Ptr clone() const = 0; virtual ReturnT operator() (double x) const = 0; virtual std::string toString(std::string const& prefix="") const { return std::string("Function1: ") + Function::toString(prefix); } virtual void computeCache(int const n) {} protected: /* Default constructor: intended only for serialization */ explicit Function1() : Function() {} private: // serialization friend class boost::serialization::access; #ifndef SWIG // SWIG doesn't like base_object template void serialize(Archive& ar, unsigned const int version) { ar & make_nvp("fn", boost::serialization::base_object >(*this)); } #endif }; /** * @brief A Function taking two arguments. * * Subclass and override operator() to do useful work. * * @ingroup afw */ template class Function2 : public afw::table::io::PersistableFacade< Function2 >, public Function { public: typedef boost::shared_ptr > Ptr; /** * @brief Construct a Function2 given the number of function parameters. * * The function parameters are initialized to 0. */ explicit Function2( unsigned int nParams) ///< number of function parameters : Function(nParams) {} /** * @brief Construct a Function2 given the function parameters. * * The number of function parameters is set to the length of params. */ explicit Function2( std::vector const ¶ms) ///< function parameters : Function(params) {} virtual ~Function2() {} /** * @brief Return a pointer to a deep copy of this function * * This function exists instead of a copy constructor * so one can obtain a copy of an actual function * instead of a useless copy of the base class. * * Every non-virtual function must override this method. * * @return a pointer to a deep copy of the function */ virtual Ptr clone() const = 0; virtual ReturnT operator() (double x, double y) const = 0; virtual std::string toString(std::string const& prefix="") const { return std::string("Function2: ") + Function::toString(prefix); } /** * Return the derivative of the Function with respect to its parameters */ virtual std::vector getDFuncDParameters(double, double) const {
    352 9e855179 - throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    352 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ "getDFuncDParameters is not implemented for this class"); } protected: /* Default constructor: intended only for serialization */ explicit Function2() : Function() {} private: friend class boost::serialization::access; #ifndef SWIG // SWIG doesn't like base_object template void serialize(Archive& ar, unsigned const int version) { ar & make_nvp("fn", boost::serialization::base_object >(*this)); } #endif }; /** * @brief Base class for 2-dimensional polynomials of the form: * * f(x,y) = c0 f0(x) f0(y) (0th order) * + c1 f1(x) f0(x) + c2 f0(x) f1(y) (1st order) * + c3 f2(x) f0(y) + c4 f1(x) f1(y) + c5 f0(x) f2(y) (2nd order) * + ... * * and typically f0(x) = 1 * * @ingroup afw */ template class BasePolynomialFunction2: public Function2 { public: typedef typename Function2::Ptr Function2Ptr; /** * @brief Construct a polynomial function of specified order. * * The polynomial will have (order + 1) * (order + 2) / 2 coefficients * * The parameters are initialized to zero. */ explicit BasePolynomialFunction2( unsigned int order) ///< order of polynomial (0 for constant) : Function2(BasePolynomialFunction2::nParametersFromOrder(order)), _order(order) {} /** * @brief Construct a polynomial function with specified parameters. * * The order of the polynomial is determined from the length of the params vector * (see orderFromNParameters) and only certain lengths are suitable: 1, 3, 6, 10, 15... *
    408 13ce3777 - * @throw lsst::pex::exceptions::InvalidParameterException if params length is unsuitable
    ? ^^^^^^ ^
    408 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if params length is unsuitable
    ? ^^ ^ */ explicit BasePolynomialFunction2( std::vector params) ///< polynomial coefficients : Function2(params), _order(BasePolynomialFunction2::orderFromNParameters(static_cast(params.size()))) {} virtual ~BasePolynomialFunction2() {} /** * @brief Get the polynomial order */ int getOrder() const { return _order; } virtual bool isLinearCombination() const { return true; } /** * @brief Compute number of parameters from polynomial order. *
    429 13ce3777 - * @throw lsst::pex::exceptions::InvalidParameterException if order < 0
    ? ^^^^^^ ^
    429 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if order < 0
    ? ^^ ^ */ static int nParametersFromOrder(int order) { if (order < 0) { std::ostringstream os; os << "order=" << order << " invalid: must be >= 0";
    435 13ce3777 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    435 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, os.str());
    ? ^^ ^ } return (order + 1) * (order + 2) / 2; } /** * @brief Compute polynomial order from the number of parameters * * Only certain values of nParameters are acceptable, including: * nParameters order * 1 0 * 3 1 * 6 2 * 10 3 * 15 4 * ... *
    452 13ce3777 - * @throw lsst::pex::exceptions::InvalidParameterException if nParameters is invalid
    ? ^^^^^^ ^
    452 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if nParameters is invalid
    ? ^^ ^ */ static int orderFromNParameters(int nParameters) { int order = static_cast( 0.5 + ((-3.0 + (std::sqrt(1.0 + (8.0 * static_cast(nParameters))))) / 2.0)); if (nParameters != BasePolynomialFunction2::nParametersFromOrder(order)) { std::ostringstream os; os << "nParameters=" << nParameters << " invalid: order is not an integer";
    460 13ce3777 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    460 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, os.str());
    ? ^^ ^ } return order; } /** * Return the derivative of the Function with respect to its parameters * * Because this is a polynomial, c0 F0(x,y) + c1 F1(x,y) + c2 F2(x,y) + ... * we can set ci = 0 for all i except the parameter of interest and evaluate. * This isn't necessarily the most efficient algorithm, but it's general, * and you can override it if it isn't suitable for your particular subclass. */ virtual std::vector getDFuncDParameters(double x, double y) const { unsigned int const numParams = this->getNParameters(); // Number of parameters std::vector deriv(numParams); // Derivatives, to return Function2Ptr dummy = this->clone(); // Dummy function to evaluate for derivatives for (unsigned int i = 0; i < numParams; ++i) { dummy->setParameter(i, 0.0); } for (unsigned int i = 0; i < numParams; ++i) { dummy->setParameter(i, 1.0); deriv[i] = (*dummy)(x, y); dummy->setParameter(i, 0.0); } return deriv; } protected: int _order; ///< order of polynomial /* Default constructor: intended only for serialization */ explicit BasePolynomialFunction2() : Function2(1), _order(0) {} private: friend class boost::serialization::access; #ifndef SWIG // SWIG doesn't like base_object template void serialize(Archive& ar, unsigned const int version) { ar & make_nvp("fn2", boost::serialization::base_object >(*this)); ar & make_nvp("order", _order); } #endif }; /** * @brief a class used in function calls to indicate that no Function1 is being provided */ template class NullFunction1 : public Function1 { public: explicit NullFunction1() : Function1(0) {} typename Function1::Ptr clone() const { return typename Function1::Ptr(new NullFunction1()); } private: ReturnT operator() (double) const { return static_cast(0); } private: friend class boost::serialization::access; #ifndef SWIG // SWIG doesn't like base_object template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("fn1", boost::serialization::base_object >(*this)); } #endif }; /** * @brief a class used in function calls to indicate that no Function2 is being provided */ template class NullFunction2 : public Function2 { public: explicit NullFunction2() : Function2(0) {} typename Function2::Ptr clone() const { return typename Function2::Ptr(new NullFunction2()); } private: ReturnT operator() (double, double) const { return static_cast(0); } private: friend class boost::serialization::access; #ifndef SWIG // SWIG doesn't like base_object template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("fn2", boost::serialization::base_object >(*this)); } #endif }; }}} // lsst::afw::math #endif // #ifndef LSST_AFW_MATH_FUNCTION_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    13ce3777

    commit 13ce37775941ae0652c04391f59807edbe2db60f
    Author: rowen 
    Date:   Thu Apr 28 22:31:38 2011 +0000
    
        First draft.
    

    9e855179

    commit 9e855179ec201246b10f3977e52a5a3398814532
    Author: rhl 
    Date:   Mon May 3 06:52:33 2010 +0000
    
        Added getDFuncDParameters to Kernel
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    f16aaf07

    commit f16aaf0792aee0df29459cdd10e073e97ba6fd92
    Author: rowen 
    Date:   Wed Nov 18 22:05:46 2009 +0000
    
        Modified GaussianFunction2 to check its cache in operator() instead of setParameter/s.
        Fixed various unit tests. Function_1.py still fails.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/testRaWrap.py

    Diff:

    1 cc7d028c - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import os import unittest
    27 cc7d028c - import eups
    28 7cbb2bb9 + import lsst.utils
    import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom
    30 cc7d028c - import lsst.afw.coord as afwCoord
    import lsst.utils.tests as utilsTests from math import sqrt class WCSTestRaWrap(unittest.TestCase): '''A test set for the RA=0 wrap-around''' def setUp(self):
    37 cc7d028c - mydir = eups.productDir('afw')
    37 7cbb2bb9 + mydir = lsst.utils.getPackageDir('afw')
    self.assertTrue(mydir is not None) self.datadir = os.path.join(mydir, 'tests') def test1(self): # This fails due to #1386 #wcsfn = os.path.join(self.datadir, 'imsim-v85518312-fu-R43-S12.wcs') wcsfn = os.path.join(self.datadir, 'imsim-v85518312-fu-R43-S12.wcs2') hdr = afwImage.readMetadata(wcsfn) wcs1 = afwImage.makeWcs(hdr) crval = wcs1.getSkyOrigin() cd = wcs1.getCDMatrix() print cd crval_p = afwGeom.Point2D(crval.getLongitude().asDegrees(), crval.getLatitude().asDegrees()) origin = wcs1.getPixelOrigin() print crval_p print origin wcs2 = afwImage.Wcs(crval_p, origin, cd) for wcs in [wcs1,wcs2]: print wcs print 'x, y, RA, Dec, pixscale("/pix), pixscale2' for x,y in [(0,0),(300,0),(350,0),(360,0),(370,0),(380,0),(400,0)]: radec = wcs.pixelToSky(x,y) ra = radec.getLongitude().asDegrees() dec = radec.getLatitude ().asDegrees() pixscale = 3600. * sqrt(wcs.pixArea(afwGeom.Point2D(x,y))) ps2 = wcs.pixelScale().asArcseconds() print x,y,ra,dec,pixscale,ps2 self.assertTrue(abs(pixscale - 0.2) < 1e-3) self.assertTrue(abs(ps2 - 0.2) < 1e-3) # Ridiculous boilerplate #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): utilsTests.init() suites = [] suites += unittest.makeSuite(WCSTestRaWrap) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    cc7d028c

    commit cc7d028c7d756f282d3cb921cf6f74b3c150054d
    Author: dstn 
    Date:   Tue Jul 27 18:01:18 2010 +0000
    
        add failing test case
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    include/lsst/afw/geom/Box.h

    Diff:

                    // -*- lsst-c++ -*-
    
    2 a6d55f08 -
    3 a6d55f08 - /*
    ? -
    2 778eee48 + /*
    * LSST Data Management System
    5 a6d55f08 - * Copyright 2008, 2009, 2010 LSST Corporation.
    ? ^^^^^^^^ ^
    4 778eee48 + * Copyright 2008-2014 LSST Corporation.
    ? ^ ^
    6 a6d55f08 - *
    ? -
    5 778eee48 + *
    * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version.
    14 a6d55f08 - *
    ? -
    13 778eee48 + *
    * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.
    19 a6d55f08 - *
    ? -
    18 778eee48 + *
    20 a6d55f08 - * You should have received a copy of the LSST License Statement and
    ? -
    19 778eee48 + * You should have received a copy of the LSST License Statement and
    21 a6d55f08 - * the GNU General Public License along with this program. If not,
    ? -
    20 778eee48 + * the GNU General Public License along with this program. If not,
    * see . */
    23 778eee48 +
    24 a6d55f08 -
    25 0b7ec4be - /**
    26 0b7ec4be - * \file
    27 0b7ec4be - * \brief A coordinate class intended to represent absolute positions.
    28 0b7ec4be - */
    #ifndef LSST_AFW_GEOM_BOX_H #define LSST_AFW_GEOM_BOX_H
    27 7911ee94 + #include
    #include "boost/format.hpp" #include "lsst/afw/geom/Point.h" #include "lsst/afw/geom/Extent.h" #include "ndarray.h" namespace lsst { namespace afw { namespace geom { class Box2D; /**
    42 b7f6a102 - * \brief An integer coordinate rectangle.
    ? ^
    38 778eee48 + * @brief An integer coordinate rectangle.
    ? ^ *
    44 25e61ab4 - * Box2I is an inclusive box that represents a rectangular region of pixels. A box
    ? -
    40 778eee48 + * Box2I is an inclusive box that represents a rectangular region of pixels. A box
    * never has negative dimensions; the empty box is defined to have zero-size dimensions, * and is treated as though it does not have a well-defined position (regardless of the * return value of getMin() or getMax() for an empty box). *
    49 b7f6a102 - * \internal
    ? ^
    45 778eee48 + * @internal
    ? ^ * * Box2I internally stores its minimum point and dimensions, because we expect * these will be the most commonly accessed quantities. * * Box2I sets the minimum point to the origin for an empty box, and returns -1 for both * elements of the maximum point in that case. */ class Box2I { public: typedef Point2I Point; typedef Extent2I Extent; enum EdgeHandlingEnum { EXPAND, SHRINK };
    65 0b7ec4be - /// \brief Construct an empty box.
    ? ^
    61 778eee48 + /// @brief Construct an empty box.
    ? ^ Box2I() : _minimum(0), _dimensions(0) {}
    64 778eee48 + /**
    65 778eee48 + * @brief Construct a box from its minimum and maximum points.
    66 778eee48 + *
    67 778eee48 + * @param[in] minimum Minimum (lower left) coordinate (inclusive).
    68 778eee48 + * @param[in] maximum Maximum (upper right) coordinate (inclusive).
    69 778eee48 + * @param[in] invert If true (default), swap the minimum and maximum coordinates if
    70 778eee48 + * minimum > maximum instead of creating an empty box.
    71 778eee48 + */
    Box2I(Point2I const & minimum, Point2I const & maximum, bool invert=true);
    73 778eee48 +
    74 778eee48 + /**
    75 778eee48 + * @brief Construct a box from its minimum point and dimensions.
    76 778eee48 + *
    77 778eee48 + * @param[in] minimum Minimum (lower left) coordinate.
    78 778eee48 + * @param[in] dimensions Box dimensions. If either dimension coordinate is 0, the box will be empty.
    79 778eee48 + * @param[in] invert If true (default), invert any negative dimensions instead of creating
    80 778eee48 + * an empty box.
    81 778eee48 + */
    Box2I(Point2I const & minimum, Extent2I const & dimensions, bool invert=true);
    84 778eee48 +
    85 778eee48 + /**
    86 778eee48 + * @brief Construct an integer box from a floating-point box.
    87 778eee48 + *
    88 778eee48 + * Floating-point to integer box conversion is based on the concept that a pixel
    89 778eee48 + * is not an infinitesimal point but rather a square of unit size centered on
    90 778eee48 + * integer-valued coordinates. Converting a floating-point box to an integer box
    91 778eee48 + * thus requires a choice on how to handle pixels which are only partially contained
    92 778eee48 + * by the input floating-point box.
    93 778eee48 + *
    94 778eee48 + * @param[in] other A floating-point box to convert.
    95 778eee48 + * @param[in] edgeHandling If EXPAND, the integer box will contain any pixels that
    96 778eee48 + * overlap the floating-point box. If SHRINK, the integer
    97 778eee48 + * box will contain only pixels completely contained by
    98 778eee48 + * the floating-point box.
    99 778eee48 + */
    explicit Box2I(Box2D const & other, EdgeHandlingEnum edgeHandling=EXPAND);
    73 b7f6a102 - /// \brief Standard copy constructor.
    ? ^
    102 778eee48 + /// @brief Standard copy constructor.
    ? ^ Box2I(Box2I const & other) : _minimum(other._minimum), _dimensions(other._dimensions) {} void swap(Box2I & other) { _minimum.swap(other._minimum); _dimensions.swap(other._dimensions); }
    109 778eee48 +
    80 b7f6a102 - /// \brief Standard assignment operator.
    ? ^
    110 778eee48 + /// @brief Standard assignment operator.
    ? ^ Box2I & operator=(Box2I const & other) { _minimum = other._minimum; _dimensions = other._dimensions; return *this; } /** * @name Min/Max Accessors * * @brief Return the minimum and maximum coordinates of the box (inclusive). */ //@{ Point2I const getMin() const { return _minimum; } int getMinX() const { return _minimum.getX(); } int getMinY() const { return _minimum.getY(); } Point2I const getMax() const { return _minimum + _dimensions - Extent2I(1); } int getMaxX() const { return _minimum.getX() + _dimensions.getX() - 1; } int getMaxY() const { return _minimum.getY() + _dimensions.getY() - 1; } //@} /** * @name Begin/End Accessors *
    105 b7f6a102 - * \brief Return STL-style begin (inclusive) and end (exclusive) coordinates for the box.
    ? ^
    135 778eee48 + * @brief Return STL-style begin (inclusive) and end (exclusive) coordinates for the box.
    ? ^ */ //@{ Point2I const getBegin() const { return _minimum; } int getBeginX() const { return _minimum.getX(); } int getBeginY() const { return _minimum.getY(); } Point2I const getEnd() const { return _minimum + _dimensions; } int getEndX() const { return _minimum.getX() + _dimensions.getX(); } int getEndY() const { return _minimum.getY() + _dimensions.getY(); } //@} /** * @name Size Accessors *
    120 b7f6a102 - * \brief Return the size of the box in pixels.
    ? ^
    150 778eee48 + * @brief Return the size of the box in pixels.
    ? ^ */ //@{ Extent2I const getDimensions() const { return _dimensions; } int getWidth() const { return _dimensions.getX(); } int getHeight() const { return _dimensions.getY(); } int getArea() const { return getWidth() * getHeight(); } //@}
    159 778eee48 + /// @brief Return slices to extract the box's region from an ndarray::Array.
    129 a7ce1e71 - ndarray::View<
    ? -
    160 778eee48 + ndarray::View<
    130 a7ce1e71 - boost::fusion::vector2< ndarray::index::Range, ndarray::index::Range >
    ? -
    161 778eee48 + boost::fusion::vector2< ndarray::index::Range, ndarray::index::Range >
    > getSlices() const;
    134 b7f6a102 - /// \brief Return true if the box contains no points.
    ? ^
    165 778eee48 + /// @brief Return true if the box contains no points.
    ? ^
    135 17d1d529 - bool isEmpty() const {
    ? -
    166 778eee48 + bool isEmpty() const {
    136 17d1d529 - return _dimensions.getX() == 0 && _dimensions.getY() == 0;
    ? -
    167 778eee48 + return _dimensions.getX() == 0 && _dimensions.getY() == 0;
    }
    170 778eee48 + /// @brief Return true if the box contains the point.
    bool contains(Point2I const & point) const;
    172 778eee48 +
    173 778eee48 + /**
    174 778eee48 + * @brief Return true if all points contained by other are also contained by this.
    175 778eee48 + *
    176 778eee48 + * An empty box is contained by every other box, including other empty boxes.
    177 778eee48 + */
    bool contains(Box2I const & other) const;
    179 778eee48 +
    180 778eee48 + /**
    181 778eee48 + * @brief Return true if any points in other are also in this.
    182 778eee48 + *
    183 778eee48 + * Any overlap operation involving an empty box returns false.
    184 778eee48 + */
    bool overlaps(Box2I const & other) const;
    187 778eee48 + /**
    188 778eee48 + * @brief Increase the size of the box by the given buffer amount in all directions.
    189 778eee48 + *
    190 778eee48 + * If a negative buffer is passed and the final size of the box is less than or
    191 778eee48 + * equal to zero, the box will be made empty.
    192 778eee48 + */
    void grow(int buffer) { grow(Extent2I(buffer)); }
    194 778eee48 +
    195 778eee48 + /**
    196 778eee48 + * @brief Increase the size of the box by the given buffer amount in each direction.
    197 778eee48 + *
    198 778eee48 + * If a negative buffer is passed and the final size of the box is less than or
    199 778eee48 + * equal to zero, the box will be made empty.
    200 778eee48 + */
    void grow(Extent2I const & buffer);
    202 778eee48 +
    203 778eee48 + /// @brief Shift the position of the box by the given offset.
    void shift(Extent2I const & offset);
    205 778eee48 +
    206 778eee48 + /// @brief Flip a bounding box about the y-axis given a parent box of extent (xExtent).
    146 584c5072 - void flipLR(int xextent);
    ? ^
    207 778eee48 + void flipLR(int xExtent);
    ? ^
    208 778eee48 +
    209 778eee48 + /// @brief Flip a bounding box about the x-axis given a parent box of extent (yExtent).
    147 584c5072 - void flipTB(int yextent);
    ? ^
    210 778eee48 + void flipTB(int yExtent);
    ? ^
    211 778eee48 +
    212 778eee48 + /// @brief Expand this to ensure that this->contains(point).
    void include(Point2I const & point);
    214 778eee48 +
    215 778eee48 + /// @brief Expand this to ensure that this->contains(other).
    void include(Box2I const & other);
    217 778eee48 +
    218 778eee48 + /// @brief Shrink this to ensure that other.contains(*this).
    void clip(Box2I const & other);
    221 778eee48 + /**
    222 778eee48 + * @brief Compare two boxes for equality.
    223 778eee48 + *
    224 778eee48 + * All empty boxes are equal.
    225 778eee48 + */
    bool operator==(Box2I const & other) const;
    227 778eee48 +
    228 778eee48 + /**
    229 778eee48 + * @brief Compare two boxes for equality.
    230 778eee48 + *
    231 778eee48 + * All empty boxes are equal.
    232 778eee48 + */
    bool operator!=(Box2I const & other) const;
    234 a8e2a7e9 +
    235 7911ee94 + /**
    236 7911ee94 + * Get the corner points
    237 778eee48 + *
    238 7911ee94 + * The order is counterclockise, starting from the lower left corner, i.e.:
    239 7911ee94 + * (minX, minY), (maxX, maxY), (maxX, maxX), (minX, maxY)
    240 7911ee94 + */
    241 7911ee94 + std::vector getCorners() const;
    std::string toString() const { return (boost::format("Box2I(%s,%s)") % _minimum.toString() % _dimensions.toString()).str(); } private: Point2I _minimum; Extent2I _dimensions; }; /**
    165 b7f6a102 - * \brief A floating-point coordinate rectangle geometry.
    ? ^
    253 778eee48 + * @brief A floating-point coordinate rectangle geometry.
    ? ^ *
    167 25e61ab4 - * Box2D is a half-open (minimum is inclusive, maximum is exclusive) box. A box
    ? -
    255 778eee48 + * Box2D is a half-open (minimum is inclusive, maximum is exclusive) box. A box
    * never has negative dimensions; the empty box is defined to zero-size dimensions * and its minimum and maximum values set to NaN. Only the empty box may have * zero-size dimensions. *
    172 b7f6a102 - * \internal
    ? ^
    260 778eee48 + * @internal
    ? ^ * * Box2D internally stores its minimum point and maximum point, instead of * minimum point and dimensions, to ensure roundoff error does not affect * whether points are contained by the box. * * Despite some recommendations to the contrary, Box2D sets the minimum and maximum * points to NaN for an empty box. In almost every case, special checks for * emptiness would have been necessary anyhow, so there was little to gain in * using the minimum > maximum condition to denote an empty box, as was used in Box2I. */ class Box2D { public: typedef Point2D Point; typedef Extent2D Extent; /** * Value the maximum coordinate is multiplied by to increase it by the smallest * possible amount. */ static double const EPSILON; /// Value used to specify undefined coordinate values. static double const INVALID;
    198 b7f6a102 - /// \brief Construct an empty box.
    ? ^
    286 778eee48 + /// @brief Construct an empty box.
    ? ^ Box2D();
    289 778eee48 + /**
    290 778eee48 + * @brief Construct a box from its minimum and maximum points.
    291 778eee48 + *
    292 778eee48 + * If any(minimum == maximum), the box will always be empty (even if invert==true).
    293 778eee48 + *
    294 778eee48 + * @param[in] minimum Minimum (lower left) coordinate (inclusive).
    295 778eee48 + * @param[in] maximum Maximum (upper right) coordinate (exclusive).
    296 778eee48 + * @param[in] invert If true (default), swap the minimum and maximum coordinates if
    297 778eee48 + * minimum > maximum instead of creating an empty box.
    298 778eee48 + */
    201 25e61ab4 - Box2D(Point2D const & minimum, Point2D const & maximum, bool invert=true);
    ? ----
    299 778eee48 + Box2D(Point2D const & minimum, Point2D const & maximum, bool invert=true);
    300 778eee48 +
    301 778eee48 + /**
    302 778eee48 + * @brief Construct a box from its minimum point and dimensions.
    303 778eee48 + *
    304 778eee48 + * @param[in] minimum Minimum (lower left) coordinate (inclusive).
    305 778eee48 + * @param[in] dimensions Box dimensions. If either dimension coordinate is 0, the box will be empty.
    306 778eee48 + * @param[in] invert If true (default), invert any negative dimensions instead of creating
    307 778eee48 + * an empty box.
    308 778eee48 + */
    Box2D(Point2D const & minimum, Extent2D const & dimensions, bool invert=true);
    310 778eee48 +
    311 778eee48 + /**
    312 778eee48 + * @brief Construct a floating-point box from an integer box.
    203 0b7ec4be -
    313 778eee48 + *
    ? ++
    314 778eee48 + * Integer to floating-point box conversion is based on the concept that a pixel
    315 778eee48 + * is not an infinitesimal point but rather a square of unit size centered on
    316 778eee48 + * integer-valued coordinates. While the output floating-point box thus has
    317 778eee48 + * the same dimensions as the input integer box, its minimum/maximum coordinates
    318 778eee48 + * are 0.5 smaller/greater.
    319 778eee48 + */
    explicit Box2D(Box2I const & other);
    205 0b7ec4be -
    321 778eee48 +
    206 b7f6a102 - /// \brief Standard copy constructor.
    ? ^
    322 778eee48 + /// @brief Standard copy constructor.
    ? ^ Box2D(Box2D const & other) : _minimum(other._minimum), _maximum(other._maximum) {}
    208 b635df09 -
    324 778eee48 +
    void swap(Box2D & other) { _minimum.swap(other._minimum); _maximum.swap(other._maximum); }
    329 778eee48 +
    213 b7f6a102 - /// \brief Standard assignment operator.
    ? ^
    330 778eee48 + /// @brief Standard assignment operator.
    ? ^ Box2D & operator=(Box2D const & other) { _minimum = other._minimum; _maximum = other._maximum; return *this; } /** * @name Min/Max Accessors * * @brief Return the minimum (inclusive) and maximum (exclusive) coordinates of the box. */ //@{ Point2D const getMin() const { return _minimum; } double getMinX() const { return _minimum.getX(); } double getMinY() const { return _minimum.getY(); } Point2D const getMax() const { return _maximum; } double getMaxX() const { return _maximum.getX(); } double getMaxY() const { return _maximum.getY(); } //@} /** * @name Size Accessors *
    238 b7f6a102 - * \brief Return the size of the box.
    ? ^
    355 778eee48 + * @brief Return the size of the box.
    ? ^ */ //@{ Extent2D const getDimensions() const { return isEmpty() ? Extent2D(0.0) : _maximum - _minimum; } double getWidth() const { return isEmpty() ? 0 : _maximum.getX() - _minimum.getX(); } double getHeight() const { return isEmpty() ? 0 : _maximum.getY() - _minimum.getY(); } double getArea() const { Extent2D dim(getDimensions()); return dim.getX() * dim.getY(); } //@} /** * @name Center Accessors *
    253 b7f6a102 - * \brief Return the center coordinate of the box.
    ? ^
    370 778eee48 + * @brief Return the center coordinate of the box.
    ? ^ */ //@{ Point2D const getCenter() const { return Point2D((_minimum.asEigen() + _maximum.asEigen())*0.5); } double getCenterX() const { return (_minimum.getX() + _maximum.getX())*0.5; } double getCenterY() const { return (_minimum.getY() + _maximum.getY())*0.5; } //@}
    261 b7f6a102 - /// \brief Return true if the box contains no points.
    ? ^
    378 778eee48 + /// @brief Return true if the box contains no points.
    ? ^ bool isEmpty() const { return _minimum.getX() != _minimum.getX(); }
    381 778eee48 + /// @brief Return true if the box contains the point.
    bool contains(Point2D const & point) const;
    383 778eee48 +
    384 778eee48 + /**
    385 778eee48 + * @brief Return true if all points contained by other are also contained by this.
    386 778eee48 + *
    387 778eee48 + * An empty box is contained by every other box, including other empty boxes.
    388 778eee48 + */
    bool contains(Box2D const & other) const;
    390 778eee48 +
    391 778eee48 + /**
    392 778eee48 + * @brief Return true if any points in other are also in this.
    393 778eee48 + *
    394 778eee48 + * Any overlap operation involving an empty box returns false.
    395 778eee48 + */
    bool overlaps(Box2D const & other) const;
    398 778eee48 + /**
    399 778eee48 + * @brief Increase the size of the box by the given buffer amount in all directions.
    400 778eee48 + *
    401 778eee48 + * If a negative buffer is passed and the final size of the box is less than or
    402 778eee48 + * equal to zero, the box will be made empty.
    403 778eee48 + */
    void grow(double buffer) { grow(Extent2D(buffer)); }
    405 778eee48 +
    406 778eee48 + /**
    407 778eee48 + * @brief Increase the size of the box by the given buffer amount in each direction.
    408 778eee48 + *
    409 778eee48 + * If a negative buffer is passed and the final size of the box is less than or
    410 778eee48 + * equal to zero, the box will be made empty.
    411 778eee48 + */
    void grow(Extent2D const & buffer);
    413 778eee48 +
    414 778eee48 + /// @brief Shift the position of the box by the given offset.
    void shift(Extent2D const & offset);
    416 778eee48 +
    417 778eee48 + /// @brief Flip a bounding box about the y-axis given a parent box of extent (xExtent).
    271 584c5072 - void flipLR(float xextent);
    ? ^
    418 778eee48 + void flipLR(float xExtent);
    ? ^
    419 778eee48 +
    420 778eee48 + /// @brief Flip a bounding box about the x-axis given a parent box of extent (yExtent).
    272 584c5072 - void flipTB(float yextent);
    ? ^
    421 778eee48 + void flipTB(float yExtent);
    ? ^
    422 778eee48 +
    423 778eee48 + /**
    424 778eee48 + * @brief Expand this to ensure that this->contains(point).
    425 778eee48 + *
    426 778eee48 + * If the point sets a new maximum value for the box, the maximum coordinate will
    427 778eee48 + * be adjusted to ensure the point is actually contained
    428 778eee48 + * by the box instead of sitting on its exclusive upper edge.
    429 778eee48 + */
    void include(Point2D const & point);
    431 778eee48 +
    432 778eee48 + /// @brief Expand this to ensure that this->contains(other).
    void include(Box2D const & other);
    434 778eee48 +
    435 778eee48 + /// @brief Shrink this to ensure that other.contains(*this).
    void clip(Box2D const & other);
    438 778eee48 + /**
    439 778eee48 + * @brief Compare two boxes for equality.
    440 778eee48 + *
    441 778eee48 + * All empty boxes are equal.
    442 778eee48 + */
    bool operator==(Box2D const & other) const;
    444 778eee48 +
    445 778eee48 + /**
    446 778eee48 + * @brief Compare two boxes for equality.
    447 778eee48 + *
    448 778eee48 + * All empty boxes are equal.
    449 778eee48 + */
    bool operator!=(Box2D const & other) const;
    451 a8e2a7e9 +
    452 7911ee94 + /**
    453 7911ee94 + * Get the corner points
    454 778eee48 + *
    455 7911ee94 + * The order is counterclockise, starting from the lower left corner, i.e.:
    456 7911ee94 + * (minX, minY), (maxX, maxY), (maxX, maxX), (minX, maxY)
    457 7911ee94 + */
    458 7911ee94 + std::vector getCorners() const;
    std::string toString() const { return (boost::format("Box2D(%s,%s)") % _minimum.toString() % _maximum.toString()).str(); } private: void _tweakMax(int n) { if (_maximum[n] < 0.0) { _maximum[n] *= (1.0 - EPSILON); } else if (_maximum[n] > 0.0) { _maximum[n] *= (1.0 + EPSILON); } else { _maximum[n] = EPSILON; } } Point2D _minimum; Point2D _maximum; }; typedef Box2D BoxD; typedef Box2I BoxI; std::ostream & operator<<(std::ostream & os, Box2I const & box); std::ostream & operator<<(std::ostream & os, Box2D const & box); }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    b635df09

    commit b635df0908f570c1c3c371b687a581da61f0be1f
    Author: dubcovsky 
    Date:   Wed Apr 27 21:32:08 2011 +0000
    
        Added swap functions for Point, Extent, and Box. Added Copy constructors to Peak and Footprint
    

    0b7ec4be

    commit 0b7ec4be44da7c523ad2dc4b39e3e3908c154805
    Author: jbosch 
    Date:   Fri Dec 18 09:41:20 2009 +0000
    
        afw/#1095 - added header for new boxes, implementation for BoxI.
    

    a7ce1e71

    commit a7ce1e71d391ee1b194eabea9cead705bd9858da
    Author: Jim Bosch 
    Date:   Mon Mar 19 16:09:24 2012 -0400
    
        moved ndarray out of lsst namespace and header directories
    

    17d1d529

    commit 17d1d529ed63e98f98e5d1a7a7da4811e95fc26c
    Author: dubcovsky 
    Date:   Tue Feb 15 00:00:43 2011 +0000
    
        #1556 Split Footprint.h into Threshold.h, FootprintSet.h, and FootprintFunctor.h, to correspond with class names. Added a constructors to Footprint which use geom objects (BoxI and Ellipse) to construct footprints. Footprints now exclusively use geom::PointI and geom::BoxI internally. (but still accept image::PointI and image::BBox for backwards compatibility wherever possible). FootprintArray.h contains a static functions to flatten and expand ndarrays using a Footprint to map between 2-d and 1-d indices.
    

    584c5072

    commit 584c50725017edd8a1051d1931f1a4aeb29ca864
    Author: krughoff 
    Date:   Thu Oct 6 17:27:46 2011 +0000
    
        Moved some code around and implemented Jim B's suggestion of passing a scalar to Box.flipTB and Box.flipRL
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    b7f6a102

    commit b7f6a1025c4a8de7ab1f9f9333cec2dd5f2d884e
    Author: jbosch 
    Date:   Sat Dec 19 01:15:49 2009 +0000
    
        afw/#1095 - nominally finished c++ implementation for BoxD.
    

    Commits in /Users/nate/repos_lsst/afw/

    778eee48

    commit 778eee48a3b8c63179e448972e5d78c64406589f
    Author: Jim Bosch 
    Date:   Wed Aug 20 13:42:54 2014 -0400
    
        Move Box2I and Box2D Doxygen comments to header.
        
        Also removed trailing whitespace and updated copyright dates.
    

    a8e2a7e9

    commit a8e2a7e9666f30c2384ae6bb3557181f65684db7
    Author: jbosch 
    Date:   Mon Dec 21 23:37:41 2009 +0000
    
        afw/#1095 - swig wrappers, some tests for BoxI and BoxD.
    

    7911ee94

    commit 7911ee946edad9f1f95b38049679799efe317cd6
    Author: Russell Owen 
    Date:   Thu Feb 20 13:47:43 2014 -0800
    
        Added getCorners method to Box2D and Box2I C++ (and removed Python-only version).
        Updated Detector.cc to use it.
    

    Return to list

    tests/imageIo1.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Test cases to test image I/O """
    28 b10ab54c - import os
    import os.path import unittest
    33 b10ab54c - import eups
    33 7cbb2bb9 + import lsst.utils
    import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.utils.tests as utilsTests import lsst.afw.display.ds9 as ds9 try: type(verbose) except NameError: verbose = 0
    44 76505c6a - dataDir = os.path.join(eups.productDir("afwdata"), "data")
    ? ^ ^ ^^^^^ ^
    44 7cbb2bb9 + dataDir = os.path.join(lsst.utils.getPackageDir("afwdata"), "data")
    ? ^^^^^ ^^^ ^^^^^ ^^^^
    45 b10ab54c - if not dataDir:
    46 b10ab54c - raise RuntimeError("Must set up afwdata to run these tests")
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ReadFitsTestCase(unittest.TestCase): """A test case for reading FITS images""" def setUp(self): pass def tearDown(self): pass def testU16(self): """Test reading U16 image""" im = afwImage.ImageD(os.path.join(dataDir, "small_img.fits")) col, row, val = 0, 0, 1154 self.assertEqual(im.get(col, row), val) def testS16(self): """Test reading S16 image""" im = afwImage.ImageD(os.path.join(dataDir, "871034p_1_img.fits")) if False: ds9.mtv(im) col, row, val = 32, 1, 62 self.assertEqual(im.get(col, row), val) def testF32(self): """Test reading F32 image""" im = afwImage.ImageD(os.path.join(dataDir, "871034p_1_MI.fits"), 4) col, row, val = 32, 1, 39.11672 self.assertAlmostEqual(im.get(col, row), val, 5) def testF64(self): """Test reading a U16 file into a F64 image""" im = afwImage.ImageD(os.path.join(dataDir, "small_img.fits")) col, row, val = 0, 0, 1154 self.assertEqual(im.get(col, row), val) #print "IM = ", im def testWriteReadF64(self): """Test writing then reading an F64 image"""
    92 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    94 4efabcba - imPath = "data"
    95 4efabcba - if os.path.exists("tests"):
    96 4efabcba - imPath = os.path.join("tests", imPath)
    97 4efabcba - imPath = os.path.join(imPath, "smallD.fits")
    98 4efabcba -
    99 20c2c467 - im = afwImage.ImageD(afwGeom.Extent2I(100, 100))
    93 c605dfcd + im = afwImage.ImageD(afwGeom.Extent2I(100, 100))
    ? ++++
    100 a7aa0c91 - im.set(666)
    94 c605dfcd + im.set(666)
    ? ++++
    101 7ca150ed - im.writeFits(imPath)
    ? ^^^^^
    95 c605dfcd + im.writeFits(tmpFile)
    ? ++++ ++++ ^^
    96 c605dfcd + afwImage.ImageD(tmpFile)
    102 7ca150ed - newIm = afwImage.ImageD(imPath)
    103 7ca150ed - os.remove(imPath)
    def testSubimage(self): """Test reading a subimage image""" fileName, hdu = os.path.join(dataDir, "871034p_1_MI.fits"), 4 im = afwImage.ImageF(fileName, hdu) bbox = afwGeom.Box2I(afwGeom.Point2I(110, 120), afwGeom.Extent2I(20, 15)) sim = im.Factory(im, bbox, afwImage.LOCAL) im2 = afwImage.ImageF(fileName, hdu, None, bbox, afwImage.LOCAL) self.assertEqual(im2.getDimensions(), sim.getDimensions()) self.assertEqual(im2.get(1, 1), sim.get(1, 1)) self.assertEqual(im2.getX0(), sim.getX0()) self.assertEqual(im2.getY0(), sim.getY0()) def testMEF(self): """Test writing a set of images to an MEF fits file, and then reading them back"""
    117 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    118 c605dfcd + im = afwImage.ImageF(afwGeom.Extent2I(20, 20))
    124 4efabcba - imPath = "data"
    125 4efabcba - if os.path.exists("tests"):
    126 4efabcba - imPath = os.path.join("tests", imPath)
    127 4efabcba - imPath = os.path.join(imPath, "MEF.fits")
    129 20c2c467 - im = afwImage.ImageF(afwGeom.Extent2I(20, 20))
    120 c605dfcd + for hdu in range(1, 5):
    121 c605dfcd + im.set(100*hdu)
    122 c605dfcd + if hdu == 1:
    123 c605dfcd + mode = "w"
    124 c605dfcd + else:
    125 c605dfcd + mode = "a"
    126 c605dfcd + im.writeFits(tmpFile, None, mode)
    131 13c19bdb - for hdu in range(1, 5):
    128 c605dfcd + for hdu in range(1, 5):
    ? ++++
    132 13c19bdb - im.set(100*hdu)
    133 13c19bdb - if hdu == 1:
    134 13c19bdb - mode = "w"
    135 13c19bdb - else:
    136 13c19bdb - mode = "a"
    137 13c19bdb - im.writeFits(imPath, None, mode)
    138 13c19bdb -
    139 13c19bdb - for hdu in range(1, 5):
    140 13c19bdb - im = afwImage.ImageF(imPath, hdu)
    ? ^^^^^
    129 c605dfcd + im = afwImage.ImageF(tmpFile, hdu)
    ? ++++ ++++ ^^
    141 13c19bdb - self.assertEqual(im.get(0, 0), 100*hdu)
    130 c605dfcd + self.assertEqual(im.get(0, 0), 100*hdu)
    ? ++++
    142 13c19bdb -
    143 13c19bdb - os.remove(imPath)
    def testWriteBool(self): """Test that we can read and write bools""" import lsst.afw.image as afwImage import lsst.daf.base as dafBase
    150 a06040f0 - imPath = "data"
    151 a06040f0 - if os.path.exists("tests"):
    152 a06040f0 - imPath = os.path.join("tests", imPath)
    153 a06040f0 - imPath = os.path.join(imPath, "tmp.fits")
    137 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    138 c605dfcd + im = afwImage.ImageF(afwGeom.ExtentI(10,20))
    139 c605dfcd + md = dafBase.PropertySet()
    140 c605dfcd + keys = {"BAD" : False,
    141 c605dfcd + "GOOD" : True,
    142 c605dfcd + }
    143 c605dfcd + for k, v in keys.items():
    144 c605dfcd + md.add(k, v)
    145 c605dfcd +
    146 c605dfcd + im.writeFits(tmpFile, md)
    148 c605dfcd + jim = afwImage.DecoratedImageF(tmpFile)
    155 a8f86353 - im = afwImage.ImageF(afwGeom.ExtentI(10,20))
    156 a06040f0 - md = dafBase.PropertySet()
    157 a06040f0 - keys = {"BAD" : False,
    158 a06040f0 - "GOOD" : True,
    159 a06040f0 - }
    160 a06040f0 - for k, v in keys.items():
    161 a06040f0 - md.add(k, v)
    162 a06040f0 -
    163 a06040f0 - im.writeFits(imPath, md)
    165 a06040f0 - jim = afwImage.DecoratedImageF(imPath)
    166 a06040f0 - os.remove(imPath)
    167 a06040f0 -
    168 a06040f0 - for k, v in keys.items():
    150 c605dfcd + for k, v in keys.items():
    ? ++++
    169 a06040f0 - self.assertEqual(jim.getMetadata().get(k), v)
    151 c605dfcd + self.assertEqual(jim.getMetadata().get(k), v)
    ? ++++ def testLongStrings(self): keyWord = 'ZZZ'
    173 feb6df36 - fitsName = 'zzz.fits'
    155 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    174 feb6df36 - longString = ' '.join(['This is a long string.'] * 8)
    156 c605dfcd + longString = ' '.join(['This is a long string.'] * 8)
    ? ++++
    176 feb6df36 - expOrig = afwImage.ExposureF(100,100)
    158 c605dfcd + expOrig = afwImage.ExposureF(100,100)
    ? ++++
    177 feb6df36 - mdOrig = expOrig.getMetadata()
    159 c605dfcd + mdOrig = expOrig.getMetadata()
    ? ++++
    178 feb6df36 - mdOrig.set(keyWord, longString)
    160 c605dfcd + mdOrig.set(keyWord, longString)
    ? ++++
    179 feb6df36 - expOrig.writeFits(fitsName)
    ? ^ ^^^^^
    161 c605dfcd + expOrig.writeFits(tmpFile)
    ? ++++ ^^^^ ^
    181 feb6df36 - expNew = afwImage.ExposureF(fitsName)
    ? ^ ^^^^^
    163 c605dfcd + expNew = afwImage.ExposureF(tmpFile)
    ? ++++ ^^^^ ^
    182 feb6df36 - self.assertEqual(expNew.getMetadata().get(keyWord), longString)
    164 c605dfcd + self.assertEqual(expNew.getMetadata().get(keyWord), longString)
    ? ++++
    183 feb6df36 - os.remove(fitsName)
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ReadFitsTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    b10ab54c

    commit b10ab54c802578e3cc4158bc33aa212a5cba5bc4
    Author: rallsman 
    Date:   Sun Apr 6 01:43:41 2008 +0000
    
        Mostly replacing the files which were inexplicably zero length on last commit.
    

    20c2c467

    commit 20c2c46776ad69164993f9837f347800a80f245b
    Author: jbosch 
    Date:   Fri Mar 4 01:19:01 2011 +0000
    
        afw #1556 - fixed all python unit tests with trivial syntax-related failures, plus a few others
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    7ca150ed

    commit 7ca150edfd268bbca94fac0337a25941c51ee2a1
    Author: rowen 
    Date:   Wed Mar 11 18:25:19 2009 +0000
    
        Minor test fixes.
    

    feb6df36

    commit feb6df36942084fe1db71661e25a04ca66c934dd
    Author: Jim Bosch 
    Date:   Wed Feb 13 15:47:22 2013 -0500
    
        Added unit tests for long strings in FITS headers
    

    13c19bdb

    commit 13c19bdb953b9bfceaf739d0782827b549f6e1b5
    Author: rhl 
    Date:   Sat May 30 13:01:59 2009 +0000
    
        Added test cases
    

    76505c6a

    commit 76505c6a9851eb22e1080810712fbd4b07f2ef02
    Author: Paul Price 
    Date:   Fri Nov 18 17:15:21 2011 -0500
    
        Updating image directory.
    

    a8f86353

    commit a8f86353b4d794d8e2accd0ce6950e72a06c3f66
    Merge: a128aac 246b6dd
    Author: dubcovsky 
    Date:   Thu Mar 31 20:50:37 2011 +0000
    
        #1556 trunk merged to ticket branch
    

    4efabcba

    commit 4efabcbafbbdffbc284800d3dbce2861843f2930
    Author: rhl 
    Date:   Tue Jun 8 14:32:02 2010 +0000
    
        Read FITS files using fits_read_subset (#1315)
    

    a06040f0

    commit a06040f0ae38ba21354906cfa74727ce5cbfd42d
    Author: rhl 
    Date:   Tue Mar 1 08:14:09 2011 +0000
    
        Fix writing bools (True used to appear as False with at least some compilers)
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    python/lsst/afw/geom/init.py

    Diff:

                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    
                    """Application Framework geometry code including Point, Extent, and ellipses
                    """
                    from .geomLib import *
    
    26 7cbdbdbb + from .xyTransformFactory import *
    27 8cea9ad2 + from .transformConfig import *
    BoxI = Box2I BoxD = Box2D PointI = Point2I PointD = Point2D ExtentI = Extent2I ExtentD = Extent2D Point = {(int, 2):Point2I, (float, 2):Point2D, (int, 3):Point3I, (float, 3):Point3D} Extent = {(int, 2):Extent2I, (float, 2):Extent2D, (int, 3):Extent3I, (float, 3):Extent3D} CoordinateExpr = {2:CoordinateExpr2, 3:CoordinateExpr3}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    7cbdbdbb

    commit 7cbdbdbb52b51d8b15168a7acb5ce48ec10d99d9
    Author: Simon Krughoff 
    Date:   Thu Mar 13 14:47:11 2014 -0500
    
        Fixed namespace issue with persisting transform registries.  Added unit test for transform config round trips. Added unit test for empty bboxes in AmpInfoCatalog.
    

    8cea9ad2

    commit 8cea9ad2e43b75b6765b8d43c9a5d2b2d7bc4efa
    Author: Simon Krughoff 
    Date:   Wed Feb 19 21:09:15 2014 -0600
    
        Python code for building cameras.
    

    Return to list

    python/lsst/afw/image/utils.py

    Diff:

    1 8ebf235c + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import re import lsst.pex.policy as pexPolicy
    26 3937a7af + from lsst.afw.cameraGeom import TAN_PIXELS
    25 54a43c29 - import lsst.afw.detection as detection
    ? ^ ---
    27 8ebf235c + import lsst.afw.detection as afwDetect
    ? ^^^^ from . import imageLib as afwImage
    27 54a43c29 - import numpy
    def clipImage(im, minClip, maxClip): """Clip an image to lie between minClip and maxclip (None to ignore)""" if re.search("::MaskedImage<", im.__repr__()): mi = im else: mi = afwImage.makeMaskedImage(im, afwImage.MaskU(im.getDimensions())) if minClip is not None: ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(-minClip, afwDetect.Threshold.VALUE, False)) afwDetect.setImageFromFootprintList(mi.getImage(), ds.getFootprints(), minClip)
    41 a7aa0c91 - if maxclip is not None:
    ? ^
    42 8ebf235c + if maxClip is not None:
    ? ^
    42 4afba64d - ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(maxclip))
    ? ^
    43 8ebf235c + ds = afwDetect.FootprintSet(mi, afwDetect.Threshold(maxClip))
    ? ^
    43 a7aa0c91 - afwDetect.setImageFromFootprintList(mi.getImage(), ds.getFootprints(), maxclip)
    ? ^
    44 8ebf235c + afwDetect.setImageFromFootprintList(mi.getImage(), ds.getFootprints(), maxClip)
    ? ^
    45 e798b07c +
    46 3937a7af + def getDistortedWcs(exposureInfo, log=None):
    47 3937a7af + """!Get a WCS from an exposureInfo, with distortion terms if possible
    48 3937a7af +
    49 3937a7af + If the WCS in the exposure is a pure TAN WCS and distortion information is available
    50 3937a7af + in the exposure's Detector, then return a DistortedTanWcs that combines the
    51 3937a7af + distortion information with the pure TAN WCS.
    52 3937a7af + Otherwise return the WCS in the exposureInfo without modification.
    53 3937a7af +
    54 3937a7af + This function is intended as a temporary workaround until ISR puts a WCS with distortion information
    55 3937a7af + into its exposures.
    56 3937a7af +
    57 3937a7af + @param[in] exposureInfo exposure information (an lsst.afw.image.ExposureInfo),
    58 3937a7af + e.g. from exposure.getInfo()
    59 3937a7af + @param[in] log an lsst.pex.logging.Log or None; if specified then a warning is logged if:
    60 3937a7af + - the exposureInfo's WCS has no distortion and cannot be cast to a TanWcs
    61 3937a7af + - the expousureInfo's detector has no TAN_PIXELS transform (distortion information)
    62 3937a7af + @throw RuntimeError if exposureInfo has no WCS.
    63 3937a7af + """
    64 3937a7af + if not exposureInfo.hasWcs():
    65 3937a7af + raise RuntimeError("exposure must have a WCS to use as an initial guess")
    66 3937a7af + wcs = exposureInfo.getWcs()
    67 3937a7af + if not wcs.hasDistortion() and exposureInfo.hasDetector():
    68 3937a7af + # warn but continue if TAN_PIXELS not present or the initial WCS is not a TanWcs;
    69 3937a7af + # other errors indicate a bug that should raise an exception
    70 3937a7af + detector = exposureInfo.getDetector()
    71 3937a7af + try:
    72 3937a7af + pixelsToTanPixels = detector.getTransform(TAN_PIXELS)
    73 3937a7af + tanWcs = afwImage.TanWcs.cast(wcs)
    74 3937a7af + except Exception as e:
    75 3937a7af + if log:
    76 3937a7af + log.warn("Could not create a DistortedTanWcs: %s" % (e,))
    77 3937a7af + else:
    78 3937a7af + wcs = afwImage.DistortedTanWcs(tanWcs, pixelsToTanPixels)
    79 3937a7af + return wcs
    def resetFilters(): """Reset registry of filters and filter properties""" afwImage.Filter.reset() afwImage.FilterProperty.reset() def defineFilter(name, lambdaEff, alias=[], force=False): """Define a filter and its properties in the filter registry""" prop = afwImage.FilterProperty(name, lambdaEff, force) afwImage.Filter.define(prop) if isinstance(alias, basestring): afwImage.Filter.defineAlias(name, alias) else: for a in alias: afwImage.Filter.defineAlias(name, a) def defineFiltersFromPolicy(filterPolicy, reset=False): """Process a Policy and define the filters""" if reset: afwImage.Filter.reset() afwImage.FilterProperty.reset() # # Process the Policy and define the filters # policyFile = pexPolicy.DefaultPolicyFile("afw", "FilterDictionary.paf", "policy") defPolicy = pexPolicy.Policy.createPolicy(policyFile, policyFile.getRepositoryPath(), True) filterPolicy.mergeDefaults(defPolicy.getDictionary()) for p in filterPolicy.getArray("Filter"): afwImage.Filter.define(afwImage.FilterProperty(p.get("name"), p)) if p.exists("alias"): for a in p.getArray("alias"): afwImage.Filter.defineAlias(p.get("name"), a) class CalibNoThrow(object): """A class intended to be used with python's with statement, to return NaNs for negative fluxes instead of raising exceptions (exceptions may be raised for other purposes). E.g. with CalibNoThrow(): ax.plot([exposure.getCalib().getMagnitude(a) for a in candAmps], zGood[:,k], 'b+') """ def __enter__(self): self._throwOnNegative = afwImage.Calib.getThrowOnNegativeFlux() afwImage.Calib.setThrowOnNegativeFlux(False) def __exit__(self, *args): afwImage.Calib.setThrowOnNegativeFlux(self._throwOnNegative)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4afba64d

    commit 4afba64d7fe74d4c1ed99f21d17cbb2008c4b024
    Author: Jim Bosch 
    Date:   Mon Jan 30 19:32:36 2012 -0500
    
        removed template parameters from FootprintSet class (now constructors and a few member functions are templated); removed now-pointless(?) makeFootprintSet functions
    

    54a43c29

    commit 54a43c297a84a2586aa62781b9b01bbf8884d5bd
    Author: jbosch 
    Date:   Sat Mar 5 04:29:47 2011 +0000
    
        afw #1556 - added ndarray/numpy constructors for Image and friends, removed slower numpy conversions in image/testUtils.py, adjusted unit tests accordingly.
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    Commits in /Users/nate/repos_lsst/afw/

    e798b07c

    commit e798b07c276e0940378fce47ee1f97d35fd2ea02
    Author: rhl 
    Date:   Fri Apr 9 01:58:34 2010 +0000
    
        Added defineFiltersFromPolicy for the Butler
    

    8ebf235c

    commit 8ebf235c7c71e95b111916e1fa03957482b28dd9
    Author: Russell Owen 
    Date:   Thu Apr 2 14:06:44 2015 -0700
    
        Fix a function in image/utils.py
        
        image/utils.py contained a function clipImage that was not used anywhere.
        not tested, and badly broken. At RHL's request I fixed it to the point of making
        pyflakes happy and will file a ticket for RHL to add a unit test.
        I also added from __future__ import absolute_import, division
        
        Fix image.utils.clipImage, or at least make pyflakes linter happy
    

    3937a7af

    commit 3937a7aff7043f9ff7014bfe208604159c5e150b
    Author: Russell Owen 
    Date:   Thu Apr 2 15:37:07 2015 -0700
    
        Add image.utils.getDistortedWcs and a test for it
        
        Added a new function lsst.image.utils.getDistortedWcs.
        Added a unit test for it. To write the unit test I added a new "modFunc" argument to
        cameraGeom.getUtils.DetectorWraper.__init__ to allow flexibile modification of wrapper
        attributes just before constructing the Detector. Finally, I used that new modFunc argument
        to replace two other arguments and updated the test that used those other arguments
        to use modFunc instead.
        
        Switch from using cast_TanWcs to TanWcs.cast
        
        Fix a typo in a doc string.
    

    Return to list

    examples/decoratedImage.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    #include 
                    
    
    27 a9aec7fc + #include "lsst/utils/Utils.h"
    28 a9aec7fc + #include "lsst/pex/exceptions.h"
    #include "lsst/afw/image/Image.h" namespace afwImage = lsst::afw::image; namespace afwGeom = lsst::afw::geom; template void print(afwImage::Image& src, const std::string& title = "") { if (title.size() > 0) { printf("%s:\n", title.c_str()); } printf("%3s ", ""); for (int x = 0; x != src.getWidth(); ++x) { printf("%4d ", x); } printf("\n"); for (int y = src.getHeight() - 1; y >= 0; --y) { printf("%3d ", y); for (typename afwImage::Image::c_iterator src_it = src.row_begin(y); src_it != src.row_end(y); ++src_it) { printf("%4g ", static_cast((*src_it)[0])); } printf("\n"); } } /************************************************************************************************************/ int main(int argc, char *argv[]) { afwImage::DecoratedImage dimg(afwGeom::Extent2I(10, 6)); afwImage::Image img(*dimg.getImage()); std::string file_u16; if (argc == 2) { file_u16 = std::string(argv[1]); } else {
    64 8c6c0d93 - std::string afwdata = getenv("AFWDATA_DIR");
    65 8c6c0d93 - if (afwdata.empty()) {
    66 a9aec7fc + try {
    67 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
    68 a9aec7fc + file_u16 = dataDir + "/data/small.fits";
    69 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    66 8c6c0d93 - std::cerr << "AFWDATA_DIR not set. Provide fits file as argument or setup afwdata.\n"
    ? ^^^^^^^^^^^^^ ^^^^^^^^^
    70 a9aec7fc + std::cerr << "Error: provide fits file path as argument or setup afwdata.\n" << std::endl;
    ? ^^^ ^^^^ +++++ ++++++++++++++
    67 8c6c0d93 - << std::endl;
    exit(EXIT_FAILURE);
    69 48aa14a6 - } else {
    70 8c6c0d93 - file_u16 = afwdata + "/small_img.fits";
    } } std::cout << "Running with: " << file_u16 << std::endl; afwImage::DecoratedImage dimg2(file_u16); return 0; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    48aa14a6

    commit 48aa14a67eab96c89e6edbaa1de4ceab648f26f0
    Author: bick 
    Date:   Fri Jan 8 20:13:46 2010 +0000
    
        #1113 Updated hardcoded fits file to use a file in afwdata.
    

    8c6c0d93

    commit 8c6c0d93eaf03478cc6379a16055c3ae6119aa35
    Author: bick 
    Date:   Fri Jan 8 21:49:43 2010 +0000
    
        #1113 Changed examples to default to afwdata fits files with no arguments.
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    include/lsst/afw/image/ExposureInfo.h

    Diff:

                    // -*- LSST-C++ -*- // fixed format comment for emacs
                    /*
                     * LSST Data Management System
                     * Copyright 2008-2013 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    #ifndef LSST_AFW_IMAGE_ExposureInfo_h_INCLUDED
                    #define LSST_AFW_IMAGE_ExposureInfo_h_INCLUDED
                    
                    #include "lsst/base.h"
                    #include "lsst/daf/base.h"
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/image/Filter.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/image/CoaddInputs.h"
                    
                    namespace lsst { namespace afw {
                    
                    namespace cameraGeom {
                    class Detector;
                    }
                    
                    namespace detection {
                    class Psf;
                    }
                    
    
    44 fd15d1dd - namespace geom { namespace polygon {
    45 fd15d1dd - class Polygon;
    46 fd15d1dd - }}
    47 fd15d1dd -
    namespace fits { class Fits; } namespace image { class Calib; class Wcs;
    56 5a944adf - class ApCorrMap;
    /** * @brief A collection of all the things that make an Exposure different from a MaskedImage * * The constness semantics of the things held by ExposureInfo are admittedly a bit of a mess, * but they're that way to preserve backwards compatibility for now. Eventually I'd like to make * a lot of these things immutable, but in the meantime, here's the summary: * - Wcs, Calib, and Psf are held by non-const pointer, and you can get a non-const pointer via a * non-const member function accessor and a const pointer via a const member function accessor. * - Detector is held by const pointer and only returned by const pointer (but if you're * in Python, SWIG will have casted all that constness away). * - Filter is held and returned by value. * - Metadata is held by non-const pointer, and you can get a non-const pointer via a const * member function accessor (i.e. constness is not propagated). * * The setters for Wcs and Calib clone their input arguments (this is a departure from the * previous behavior for Calib and Wcs but it's safer w.r.t. aliasing and it matches the old * (and current) behavior of the Exposure and ExposureInfo constructors, which clone their * arguments. The setter for Psf and constructors do not clone the Psf, as Psfs are immutable * and hence we don't need to ensure strict ownership. The setter for Detector does *not* * clone its input argument, because while it technically isn't, we can safely consider a * Detector to be immutable once it's attached to an ExposureInfo. */ class ExposureInfo { public: /// Does this exposure have a Wcs? bool hasWcs() const { return static_cast(_wcs); } /// Return the coordinate system of the exposure PTR(Wcs) getWcs() { return _wcs; } /// Return the coordinate system of the exposure CONST_PTR(Wcs) getWcs() const { return _wcs; } /// Set the coordinate system of the exposure void setWcs(CONST_PTR(Wcs) wcs) { _wcs = _cloneWcs(wcs); } /// Does this exposure have Detector information? bool hasDetector() const { return static_cast(_detector); } /// Return the exposure's Detector information CONST_PTR(cameraGeom::Detector) getDetector() const { return _detector; } /// Set the exposure's Detector information void setDetector(CONST_PTR(cameraGeom::Detector) detector) { _detector = detector; } /// Return the exposure's filter Filter getFilter() const { return _filter; } /// Set the exposure's filter void setFilter(Filter const& filter) { _filter = filter; } /// Does this exposure have a Calib? bool hasCalib() const { return static_cast(_calib); } /// Return the exposure's photometric calibration PTR(Calib) getCalib() { return _calib; } /// Return the exposure's photometric calibration CONST_PTR(Calib) getCalib() const { return _calib; } /// Set the Exposure's Calib object void setCalib(CONST_PTR(Calib) calib) { _calib = _cloneCalib(calib); } /// Return flexible metadata PTR(daf::base::PropertySet) getMetadata() const { return _metadata; } /// Set the flexible metadata void setMetadata(PTR(daf::base::PropertySet) metadata) { _metadata = metadata; } /// Does this exposure have a Psf? bool hasPsf() const { return static_cast(_psf); } /// Return the exposure's point-spread function PTR(detection::Psf) getPsf() const { return _psf; } /// Set the exposure's point-spread function void setPsf(CONST_PTR(detection::Psf) psf) { // Psfs are immutable, so this is always safe; it'd be better to always just pass around // const or non-const pointers, instead of both, but this is more backwards-compatible. _psf = boost::const_pointer_cast(psf); }
    141 fd15d1dd - /// Does this exposure have a valid Polygon
    142 fd15d1dd - bool hasValidPolygon() const { return static_cast(_validPolygon);}
    143 fd15d1dd -
    144 fd15d1dd - /// Return the valid Polygon
    145 fd15d1dd - CONST_PTR(geom::polygon::Polygon) getValidPolygon() const { return _validPolygon;}
    146 fd15d1dd -
    147 fd15d1dd - /// Set the exposure's valid Polygon
    148 fd15d1dd - void setValidPolygon(CONST_PTR(geom::polygon::Polygon) polygon) { _validPolygon = polygon; }
    149 fd15d1dd -
    150 5a944adf - /// Return true if the exposure has an aperture correction map
    151 5a944adf - bool hasApCorrMap() const { return static_cast(_apCorrMap); }
    152 5a944adf -
    153 5a944adf - /// Return the exposure's aperture correction map (null pointer if !hasApCorrMap())
    154 5a944adf - PTR(ApCorrMap) getApCorrMap() { return _apCorrMap; }
    155 5a944adf -
    156 5a944adf - /// Return the exposure's aperture correction map (null pointer if !hasApCorrMap())
    157 5a944adf - PTR(ApCorrMap const) getApCorrMap() const { return _apCorrMap; }
    158 5a944adf -
    159 5a944adf - /// Set the exposure's aperture correction map (null pointer if !hasApCorrMap())
    160 5a944adf - void setApCorrMap(PTR(ApCorrMap) apCorrMap) { _apCorrMap = apCorrMap; }
    161 5a944adf -
    162 5a944adf - /**
    163 5a944adf - * Set the exposure's aperture correction map to a new, empty map
    164 5a944adf - *
    165 5a944adf - * Note that the ExposureInfo constructors do not create an empty aperture correction map,
    166 5a944adf - * so this method provide a convenient way to initialize one before filling it.
    167 5a944adf - */
    168 5a944adf - void initApCorrMap();
    169 5a944adf -
    /// Does this exposure have coadd provenance catalogs? bool hasCoaddInputs() const { return static_cast(_coaddInputs); } /// Set the exposure's coadd provenance catalogs. void setCoaddInputs(PTR(CoaddInputs) coaddInputs) { _coaddInputs = coaddInputs; } /// Return a pair of catalogs that record the inputs, if this Exposure is a coadd (otherwise null). PTR(CoaddInputs) getCoaddInputs() const { return _coaddInputs; } /** * @brief Construct an ExposureInfo from its various components. * * If a null Calib and/or PropertySet pointer is passed (the default), * a new Calib and/or PropertyList will be created. To set these pointers * to null, you must explicitly call setCalib or setMetadata after construction. */ explicit ExposureInfo( CONST_PTR(Wcs) const & wcs = CONST_PTR(Wcs)(), CONST_PTR(detection::Psf) const & psf = CONST_PTR(detection::Psf)(), CONST_PTR(Calib) const & calib = CONST_PTR(Calib)(), CONST_PTR(cameraGeom::Detector) const & detector = CONST_PTR(cameraGeom::Detector)(),
    191 fd15d1dd - CONST_PTR(geom::polygon::Polygon) const & polygon = CONST_PTR(geom::polygon::Polygon)(),
    Filter const & filter = Filter(), PTR(daf::base::PropertySet) const & metadata = PTR(daf::base::PropertySet)(),
    194 5a944adf - PTR(CoaddInputs) const & coaddInputs = PTR(CoaddInputs)(),
    ? -
    159 910062c9 + PTR(CoaddInputs) const & coaddInputs = PTR(CoaddInputs)()
    195 5a944adf - PTR(ApCorrMap) const & apCorrMap = PTR(ApCorrMap)()
    ); /// Copy constructor; deep-copies all components except the metadata. ExposureInfo(ExposureInfo const & other); /// Copy constructor; deep-copies everything, possibly including the metadata. ExposureInfo(ExposureInfo const & other, bool copyMetadata); /// Assignment; deep-copies all components except the metadata. ExposureInfo & operator=(ExposureInfo const & other); // Destructor defined in source file because we need access to destructors of forward-declared components ~ExposureInfo(); private: template friend class Exposure; /** * @brief A struct passed back and forth between Exposure and ExposureInfo when writing FITS files. * * An ExposureInfo is generally held by an Exposure, and we implement much of Exposure persistence * here in ExposureInfo. FITS writing needs to take place in three steps: * 1. Exposure calls ExposureInfo::_startWriteFits to generate the image headers in the form of * PropertyLists. The headers include archive IDs for the components of ExposureInfo, so we * have to put those in the archive at this time, and transfer the PropertyLists and archive * to the Exposure for the next step. * 2. Exposure calls MaskedImage::writeFits to save the Image, Mask, and Variance HDUs along * with the headers. * 3. Exposure calls ExposureInfo::_finishWriteFits to save the archive to additional table HDUs. */ struct FitsWriteData { PTR(daf::base::PropertyList) metadata; PTR(daf::base::PropertyList) imageMetadata; PTR(daf::base::PropertyList) maskMetadata; PTR(daf::base::PropertyList) varianceMetadata; table::io::OutputArchive archive; }; /** * @brief Start the process of writing an exposure to FITS. * * @param[in] xy0 The origin of the exposure associated with this object, used to * install a linear offset-only WCS in the FITS header. * * @sa FitsWriteData */ FitsWriteData _startWriteFits(geom::Point2I const & xy0=geom::Point2I()) const; /** * @brief Write any additional non-image HDUs to a FITS file. * * @param[in] fitsfile Open FITS object to write to. Does not need to be positioned to any * particular HDU. * * The additional HDUs will be appended to the FITS file, and should line up with the HDU index * keys included in the result of getFitsMetadata() if this is called after writing the * MaskedImage HDUs. * * @sa FitsWriteData */ void _finishWriteFits(fits::Fits & fitsfile, FitsWriteData const & data) const; /** * @brief Read from a FITS file and metadata. * * This operates in-place on this instead of returning a new object, because it will usually * only be called by the exposure constructor, which starts by default-constructing the * ExposureInfo. */ void _readFits( fits::Fits & fitsfile, PTR(daf::base::PropertySet) metadata, PTR(daf::base::PropertySet) imageMetadata ); static PTR(Calib) _cloneCalib(CONST_PTR(Calib) calib); static PTR(Wcs) _cloneWcs(CONST_PTR(Wcs) wcs);
    274 5a944adf - static PTR(ApCorrMap) _cloneApCorrMap(PTR(ApCorrMap const) apCorrMap);
    PTR(Wcs) _wcs; PTR(detection::Psf) _psf; PTR(Calib) _calib; CONST_PTR(cameraGeom::Detector) _detector;
    280 fd15d1dd - CONST_PTR(geom::polygon::Polygon) _validPolygon;
    Filter _filter; PTR(daf::base::PropertySet) _metadata; PTR(CoaddInputs) _coaddInputs;
    284 5a944adf - PTR(ApCorrMap) _apCorrMap;
    }; }}} // lsst::afw::image #endif // !LSST_AFW_IMAGE_ExposureInfo_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    fd15d1dd

    commit fd15d1dd03c8a1d1b06864fe90ad7d962bc7e567
    Author: Bob Armstrong 
    Date:   Mon Sep 15 08:34:26 2014 -0400
    
        Exposure: Add a Polygon object to Exposure.
        
        Polygons will be used to define valid regions for each CCD to
        reject vignetted regions when building the Coadd Psf.
    

    5a944adf

    commit 5a944adfda0e29fe234bd1b6e7528768f4062652
    Author: Jim Bosch 
    Date:   Tue Jun 3 16:44:07 2014 -0400
    
        Add an ApCorrMap to ExposureInfo (and by extension, Exposure).
    

    Commits in /Users/nate/repos_lsst/afw/

    910062c9

    commit 910062c9757a18d5415355827222db51a51a4ca7
    Author: Jim Bosch 
    Date:   Mon Jan 7 17:57:00 2013 -0500
    
        ExposureInfo now holds an (optional) pair of ExposureCatalogs for coadd provenance.
    

    Return to list

    src/formatters/WcsFormatter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    /** @file
                     * @brief Implementation of WcsFormatter class
                     *
                     * @author $Author: ktlim $
                     * @version $Revision: 2151 $
                     * @date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * @ingroup afw
                     */
                    
                    #ifndef __GNUC__
                    #  define __attribute__(x) /*NOTHING*/
                    #endif
                    static char const* SVNid __attribute__((unused)) = "$Id$";
                    
                    // not used? #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    //#include "boost/serialization/shared_ptr.hpp"
                    #include "wcslib/wcs.h"
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/daf/persistence/PropertySetFormatter.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/formatters/ImageFormatter.h"
                    #include "lsst/afw/formatters/MaskedImageFormatter.h"
                    #include "lsst/afw/formatters/WcsFormatter.h"
                    #include "lsst/afw/image/Wcs.h"
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.WcsFormatter", level, s);
                    }
                    
                    
                    namespace afwForm = lsst::afw::formatters;
                    namespace afwImg = lsst::afw::image;
                    namespace dafBase = lsst::daf::base;
                    namespace dafPersist = lsst::daf::persistence;
                    namespace pexPolicy = lsst::pex::policy;
                    namespace pexExcept = lsst::pex::exceptions;
                    
                    
                    dafPersist::FormatterRegistration afwForm::WcsFormatter::registration(
                        "Wcs", typeid(afwImg::Wcs), createInstance);
                    
                    afwForm::WcsFormatter::WcsFormatter(
                        pexPolicy::Policy::Ptr) :
                        dafPersist::Formatter(typeid(this)) {
                    }
                    
                    afwForm::WcsFormatter::~WcsFormatter(void) {
                    }
                    
                    void afwForm::WcsFormatter::write(
                        dafBase::Persistable const* persistable,
                        dafPersist::Storage::Ptr storage,
                        dafBase::PropertySet::Ptr) {
                        execTrace("WcsFormatter write start");
                        afwImg::Wcs const* ip =
                            dynamic_cast(persistable);
                        if (ip == 0) {
    
    95 fc19284a - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Persisting non-Wcs");
    ? ---------
    95 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Persisting non-Wcs");
    } if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { execTrace("WcsFormatter write BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & *ip; execTrace("WcsFormatter write end"); return; }
    104 fc19284a - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Unrecognized Storage for Wcs");
    ? ---------
    104 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Unrecognized Storage for Wcs");
    } dafBase::Persistable* afwForm::WcsFormatter::read( dafPersist::Storage::Ptr storage, dafBase::PropertySet::Ptr additionalData) { execTrace("WcsFormatter read start"); if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { afwImg::Wcs* ip = new afwImg::Wcs; execTrace("WcsFormatter read BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getIArchive() & *ip; execTrace("WcsFormatter read end"); return ip; } else if (typeid(*storage) == typeid(dafPersist::FitsStorage)) { execTrace("WcsFormatter read FitsStorage"); dafPersist::FitsStorage* fits = dynamic_cast(storage.get()); int hdu = additionalData->get("hdu", 0); dafBase::PropertySet::Ptr md = afwImg::readMetadata(fits->getPath(), hdu); afwImg::Wcs* ip = new afwImg::Wcs(md); execTrace("WcsFormatter read end"); return ip; }
    129 fc19284a - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Unrecognized Storage for Wcs");
    ? ---------
    129 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Unrecognized Storage for Wcs");
    } void afwForm::WcsFormatter::update( dafBase::Persistable*, dafPersist::Storage::Ptr, dafBase::PropertySet::Ptr) {
    136 fc19284a - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Unexpected call to update for Wcs");
    ? ---------
    136 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Unexpected call to update for Wcs");
    } dafBase::PropertyList::Ptr afwForm::WcsFormatter::generatePropertySet(afwImg::Wcs const& wcs) { // Only generates properties for the first wcsInfo. dafBase::PropertyList::Ptr wcsProps(new dafBase::PropertyList()); assert(wcs._wcsInfo); // default ctor is private, so an uninitialized Wcs should not exist in the wild wcsProps->add("NAXIS", wcs._wcsInfo[0].naxis, "number of data axes"); wcsProps->add("EQUINOX", wcs._wcsInfo[0].equinox, "Equinox of coordinates"); wcsProps->add("RADESYS", std::string(wcs._wcsInfo[0].radesys), "Coordinate system for equinox"); wcsProps->add("CRPIX1", wcs._wcsInfo[0].crpix[0], "WCS Coordinate reference pixel"); wcsProps->add("CRPIX2", wcs._wcsInfo[0].crpix[1], "WCS Coordinate reference pixel"); wcsProps->add("CD1_1", wcs._wcsInfo[0].cd[0], "WCS Coordinate scale matrix"); wcsProps->add("CD1_2", wcs._wcsInfo[0].cd[1], "WCS Coordinate scale matrix"); wcsProps->add("CD2_1", wcs._wcsInfo[0].cd[2], "WCS Coordinate scale matrix"); wcsProps->add("CD2_2", wcs._wcsInfo[0].cd[3], "WCS Coordinate scale matrix"); wcsProps->add("CRVAL1", wcs._wcsInfo[0].crval[0], "WCS Ref value (RA in decimal degrees)"); wcsProps->add("CRVAL2", wcs._wcsInfo[0].crval[1], "WCS Ref value (DEC in decimal degrees)"); wcsProps->add("CUNIT1", std::string(wcs._wcsInfo[0].cunit[0])); wcsProps->add("CUNIT2", std::string(wcs._wcsInfo[0].cunit[1])); std::string ctype1(wcs._wcsInfo[0].ctype[0]); std::string ctype2(wcs._wcsInfo[0].ctype[1]); wcsProps->add("CTYPE1", ctype1, "WCS Coordinate type"); wcsProps->add("CTYPE2", ctype2, "WCS Coordinate type"); return wcsProps; } template void afwForm::WcsFormatter::delegateSerialize( Archive& ar, int const, dafBase::Persistable* persistable) { execTrace("WcsFormatter delegateSerialize start"); afwImg::Wcs* ip = dynamic_cast(persistable); if (ip == 0) {
    174 fc19284a - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Serializing non-Wcs");
    ? ---------
    174 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Serializing non-Wcs");
    } // Serialize most fields normally ar & ip->_nWcsInfo & ip->_relax; ar & ip->_wcsfixCtrl & ip->_wcshdrCtrl & ip->_nReject; ar & ip->_coordSystem; // If we are loading, create the array of Wcs parameter structs if (Archive::is_loading::value) { ip->_wcsInfo = reinterpret_cast(malloc(ip->_nWcsInfo * sizeof(wcsprm))); } for (int i = 0; i < ip->_nWcsInfo; ++i) { // If we are loading, initialize the struct first if (Archive::is_loading::value) { ip->_wcsInfo[i].flag = -1; wcsini(1, 2, &(ip->_wcsInfo[i])); } // Serialize only critical Wcs parameters //wcslib provides support for arrays of wcs', but we only //implement support for one. ar & ip->_wcsInfo[i].naxis; ar & ip->_wcsInfo[i].equinox; ar & ip->_wcsInfo[i].radesys; ar & ip->_wcsInfo[i].crpix[0]; ar & ip->_wcsInfo[i].crpix[1]; ar & ip->_wcsInfo[i].cd[0]; ar & ip->_wcsInfo[i].cd[1]; ar & ip->_wcsInfo[i].cd[2]; ar & ip->_wcsInfo[i].cd[3]; ar & ip->_wcsInfo[i].crval[0]; ar & ip->_wcsInfo[i].crval[1]; ar & ip->_wcsInfo[i].cunit[0]; ar & ip->_wcsInfo[i].cunit[1]; ar & ip->_wcsInfo[i].ctype[0]; ar & ip->_wcsInfo[i].ctype[1]; ar & ip->_wcsInfo[i].altlin; // If we are loading, compute intermediate values given those above if (Archive::is_loading::value) { ip->_wcsInfo[i].flag = 0; wcsset(&(ip->_wcsInfo[i])); } } execTrace("WcsFormatter delegateSerialize end"); } template void afwForm::WcsFormatter::delegateSerialize( boost::archive::text_oarchive & , int, dafBase::Persistable*); template void afwForm::WcsFormatter::delegateSerialize( boost::archive::text_iarchive & , int, dafBase::Persistable*); template void afwForm::WcsFormatter::delegateSerialize( boost::archive::binary_oarchive & , int, dafBase::Persistable*); template void afwForm::WcsFormatter::delegateSerialize( boost::archive::binary_iarchive & , int, dafBase::Persistable*); dafPersist::Formatter::Ptr afwForm::WcsFormatter::createInstance( pexPolicy::Policy::Ptr policy) { return dafPersist::Formatter::Ptr(new afwForm::WcsFormatter(policy)); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    fc19284a

    commit fc19284a6f50da7c5c2b735324d8d05c6915c88e
    Author: ktlim 
    Date:   Sat Mar 7 01:52:21 2009 +0000
    
        Add ability to retrieve Wcs from FitsStorage.  Standardize syntax.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/footprintMergeCatalog.py

    Diff:

                    #!/usr/bin/env python
                    
                    import unittest
                    import lsst.utils.tests as tests
                    import lsst.pex.exceptions
                    import lsst.afw.image as afwImage
                    import lsst.afw.geom as afwGeom
                    import lsst.afw.detection as afwDetect
    
    9 49c1e86d - import lsst.meas.algorithms as measAlg
    import lsst.afw.table as afwTable import numpy as np #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def insertPsf(pos, im, psf, kernelSize, flux): for x, y in pos: x0 = x-kernelSize/2 y0 = y-kernelSize/2 tmpbox = afwGeom.Box2I(afwGeom.Point2I(x0,y0),afwGeom.Extent2I(kernelSize,kernelSize)) tmp = psf.computeImage(afwGeom.Point2D(x0,y0)) tmp *= flux im.getImage()[tmpbox] += tmp def mergeCatalogs(catList, names, peakDist, idFactory, indivNames=[], samePeakDist=-1.): schema = afwTable.SourceTable.makeMinimalSchema() merged = afwDetect.FootprintMergeList(schema, names) if not indivNames: indivNames = names # Count the number of objects and peaks in this list mergedList = merged.getMergedSourceCatalog(catList, indivNames, peakDist, schema, idFactory, samePeakDist) nob = len(mergedList) npeaks = sum([ len(ob.getFootprint().getPeaks()) for ob in mergedList]) return mergedList, nob, npeaks def isPeakInCatalog(peak, catalog): for record in catalog: for p in record.getFootprint().getPeaks(): if p.getI() == peak.getI(): return True return False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class FootprintMergeCatalogTestCase(tests.TestCase): def setUp(self): """Build up three different sets of objects that are to be merged""" pos1 = [(40, 40), (220, 35), (40, 48), (220, 50), (67, 67),(150, 50), (40, 90), (70, 160), (35, 255), (70, 180), (250, 200), (120, 120), (170, 180),(100, 210), (20, 210), ] pos2 = [(43, 45), (215, 31), (171, 258), (211, 117), (48, 99), (70, 160), (125, 45), (251, 33), (37, 170),(134, 191), (79, 223),(258, 182) ] pos3 = [(70,170),(219,41),(253,173),(253,192)] box = afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Point2I(300,300)) psfsig = 1.
    65 49c1e86d - kernelSize = 40
    ? ^
    64 37639218 + kernelSize = 41
    ? ^ flux = 1000 # Create a different sized psf for each image and insert them at the desired positions im1 = afwImage.MaskedImageD(box)
    70 49c1e86d - psf1 = measAlg.DoubleGaussianPsf(kernelSize, kernelSize, psfsig)
    ? ^ ^^^^^ ------
    69 37639218 + psf1 = afwDetect.GaussianPsf(kernelSize, kernelSize, psfsig)
    ? ^^^^ ^^^^ im2 = afwImage.MaskedImageD(box)
    73 49c1e86d - psf2 = measAlg.DoubleGaussianPsf(kernelSize, kernelSize, 2*psfsig)
    ? ^ ^^^^^ ------
    72 37639218 + psf2 = afwDetect.GaussianPsf(kernelSize, kernelSize, 2*psfsig)
    ? ^^^^ ^^^^ im3 = afwImage.MaskedImageD(box)
    76 49c1e86d - psf3 = measAlg.DoubleGaussianPsf(kernelSize, kernelSize, 1.3*psfsig)
    ? ^ ^^^^^ ------
    75 37639218 + psf3 = afwDetect.GaussianPsf(kernelSize, kernelSize, 1.3*psfsig)
    ? ^^^^ ^^^^ insertPsf(pos1, im1, psf1, kernelSize, flux) insertPsf(pos2, im2, psf2, kernelSize, flux) insertPsf(pos3, im3, psf3, kernelSize, flux) schema = afwTable.SourceTable.makeMinimalSchema() self.idFactory = afwTable.IdFactory.makeSimple() self.table = afwTable.SourceTable.make(schema, self.idFactory) # Create SourceCatalogs from these objects fp1 = afwDetect.FootprintSet(im1, afwDetect.Threshold(0.001), "DETECTED") self.catalog1 = afwTable.SourceCatalog(self.table) fp1.makeSources(self.catalog1) fp2 = afwDetect.FootprintSet(im2, afwDetect.Threshold(0.001), "DETECTED") self.catalog2 = afwTable.SourceCatalog(self.table) fp2.makeSources(self.catalog2) fp3 = afwDetect.FootprintSet(im3, afwDetect.Threshold(0.001), "DETECTED") self.catalog3 = afwTable.SourceCatalog(self.table) fp3.makeSources(self.catalog3) def tearDown(self): del self.catalog1 del self.catalog2 del self.catalog3 del self.table def testMerge1(self): # Add the first catalog only merge, nob, npeak = mergeCatalogs([self.catalog1], ["1"], [-1], self.idFactory) self.assertEqual(nob, 14) self.assertEqual(npeak, 15) for record in merge: self.assertTrue(record.get("merge.footprint.1")) for peak in record.getFootprint().getPeaks(): self.assertTrue(peak.get("merge.peak.1")) # area for each object pixArea = np.empty(14) pixArea.fill(69) pixArea[1] = 135 measArea = [i.getFootprint().getArea() for i in merge] self.assert_(np.all(pixArea == measArea)) # Add the first catalog and second catalog with the wrong name, which should result # an exception being raised
    127 e3cdd56c - self.assertRaisesLsstCpp(lsst.pex.exceptions.LogicErrorException,
    ? ---------
    126 f65a55f9 + self.assertRaisesLsstCpp(lsst.pex.exceptions.LogicError,
    mergeCatalogs, [self.catalog1,self.catalog2], ["1","2"], [0, 0], self.idFactory, ["1","3"]) # Add the first catalog and second catalog with the wrong number of peakDist elements, # which should raise an exception self.assertRaises(ValueError, mergeCatalogs, [self.catalog1,self.catalog2], ["1","2"], [0], self.idFactory, ["1","3"]) # Add the first catalog and second catalog with the wrong number of filters, # which should raise an exception self.assertRaises(ValueError, mergeCatalogs, [self.catalog1,self.catalog2], ["1"], [0], self.idFactory, ["1","3"]) # Add the first catalog and second catalog with minPeak < 1 so it will not add new peaks merge, nob, npeak = mergeCatalogs([self.catalog1, self.catalog2], ["1", "2"], [0, -1], self.idFactory) self.assertEqual(nob, 22) self.assertEqual(npeak, 23) # area for each object pixArea = np.ones(22) pixArea[0] = 275 pixArea[1] = 270 pixArea[2:5].fill(69) pixArea[5] = 323 pixArea[6] = 69 pixArea[7] = 261 pixArea[8:14].fill(69) pixArea[14:22].fill(261) measArea = [i.getFootprint().getArea() for i in merge] self.assert_(np.all(pixArea == measArea)) for record in merge: for peak in record.getFootprint().getPeaks(): # Should only get peaks from catalog2 if catalog1 didn't contribute to the footprint if record.get("merge.footprint.1"): self.assertTrue(peak.get("merge.peak.1")) self.assertFalse(peak.get("merge.peak.2")) else: self.assertFalse(peak.get("merge.peak.1")) self.assertTrue(peak.get("merge.peak.2")) # Same as previous with another catalog merge, nob, npeak = mergeCatalogs([self.catalog1, self.catalog2, self.catalog3], ["1", "2", "3"], [0, -1, -1], self.idFactory) self.assertEqual(nob, 19) self.assertEqual(npeak, 20) pixArea = np.ones(19) pixArea[0] = 416 pixArea[1] = 270 pixArea[2:4].fill(69) pixArea[4] = 323 pixArea[5] = 69 pixArea[6] = 406 pixArea[7] = 69 pixArea[8] = 493 pixArea[9:13].fill(69) pixArea[12:19].fill(261) measArea = [i.getFootprint().getArea() for i in merge] self.assert_(np.all(pixArea == measArea)) for record in merge: for peak in record.getFootprint().getPeaks(): # Should only get peaks from catalog2 if catalog1 didn't contribute to the footprint if record.get("merge.footprint.1"): self.assertTrue(peak.get("merge.peak.1")) self.assertFalse(peak.get("merge.peak.2")) else: self.assertFalse(peak.get("merge.peak.1")) self.assertTrue(peak.get("merge.peak.2")) # Add all the catalogs with minPeak = 0 so all peaks will be added merge, nob, npeak = mergeCatalogs([self.catalog1, self.catalog2, self.catalog3], ["1", "2", "3"], [0, 0, 0], self.idFactory) self.assertEqual(nob, 19) self.assertEqual(npeak, 30) measArea = [i.getFootprint().getArea() for i in merge] self.assert_(np.all(pixArea == measArea)) # Add all the catalogs with minPeak = 10 so some peaks will be added to the footprint merge, nob, npeak = mergeCatalogs([self.catalog1, self.catalog2, self.catalog3], ["1", "2", "3"], 10, self.idFactory) self.assertEqual(nob, 19) self.assertEqual(npeak, 25) measArea = [i.getFootprint().getArea() for i in merge] self.assert_(np.all(pixArea == measArea)) for record in merge: for peak in record.getFootprint().getPeaks(): if peak.get("merge.peak.1"): self.assertTrue(record.get("merge.footprint.1")) self.assertTrue(isPeakInCatalog(peak, self.catalog1)) elif peak.get("merge.peak.2"): self.assertTrue(record.get("merge.footprint.2")) self.assertTrue(isPeakInCatalog(peak, self.catalog2)) elif peak.get("merge.peak.3"): self.assertTrue(record.get("merge.footprint.3")) self.assertTrue(isPeakInCatalog(peak, self.catalog3)) else: self.fail("At least one merge.peak flag must be set") # Add all the catalogs with minPeak = 100 so no new peaks will be added merge, nob, npeak = mergeCatalogs([self.catalog1, self.catalog2, self.catalog3], ["1", "2", "3"], 100, self.idFactory) self.assertEqual(nob, 19) self.assertEqual(npeak, 20) measArea = [i.getFootprint().getArea() for i in merge] self.assert_(np.all(pixArea == measArea)) for record in merge: for peak in record.getFootprint().getPeaks(): if peak.get("merge.peak.1"): self.assertTrue(record.get("merge.footprint.1")) self.assertTrue(isPeakInCatalog(peak, self.catalog1)) elif peak.get("merge.peak.2"): self.assertTrue(record.get("merge.footprint.2")) self.assertTrue(isPeakInCatalog(peak, self.catalog2)) elif peak.get("merge.peak.3"): self.assertTrue(record.get("merge.footprint.3")) self.assertTrue(isPeakInCatalog(peak, self.catalog3)) else: self.fail("At least one merge.peak flag must be set") # Add footprints with large samePeakDist so that any footprint that merges will also # have the peak flagged merge, nob, npeak = mergeCatalogs([self.catalog1, self.catalog2, self.catalog3], ["1", "2", "3"], 100, self.idFactory, samePeakDist=40) # peaks detected in more than one catalog multiPeakIndex = [0, 2, 5, 7, 9] peakIndex = 0 for record in merge: for peak in record.getFootprint().getPeaks(): numPeak = np.sum([peak.get("merge.peak.1"),peak.get("merge.peak.2"), peak.get("merge.peak.3")]) if peakIndex in multiPeakIndex: self.assertTrue(numPeak > 1) else: self.assertTrue(numPeak == 1) peakIndex += 1 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" tests.init() suites = [] suites += unittest.makeSuite(FootprintMergeCatalogTestCase) suites += unittest.makeSuite(tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    49c1e86d

    commit 49c1e86d7b4036ecb1d6b5db4afa24e0db44481c
    Author: Bob Armstrong 
    Date:   Thu Nov 13 13:36:56 2014 -0500
    
        FootprintMerge: Add new class to merge Footprints from different filters.
    

    e3cdd56c

    commit e3cdd56cb8749e3a51538762c471a5e305795e55
    Author: Jim Bosch 
    Date:   Wed Dec 17 15:08:47 2014 -0500
    
        More careful handling of mismatched arrays in footprint-merge tests
        
        Some of this test code wasn't quite testing what it claimed to be testing,
        because the arrays being passed in were not all the same size, and zip()
        silently iterates over the smallest of its arguments.  The removal of
        some of the test utility code in this change is just to make it so we have
        to worry about that problem in fewer places.
        
        Also changed the failure mode to an exception instead of a warning
        and no-op; seems like a logic error that should be fatal in order to
        better catch bugs in higher-level code.
    

    Commits in /Users/nate/repos_lsst/afw/

    37639218

    commit 37639218822e27259bbe5fc51af42595c6c43268
    Author: Lauren MacArthur 
    Date:   Fri Apr 24 11:58:51 2015 -0400
    
        Adapt test code to avoid import of meas_algorithms
        
        The tests/footprintMergeCatalog.py code made use of meas_algorithms
        DoubleGaussianPsf to create a psf for a generated image.  Since afw
        does not require meas_algorithms as a build dependency, it cannot be
        assumed that the latter is set up and available.  The psf is now
        created using afw.detection's GaussianPsf.
    

    f65a55f9

    commit f65a55f97c110b934263cb7bf5f1cd8baff54b51
    Author: Lauren MacArthur 
    Date:   Wed Apr 22 13:48:07 2015 -0400
    
        Remove trailing Exception in exception names
    

    Return to list

    ups/afw.table

    Diff:

    1 6baaabc9 - setupRequired(daf_base >= 4.7.3.0)
    ? -----------
    1 962f274f + setupRequired(daf_base)
    2 57d33215 - setupRequired(daf_persistence >= 5.0.0.0)
    ? -----------
    2 962f274f + setupRequired(daf_persistence)
    3 df068fef - setupRequired(pex_config >= 4.8.0.0)
    ? -----------
    3 962f274f + setupRequired(pex_config)
    4 c155fe0f - setupRequired(ndarray >= 4.6.0.0)
    ? -----------
    4 962f274f + setupRequired(ndarray)
    5 c155fe0f - setupRequired(cfitsio >= 3260)
    ? --------
    5 962f274f + setupRequired(cfitsio)
    6 550691ab - setupRequired(wcslib >= 4.4.4)
    ? ---------
    6 962f274f + setupRequired(wcslib)
    7 c155fe0f - setupRequired(xpa >= 2.1.13)
    8 c155fe0f - setupRequired(numpy >= 1.5)
    ? -------
    7 962f274f + setupRequired(numpy)
    9 6976063e - setupRequired(minuit2 >= 5.22.00+1)
    ? -------------
    8 962f274f + setupRequired(minuit2)
    10 c155fe0f - setupRequired(eigen >= 3.0.0)
    ? ---------
    9 962f274f + setupRequired(eigen)
    11 2f79a5ce - setupRequired(gsl >= 1.15)
    ? --------
    10 962f274f + setupRequired(gsl)
    12 8ad17abb - setupRequired(fftw >= 3.1.2+1)
    ? -----------
    11 962f274f + setupRequired(fftw)
    13 2212827a - setupRequired(utils >= 4.7.3.2)
    ? -----------
    12 962f274f + setupRequired(utils)
    14 60921c8c - setupOptional(pyfits >= 2.2.2)
    ? ---------
    13 962f274f + setupOptional(pyfits)
    setupOptional(matplotlib) setupOptional(afwdata) setupOptional(cuda_toolkit) envPrepend(LD_LIBRARY_PATH, ${PRODUCT_DIR}/lib) envPrepend(DYLD_LIBRARY_PATH, ${PRODUCT_DIR}/lib) envPrepend(PYTHONPATH, ${PRODUCT_DIR}/python)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    550691ab

    commit 550691abc7722109f2c64e67833bb00414a146e6
    Author: rplante 
    Date:   Thu Jan 28 12:33:14 2010 +0000
    
        updated table file to require wcslib 4.4.4
    

    df068fef

    commit df068fefa88e06c286b0b956a47e5f604a5c51fd
    Author: Paul Price 
    Date:   Thu Mar 8 01:26:20 2012 +0900
    
        Apparently malformed pex_config setup seems to be ignored by eups.
    

    2f79a5ce

    commit 2f79a5ce36d8ba0b0d4be23078d15973f6c0d3d2
    Author: Paul Price 
    Date:   Tue Feb 7 17:26:10 2012 -0500
    
        Distortion changes require gsl 1.15, not 1.8.
    

    60921c8c

    commit 60921c8cedaa12373357e906c6fb59aa198e5c3e
    Author: rhl 
    Date:   Fri Sep 16 14:02:38 2011 +0000
    
        pyfits is not required
    

    57d33215

    commit 57d3321538c077b59869ede0681b85dd04ba185e
    Author: Jim Bosch 
    Date:   Thu Mar 15 18:08:18 2012 -0400
    
        update daf_persistence dependency version
    

    6976063e

    commit 6976063e1faec14ade0fe9fa4059947f3c46144d
    Author: rowen 
    Date:   Mon Jan 11 22:12:02 2010 +0000
    
        Fixed ups table to require minuit2 5.22.00+1.
        Thanks to Bill Baker and Ray Plante for finding this.
    

    6baaabc9

    commit 6baaabc9d809379d15d757a9a095d6c3bf736304
    Author: Serge Monkewitz 
    Date:   Tue Dec 13 07:47:00 2011 -0600
    
        Adjust table file
    

    8ad17abb

    commit 8ad17abbf115a55044253c97efb4cfeff5849a4e
    Merge: d330d4f 938a8ee
    Author: dubcovsky 
    Date:   Fri Oct 9 22:22:55 2009 +0000
    
        #905 Merging ticket branch back to trunk. This ticket introduces the notion of a FourierCutout, the fourier transformed version of an imaga, along with a FourierCutoutStack (which is simply a contiguous allocation of many FourierCutout. The more important changes are the addition of a ConvolutionVisitor base class and two subclasses ImageConvolutionVisitor and FourierConvolutionVisitor. These visitors are in place to allow kernels, and eventually PSFs to construct a specific representation of themselves by which models can be convolved. All of these changes are in the lsst::afw::math namespace
    

    c155fe0f

    commit c155fe0f254117d09241849fe3fe97ac266e224b
    Author: Kresimir Cosic 
    Date:   Mon Dec 5 22:04:14 2011 +0100
    
        merged from master to update sconsUtils, added dependencies on cuda* EUPS packages
    

    2212827a

    commit 2212827a752863ac8bf0204d570daf9990f41805
    Author: Jim Bosch 
    Date:   Mon Jan 9 23:45:38 2012 -0500
    
        added intro docs for table library
    

    Commits in /Users/nate/repos_lsst/afw/

    962f274f

    commit 962f274f14265afd5cdbba9a86c7b63d9b898c1f
    Author: Mario Juric 
    Date:   Wed Mar 5 16:28:55 2014 -0600
    
        removed explicit versions from the table file.
    

    Return to list

    src/detection/HeavyFootprint.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    /*****************************************************************************/
                    /** \file
                     *
                     * \brief HeavyFootprint and associated classes
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    #include "boost/format.hpp"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/detection/Peak.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/detection/HeavyFootprint.h"
                    #include "lsst/afw/detection/Footprint.h"
                    #include "lsst/afw/detection/FootprintCtrl.h"
                    #include "lsst/afw/detection/FootprintArray.h"
                    #include "lsst/afw/detection/FootprintArray.cc"
                    #include "lsst/afw/table/io/CatalogVector.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/table/io/InputArchive.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace detection {
                    namespace {
                        template
                        struct setPixel {
                            setPixel(T val) : _val(val) {}
                    
                            T operator()(T) const {
                                return _val;
                            }
                        private:
                            T _val;
                        };
                    
                        template<>
                        struct setPixel {
                            typedef boost::uint16_t T;
                    
                            setPixel(T val) : _mask(~val) {}
                    
                            T operator()(T pix) const {
                                pix &= _mask;
                                return pix;
                            }
                        private:
                            T _mask;
                        };
                    }
                    
    
    76 ca14db9a - /**
    77 ca14db9a - * Create a HeavyFootprint from a regular Footprint and the image that provides the pixel values
    78 92eb868e - *
    79 92eb868e - * \note: the HeavyFootprintCtrl is passed by const* not const& so that we needn't provide a definition
    80 92eb868e - * in Footprint.h
    81 ca14db9a - */
    template HeavyFootprint::HeavyFootprint(
    84 ca14db9a - Footprint const& foot, ///< The Footprint defining the pixels to set
    78 94770baf + Footprint const& foot,
    85 92eb868e - lsst::afw::image::MaskedImage const& mimage, ///< The pixel values
    ? ----------------------
    79 94770baf + lsst::afw::image::MaskedImage const& mimage,
    86 92eb868e - HeavyFootprintCtrl const *ctrl ///< Control how we manipulate HeavyFootprints
    80 94770baf + HeavyFootprintCtrl const *ctrl
    ) : Footprint(foot), _image(ndarray::allocate(ndarray::makeVector(foot.getNpix()))), _mask(ndarray::allocate(ndarray::makeVector(foot.getNpix()))), _variance(ndarray::allocate(ndarray::makeVector(foot.getNpix()))) { HeavyFootprintCtrl ctrl_s = HeavyFootprintCtrl(); if (!ctrl) { ctrl = &ctrl_s; } switch (ctrl->getModifySource()) { case HeavyFootprintCtrl::NONE: flattenArray(*this, mimage.getImage()->getArray(), _image, mimage.getXY0()); flattenArray(*this, mimage.getMask()->getArray(), _mask, mimage.getXY0()); flattenArray(*this, mimage.getVariance()->getArray(), _variance, mimage.getXY0()); break; case HeavyFootprintCtrl::SET: { ImagePixelT const ival = ctrl->getImageVal(); MaskPixelT const mval = ctrl->getMaskVal(); VariancePixelT const vval = ctrl->getVarianceVal(); flattenArray(*this, mimage.getImage()->getArray(), _image, setPixel(ival), mimage.getXY0()); flattenArray(*this, mimage.getMask()->getArray(), _mask, setPixel(mval), mimage.getXY0()); flattenArray(*this, mimage.getVariance()->getArray(), _variance, setPixel(vval), mimage.getXY0()); break; } } }
    121 ca14db9a - /**
    122 92b897b8 - * Create a HeavyFootprint from a regular Footprint, allocating space
    123 92b897b8 - * to hold foot.getArea() pixels, but not initializing them. This is
    124 92b897b8 - * used when unpersisting a HeavyFootprint.
    125 92b897b8 - */
    template HeavyFootprint::HeavyFootprint( Footprint const& foot, ///< The Footprint defining the pixels to set HeavyFootprintCtrl const* ctrl) : Footprint(foot), _image (ndarray::allocate(ndarray::makeVector(foot.getNpix()))), _mask (ndarray::allocate(ndarray::makeVector(foot.getNpix()))), _variance(ndarray::allocate(ndarray::makeVector(foot.getNpix()))) { }
    137 92b897b8 - /**
    138 ca14db9a - * Replace all the pixels in the image with the values in the HeavyFootprint
    139 ca14db9a - */
    template void HeavyFootprint::insert( lsst::afw::image::MaskedImage & mimage ///< Image to set ) const { expandArray(*this, _image, mimage.getImage()->getArray(), mimage.getXY0()); expandArray(*this, _mask, mimage.getMask()->getArray(), mimage.getXY0()); expandArray(*this, _variance, mimage.getVariance()->getArray(), mimage.getXY0()); }
    150 1e82950b - /**
    151 1e82950b - * Replace all the pixels in the image with the values in the HeavyFootprint
    152 1e82950b - */
    template void HeavyFootprint::insert(
    138 94770baf + lsst::afw::image::Image & image) const
    155 1e82950b - lsst::afw::image::Image & image ///< Image to set
    156 1e82950b - ) const
    { expandArray(*this, _image, image.getArray(), image.getXY0()); }
    161 b3dcd175 -
    162 36cfb16b - /**
    163 36cfb16b - Sums the two given HeavyFootprints *h1* and *h2*, returning a
    164 36cfb16b - HeavyFootprint with the union footprint, and summed pixels where they
    165 b2231e2b - overlap. The peak list is the union of the two inputs.
    166 36cfb16b - */
    template PTR(HeavyFootprint) mergeHeavyFootprints(HeavyFootprint const& h1, HeavyFootprint const& h2) { // Merge the Footprints (by merging the Spans) PTR(Footprint) foot = mergeFootprints(h1, h2); // Find the union bounding-box geom::Box2I bbox(h1.getBBox()); bbox.include(h2.getBBox()); // Create union-bb-sized images and insert the heavies image::MaskedImage im1(bbox); image::MaskedImage im2(bbox); h1.insert(im1); h2.insert(im2); // Add the pixels im1 += im2; // Build new HeavyFootprint from the merged spans and summed pixels. return PTR(HeavyFootprint) (new HeavyFootprint(*foot, im1));
    190 f3fa8ed3 - //PTR(HeavyFootprint) x(new HeavyFootprint(*foot, im1));
    191 f3fa8ed3 - //return x;
    } /************************************************************************************************************/ // Persistence (using afw::table::io) // namespace { // Schema and Keys used to persist the pixels of a HeavyFootprint (Spans and Peaks are handled by the // Footprint base class). This is a singleton, but a different one for each template instantiation. template struct HeavyFootprintPersistenceHelper { afw::table::Schema schema; afw::table::Key< afw::table::Array > image; afw::table::Key< afw::table::Array > mask; afw::table::Key< afw::table::Array > variance; static HeavyFootprintPersistenceHelper const & get() { static HeavyFootprintPersistenceHelper const instance; return instance; } private: HeavyFootprintPersistenceHelper() : schema(), image(schema.addField< afw::table::Array >( "image", "image pixels for HeavyFootprint", "dn" )), mask(schema.addField< afw::table::Array >( "mask", "mask pixels for HeavyFootprint" )), variance(schema.addField< afw::table::Array >( "variance", "variance pixels for HeavyFootprint", "dn^2" )) { schema.getCitizen().markPersistent(); } }; // These suffix-computing structs are used to compute the string name associated with a HeavyFootprint // for Persistence. // We don't instantiate HeavyFootprints with anything other than defaults for Mask and Variance, so we // don't bother figuring out what suffixes to use for them for now. If we change that, we just need // to add more explicit specializations of this template. template struct ComputeSuffix; template <> struct ComputeSuffix { static std::string apply() { return "U"; } }; template <> struct ComputeSuffix { static std::string apply() { return "F"; } }; template <> struct ComputeSuffix { static std::string apply() { return "D"; } }; template <> struct ComputeSuffix { static std::string apply() { return "I"; } }; } // anonymous template std::string HeavyFootprint::getPersistenceName() const { return "HeavyFootprint" + ComputeSuffix::apply(); } template void HeavyFootprint::write(OutputArchiveHandle & handle) const { HeavyFootprintPersistenceHelper const & keys = HeavyFootprintPersistenceHelper::get(); // delegate to Footprint::write to handle spans and peaks Footprint::write(handle); // add one more catalog for pixel values afw::table::BaseCatalog cat = handle.makeCatalog(keys.schema); PTR(afw::table::BaseRecord) record = cat.addNew(); // We could deep-copy the arrays instead of const-casting them, which might be marginally safer, // but we always save an OutputArchive to disk immediately after we create it, so there's really // no chance that we could get the HeavyFootprint in trouble by having this view modified. record->set(keys.image, ndarray::const_array_cast(getImageArray())); record->set(keys.mask, ndarray::const_array_cast(getMaskArray())); record->set(keys.variance, ndarray::const_array_cast(getVarianceArray())); handle.saveCatalog(cat); } template class HeavyFootprint::Factory : public afw::table::io::PersistableFactory { public: explicit Factory(std::string const & name) : afw::table::io::PersistableFactory(name) {} virtual PTR(afw::table::io::Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const { HeavyFootprintPersistenceHelper const & keys = HeavyFootprintPersistenceHelper::get(); LSST_ARCHIVE_ASSERT(catalogs.size() == 3u); PTR(HeavyFootprint) result( new HeavyFootprint() ); result->readSpans(catalogs[0]); // these read methods are inherited from Footprint result->readPeaks(catalogs[1]); afw::table::BaseRecord const & record = catalogs[2].front(); result->_image = ndarray::const_array_cast(record.get(keys.image)); result->_mask = ndarray::const_array_cast(record.get(keys.mask)); result->_variance = ndarray::const_array_cast(record.get(keys.variance)); return result; } static Factory registration; }; // initialize static instance, registering the factory with the persistence mechanism at the same time template typename HeavyFootprint::Factory HeavyFootprint::Factory::registration( "HeavyFootprint" + ComputeSuffix::apply() ); /************************************************************************************************************/ // // Explicit instantiations // \cond // // #define INSTANTIATE(TYPE) \ template class HeavyFootprint; \ template PTR(HeavyFootprint) mergeHeavyFootprints( \ HeavyFootprint const&, HeavyFootprint const&); INSTANTIATE(boost::uint16_t); INSTANTIATE(double); INSTANTIATE(float); INSTANTIATE(int); }}} // \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    92eb868e

    commit 92eb868e36a65a68c15beaa048231ede01fe1fb6
    Author: Robert Lupton the Good 
    Date:   Mon Nov 28 13:55:52 2011 -0500
    
        Add option (controlled via HeavyFootprintCtrl) to clear the image under a Footprint when creating a HeavyFootprint
    

    f3fa8ed3

    commit f3fa8ed3c1b352847076f6b6d76f07d69fe741b3
    Author: Dustin Lang 
    Date:   Thu Apr 10 15:36:50 2014 -0400
    
        minor: remove peak debugging
    

    b2231e2b

    commit b2231e2bf23bfbd0257c54a2fd2350984e5d3ebd
    Author: Dustin Lang 
    Date:   Thu Apr 10 11:41:19 2014 -0400
    
        fix peak lists in mergeFootprints() -- dumb missing reference &
    

    92b897b8

    commit 92b897b8b34d665503396103cfa1bada0b343afb
    Author: Dustin Lang 
    Date:   Thu May 24 09:51:56 2012 -0400
    
        Remove HeavyFootprintCtrl::IGNORE, instead add a new constructor; use it in FITS unpersistence
    

    36cfb16b

    commit 36cfb16be779ed99d60e5b287db72b6821d470d4
    Author: Dustin Lang 
    Date:   Wed Jan 15 16:11:28 2014 -0600
    
        add some Footprint functions used in meas_deblender: copyWithinFootprint, and mergeHeavyFootprints, including tests
    

    1e82950b

    commit 1e82950b67df0dd27bf37bc1ed4d67f126a12b4b
    Author: Dustin Lang 
    Date:   Tue Apr 3 15:58:10 2012 -0500
    
        HeavyFootprint: add overload for just setting pixels
    

    b3dcd175

    commit b3dcd17547b9491944f77e4fe31128b569aaf7fe
    Author: Dustin Lang 
    Date:   Fri May 18 23:06:14 2012 -0400
    
        save HeavyFootprints to FITS, with extra junk
    

    ca14db9a

    commit ca14db9a18583957b628ceb953de99a23a921137
    Author: Robert Lupton the Good 
    Date:   Sat Nov 26 11:59:04 2011 -0500
    
        Support making FootprintSets heavy, and swig up dynamic casts to HeavyFootprints
        
        Added doxy comments
    

    Commits in /Users/nate/repos_lsst/afw/

    94770baf

    commit 94770bafec04976204f56cf3aed80fa02bece412
    Author: Dustin Lang 
    Date:   Mon Jun 23 17:17:08 2014 -0500
    
        Address various issues from Paul Price's in-depth review.
        
        Footprint.h:
            No documentation for new methods and functions.
        
        Footprint.cc:
            Move documentation to header file.
            Indentation is inconsistent. Should always be 4.
            Don't use this-> when there is no need for it, e.g., this->addSpan should be addSpan.
            Paren following LSST_EXCEPT *must* cuddle --- it certainly may not be on the next line.
            Breaks 110 column limit.
            PixelT zero = 0; should be PixelT const zero = 0; Add const also for ix0 and iy0 --- *anywhere* the value will never change, as it helps the compiler write faster code.
            You're iterating with the postfix operator (s++) instead of prefix (++s); this can adversely affect performance in C++.
            What does the comment Ugly! refer to?
            Names foota and footb don't follow naming rules, and are a bit hard to read. Suggest aFoot and bFoot. Similarly with pka, etc.
            const Footprint::PeakList& --> Footprint::PeakList const& (throughout).
            while (1) --> while (true)
            nearestFootprint isn't documented.
            Why do you call INSTANTIATE_FLOAT on integer types???  [I renamed it -- it instantiated functions that were appropriate for *numeric*, not necessarily floating-point, types!]
            remove gratuitous 'typename'
            prefer PTR(Foo) to Foo::Ptr and CONST_PTR(Foo) to Foo:ConstPtr.
        
        HeavyFootprint?.cc:
            Some lines exceed 110 columns.
            Commented out code should be removed
        
        footprint1.py:
            Instead of self.assertTrue(a > b) use self.assertGreater(a, b). This provides a more useful message when it fails.
            Why is the trailing F required on clipToNonzeroF? It should be able to tell from the type of the image.  [fixed]
        
        Also removed stray Footprint.mergeWith() function that got messed up during rebase
    

    Return to list

    src/table/Match.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    
                    #include "boost/scoped_array.hpp"
                    
                    #include "lsst/utils/ieee.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/pex/logging/Log.h"
                    #include "lsst/afw/table/Match.h"
                    #include "lsst/afw/geom/Angle.h"
                    
                    namespace lsst { namespace afw { namespace table { namespace {
                    
                    template 
                    struct RecordPos {
                        double dec;
                        double x;
                        double y;
                        double z;
                        // JFB removed extra pointer here; this may have performance implications, but hopefully not
                        // significant ones.  BaseCatalog iterators yield temporary BaseRecord PTRs, so storing
                        // their address was no longer an option.
                        PTR(RecordT) src;
                    };
                    
                    template 
                    bool operator<(RecordPos const &s1, RecordPos const &s2) {
                        return (s1.dec < s2.dec);
                    }
                    
                    struct CmpRecordPtr {
                    
                        bool operator()(PTR(SourceRecord) const s1, PTR(SourceRecord) const s2) {
                            return s1->getY() < s2->getY();
                        }
                    
                    };
                    
                    /**
                     * Extract source positions from @a set, convert them to cartesian coordinates
                     * (for faster distance checks) and sort the resulting array of @c RecordPos
                     * instances by declination. Records with positions containing a NaN are skipped.
                     *
                     * @param[in] set          set of sources to process
                     * @param[out] positions   pointer to an array of at least @c set.size()
                     *                         RecordPos instances
                     * @return                 The number of sources with positions not containing a NaN.
                     */
                    template 
                    size_t makeRecordPositions(
                        Cat const & cat,
                        RecordPos *positions
                    ) {
                        size_t n = 0;
                        Key raKey = Cat::Table::getCoordKey().getRa();
                        Key decKey = Cat::Table::getCoordKey().getDec();
                        for (typename Cat::const_iterator i(cat.begin()), e(cat.end()); i != e; ++i) {
                            geom::Angle ra = i->get(raKey);
                            geom::Angle dec = i->get(decKey);
                            if (lsst::utils::isnan(ra.asRadians()) || lsst::utils::isnan(dec.asRadians())) {
                                continue;
                            }
                            double cosDec    = std::cos(dec);
                            positions[n].dec = dec.asRadians();
                            positions[n].x   = std::cos(ra)*cosDec;
                            positions[n].y   = std::sin(ra)*cosDec;
                            positions[n].z   = std::sin(dec);
                            positions[n].src = i;
                            ++n;
                        }
                        std::sort(positions, positions + n);
                        if (n < cat.size()) {
                            lsst::pex::logging::TTrace<1>("afw.table.matchRaDec",
                                                          "At least one source had ra or dec equal to NaN");
                        }
                        return n;
                    }
                    
                    template size_t makeRecordPositions(SimpleCatalog const &, RecordPos *);
                    template size_t makeRecordPositions(SourceCatalog const &, RecordPos *);
                    
                    template 
                    bool doSelfMatchIfSame(
                        std::vector< Match< typename Cat1::Record, typename Cat2::Record> > & result,
                        Cat1 const & cat1, Cat2 const & cat2, Angle radius
                    ) {
                        // types are different, so the catalogs are never the same.
                        return false;
                    }
                    
                    template 
                    bool doSelfMatchIfSame(
                        std::vector< Match< typename Cat::Record, typename Cat::Record> > & result,
                        Cat const & cat1, Cat const & cat2, Angle radius
                    ) {
                        if (&cat1 == &cat2) {
    
    122 3252a40a - result = matchRaDec(cat1, radius);
    122 4c363d4e + result = matchRaDec(cat1, radius, true);
    ? ++++++ return true; } return false; } } // anonymous
    129 4c363d4e -
    template std::vector< Match< typename Cat1::Record, typename Cat2::Record> >
    133 3252a40a - matchRaDec(Cat1 const & cat1, Cat2 const & cat2, Angle radius, bool closest)
    132 4c363d4e + matchRaDec(Cat1 const & cat1, Cat2 const & cat2, Angle radius, bool closest) {
    ? ++
    134 3252a40a - {
    135 3252a40a - MatchControl mc;
    136 3252a40a - mc.findOnlyClosest = closest;
    137 3252a40a -
    138 3252a40a - return matchRaDec(cat1, cat2, radius, mc);
    139 3252a40a - }
    140 3252a40a -
    141 4c363d4e - template
    142 4c363d4e - std::vector< Match< typename Cat1::Record, typename Cat2::Record> >
    143 3252a40a - matchRaDec(Cat1 const & cat1, Cat2 const & cat2, Angle radius,
    144 3252a40a - MatchControl const& mc)
    145 3252a40a - {
    typedef Match< typename Cat1::Record, typename Cat2::Record> MatchT; std::vector matches; if (doSelfMatchIfSame(matches, cat1, cat2, radius)) return matches; if (radius < 0.0 || (radius > (45. * geom::degrees))) {
    152 b7624bb3 - throw LSST_EXCEPT(pex::exceptions::RangeErrorException,
    ? ---------
    139 21597d88 + throw LSST_EXCEPT(pex::exceptions::RangeError,
    "match radius out of range (0 to 45 degrees)"); } if (cat1.size() == 0 || cat2.size() == 0) { return matches; } // setup match parameters double const d2Limit = radius.toUnitSphereDistanceSquared(); // Build position lists size_t len1 = cat1.size(); size_t len2 = cat2.size(); typedef RecordPos Pos1; typedef RecordPos Pos2; boost::scoped_array pos1(new Pos1[len1]); boost::scoped_array pos2(new Pos2[len2]); len1 = makeRecordPositions(cat1, pos1.get()); len2 = makeRecordPositions(cat2, pos2.get());
    171 81c6063a - PTR(typename Cat2::Record) nullRecord = boost::shared_ptr();
    for (size_t i = 0, start = 0; i < len1; ++i) { double minDec = pos1[i].dec - radius.asRadians(); while (start < len2 && pos2[start].dec < minDec) { ++start; } if (start == len2) { break; } double maxDec = pos1[i].dec + radius.asRadians(); size_t closestIndex = -1; // Index of closest match (if any) double d2Include = d2Limit; // Squared distance for inclusion of match bool found = false; // Found anything?
    183 81c6063a - size_t nMatches = 0; // Number of matches
    for (size_t j = start; j < len2 && pos2[j].dec <= maxDec; ++j) { double dx = pos1[i].x - pos2[j].x; double dy = pos1[i].y - pos2[j].y; double dz = pos1[i].z - pos2[j].z; double d2 = dx*dx + dy*dy + dz*dz; if (d2 < d2Include) {
    190 3252a40a - if (mc.findOnlyClosest) {
    ? - ----------
    175 b7624bb3 + if (closest) {
    d2Include = d2; closestIndex = j; found = true; } else { matches.push_back( MatchT(pos1[i].src, pos2[j].src, geom::Angle::fromUnitSphereDistanceSquared(d2)) ); }
    199 81c6063a - ++nMatches;
    } }
    202 81c6063a - if (mc.includeMismatches && nMatches == 0) {
    203 81c6063a - matches.push_back(MatchT(pos1[i].src, nullRecord, NAN));
    204 81c6063a - }
    205 3252a40a - if (mc.findOnlyClosest && found) {
    ? - ----------
    186 b7624bb3 + if (closest && found) {
    matches.push_back( MatchT(pos1[i].src, pos2[closestIndex].src, geom::Angle::fromUnitSphereDistanceSquared(d2Include)) ); } } return matches; }
    215 3252a40a - #define LSST_MATCH_RADEC(RTYPE, C1, C2) \
    216 3252a40a - template RTYPE matchRaDec(C1 const &, C2 const &, Angle, bool); \
    217 3252a40a - template RTYPE matchRaDec(C1 const &, C2 const &, Angle, MatchControl const&)
    196 4c363d4e + template SimpleMatchVector matchRaDec(SimpleCatalog const &, SimpleCatalog const &, Angle, bool);
    197 4c363d4e + template ReferenceMatchVector matchRaDec(SimpleCatalog const &, SourceCatalog const &, Angle, bool);
    198 4c363d4e + template SourceMatchVector matchRaDec(SourceCatalog const &, SourceCatalog const &, Angle, bool);
    219 3252a40a - LSST_MATCH_RADEC(SimpleMatchVector, SimpleCatalog, SimpleCatalog);
    220 3252a40a - LSST_MATCH_RADEC(ReferenceMatchVector, SimpleCatalog, SourceCatalog);
    221 3252a40a - LSST_MATCH_RADEC(SourceMatchVector, SourceCatalog, SourceCatalog);
    222 3252a40a -
    223 3252a40a - #undef LSST_MATCH_RADEC
    template std::vector< Match< typename Cat::Record, typename Cat::Record> >
    227 3252a40a - matchRaDec(Cat const &cat, geom::Angle radius, bool symmetric)
    203 4c363d4e + matchRaDec(Cat const &cat, geom::Angle radius, bool symmetric) {
    ? ++
    228 3252a40a - {
    229 3252a40a - MatchControl mc;
    230 3252a40a - mc.symmetricMatch = symmetric;
    231 3252a40a -
    232 3252a40a - return matchRaDec(cat, radius, mc);
    233 3252a40a - }
    234 3252a40a -
    235 3252a40a - template
    236 3252a40a - std::vector< Match< typename Cat::Record, typename Cat::Record> >
    237 3252a40a - matchRaDec(Cat const &cat, geom::Angle radius,
    238 3252a40a - MatchControl const& mc
    239 3252a40a - )
    240 3252a40a - {
    typedef Match MatchT; std::vector matches; if (radius < 0.0 || radius > (45.0 * geom::degrees)) {
    245 b7624bb3 - throw LSST_EXCEPT(pex::exceptions::RangeErrorException,
    ? ---------
    208 21597d88 + throw LSST_EXCEPT(pex::exceptions::RangeError,
    "match radius out of range (0 to 45 degrees)"); } if (cat.size() == 0) { return matches; } // setup match parameters double const d2Limit = radius.toUnitSphereDistanceSquared(); // Build position list size_t len = cat.size(); typedef RecordPos Pos; boost::scoped_array pos(new Pos[len]); len = makeRecordPositions(cat, pos.get()); for (size_t i = 0; i < len; ++i) { double maxDec = pos[i].dec + radius.asRadians(); for (size_t j = i + 1; j < len && pos[j].dec <= maxDec; ++j) { double dx = pos[i].x - pos[j].x; double dy = pos[i].y - pos[j].y; double dz = pos[i].z - pos[j].z; double d2 = dx*dx + dy*dy + dz*dz; if (d2 < d2Limit) { Angle d = Angle::fromUnitSphereDistanceSquared(d2); matches.push_back(MatchT(pos[i].src, pos[j].src, d));
    270 3252a40a - if (mc.symmetricMatch) {
    ? --- -----
    233 b7624bb3 + if (symmetric) {
    matches.push_back(MatchT(pos[j].src, pos[i].src, d)); } } } } return matches; }
    242 4c363d4e + template SimpleMatchVector matchRaDec(SimpleCatalog const &, Angle, bool);
    243 4c363d4e + template SourceMatchVector matchRaDec(SourceCatalog const &, Angle, bool);
    279 3252a40a - #define LSST_MATCH_RADEC(RTYPE, C) \
    280 3252a40a - template RTYPE matchRaDec(C const &, Angle, bool); \
    281 3252a40a - template RTYPE matchRaDec(C const &, Angle, MatchControl const&)
    283 3252a40a - LSST_MATCH_RADEC(SimpleMatchVector, SimpleCatalog);
    284 3252a40a - LSST_MATCH_RADEC(SourceMatchVector, SourceCatalog);
    285 3252a40a -
    286 3252a40a - #undef LSST_MATCH_RADEC
    SourceMatchVector matchXy(SourceCatalog const &cat1, SourceCatalog const &cat2,
    289 3252a40a - double radius, bool closest)
    247 4900a14b + double radius, bool closest) {
    ? ++
    290 3252a40a - {
    291 3252a40a - MatchControl mc;
    292 3252a40a - mc.findOnlyClosest = closest;
    293 b7624bb3 -
    294 3252a40a - return matchXy(cat1, cat2, radius, mc);
    295 3252a40a - }
    296 4c363d4e -
    297 4c363d4e - SourceMatchVector matchXy(SourceCatalog const &cat1, SourceCatalog const &cat2,
    298 3252a40a - double radius, MatchControl const& mc)
    299 3252a40a - {
    if (&cat1 == &cat2) { return matchXy(cat1, radius); } // setup match parameters double const r2 = radius*radius; // copy and sort array of pointers on y size_t len1 = cat1.size(); size_t len2 = cat2.size(); boost::scoped_array pos1(new PTR(SourceRecord)[len1]); boost::scoped_array pos2(new PTR(SourceRecord)[len2]);
    311 81c6063a - PTR(SourceRecord) nullRecord = boost::shared_ptr();
    size_t n = 0; for (SourceCatalog::const_iterator i(cat1.begin()), e(cat1.end()); i != e; ++i) { if (lsst::utils::isnan(i->getX()) || lsst::utils::isnan(i->getY())) { continue; } pos1[n] = i; ++n; } len1 = n; n = 0; for (SourceCatalog::const_iterator i(cat2.begin()), e(cat2.end()); i != e; ++i) { if (lsst::utils::isnan(i->getX()) || lsst::utils::isnan(i->getY())) { continue; } pos2[n] = i; ++n; } len2 = n; std::sort(pos1.get(), pos1.get() + len1, CmpRecordPtr()); std::sort(pos2.get(), pos2.get() + len2, CmpRecordPtr()); SourceMatchVector matches; for (size_t i = 0, start = 0; i < len1; ++i) { double y = pos1[i]->getY(); double minY = y - radius; while (start < len2 && pos2[start]->getY() < minY) { ++start; } if (start == len2) { break; } double x = pos1[i]->getX(); double maxY = y + radius; double y2; size_t closestIndex = -1; // Index of closest match (if any) double r2Include = r2; // Squared radius for inclusion of match bool found = false; // Found anything?
    348 81c6063a - size_t nMatches = 0; // Number of matches
    for (size_t j = start; j < len2 && (y2 = pos2[j]->getY()) <= maxY; ++j) { double dx = x - pos2[j]->getX(); double dy = y - y2; double d2 = dx*dx + dy*dy; if (d2 < r2Include) {
    354 3252a40a - if (mc.findOnlyClosest) {
    ? - ----------
    300 b7624bb3 + if (closest) {
    r2Include = d2; closestIndex = j; found = true; } else { matches.push_back(SourceMatch(pos1[i], pos2[j], std::sqrt(d2))); }
    361 81c6063a - ++nMatches;
    } }
    364 81c6063a - if (mc.includeMismatches && nMatches == 0) {
    365 81c6063a - matches.push_back(SourceMatch(pos1[i], nullRecord, NAN));
    366 81c6063a - }
    367 3252a40a - if (mc.findOnlyClosest && found) {
    ? - ----------
    309 b7624bb3 + if (closest && found) {
    matches.push_back(SourceMatch(pos1[i], pos2[closestIndex], std::sqrt(r2Include))); } } return matches; } SourceMatchVector matchXy( SourceCatalog const & cat, double radius, bool symmetric
    318 4900a14b + ) {
    376 3252a40a - )
    377 3252a40a - {
    378 3252a40a - MatchControl mc;
    379 3252a40a - mc.symmetricMatch = symmetric;
    380 3252a40a -
    381 3252a40a - return matchXy(cat, radius, mc);
    382 3252a40a - }
    383 3252a40a -
    384 3252a40a - SourceMatchVector matchXy(
    385 3252a40a - SourceCatalog const & cat, double radius,
    386 3252a40a - MatchControl const& mc
    387 3252a40a - )
    388 3252a40a - {
    // setup match parameters double const r2 = radius*radius; // copy and sort array of pointers on y size_t len = cat.size(); boost::scoped_array pos(new PTR(SourceRecord)[len]); size_t n = 0; for (SourceCatalog::const_iterator i(cat.begin()), e(cat.end()); i != e; ++i) { if (lsst::utils::isnan(i->getX()) || lsst::utils::isnan(i->getY())) { continue; } pos[n] = i; ++n; } len = n; std::sort(pos.get(), pos.get() + len, CmpRecordPtr()); SourceMatchVector matches; for (size_t i = 0; i < len; ++i) { double x = pos[i]->getX(); double y = pos[i]->getY(); double maxY = y + radius; double y2; for (size_t j = i + 1; j < len && (y2 = pos[j]->getY()) <= maxY; ++j) { double dx = x - pos[j]->getX(); double dy = y - y2; double d2 = dx*dx + dy*dy; if (d2 < r2) { double d = std::sqrt(d2); matches.push_back(SourceMatch(pos[i], pos[j], d));
    420 3252a40a - if (mc.symmetricMatch) {
    ? --- -----
    350 b7624bb3 + if (symmetric) {
    matches.push_back(SourceMatch(pos[j], pos[i], d)); } } } } return matches; } template BaseCatalog packMatches( std::vector< Match > const & matches ) { Schema schema; Key outKey1 = schema.addField("first", "ID for first source record in match."); Key outKey2 = schema.addField("second", "ID for second source record in match."); Key keyD = schema.addField("distance", "Distance between matches sources."); BaseCatalog result(schema); result.getTable()->preallocate(matches.size()); result.reserve(matches.size()); typedef typename std::vector< Match >::const_iterator Iter; for (Iter i = matches.begin(); i != matches.end(); ++i) { PTR(BaseRecord) record = result.addNew(); record->set(outKey1, i->first->getId()); record->set(outKey2, i->second->getId()); record->set(keyD, i->distance); } return result; } template BaseCatalog packMatches(SimpleMatchVector const &); template BaseCatalog packMatches(ReferenceMatchVector const &); template BaseCatalog packMatches(SourceMatchVector const &); template std::vector< Match< typename Cat1::Record, typename Cat2::Record> > unpackMatches(BaseCatalog const & matches, Cat1 const & first, Cat2 const & second) { pex::logging::Log tableLog(pex::logging::Log::getDefaultLog(), "afw.table"); Key inKey1 = matches.getSchema()["first"]; Key inKey2 = matches.getSchema()["second"]; Key keyD = matches.getSchema()["distance"]; if (!first.isSorted() || !second.isSorted()) throw LSST_EXCEPT(
    463 4900a14b - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    393 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Catalogs passed to unpackMatches must be sorted." ); typedef Match< typename Cat1::Record, typename Cat2::Record> MatchT; std::vector result; result.resize(matches.size()); typename std::vector::iterator j = result.begin(); for (BaseCatalog::const_iterator i = matches.begin(); i != matches.end(); ++i, ++j) { typename Cat1::const_iterator k1 = first.find(i->get(inKey1)); typename Cat2::const_iterator k2 = second.find(i->get(inKey2)); if (k1 != first.end()) { j->first = k1; } else { tableLog.log( pex::logging::Log::WARN, boost::format("Persisted match record with ID %s not found in catalog 1.") % i->get(inKey1) ); } if (k2 != second.end()) { j->second = k2; } else { tableLog.log( pex::logging::Log::WARN, boost::format("Persisted match record with ID %s not found in catalog 2.") % i->get(inKey2) ); } j->distance = i->get(keyD); } return result; } template SimpleMatchVector unpackMatches(BaseCatalog const &, SimpleCatalog const &, SimpleCatalog const &); template ReferenceMatchVector unpackMatches( BaseCatalog const &, SimpleCatalog const &, SourceCatalog const & ); template SourceMatchVector unpackMatches(BaseCatalog const &, SourceCatalog const &, SourceCatalog const &); }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4c363d4e

    commit 4c363d4e26003e91da9c9731de483546f68950f9
    Author: Jim Bosch 
    Date:   Fri Feb 24 16:50:39 2012 -0500
    
        more refactoring of matching; should finally be usable with meas_astrom (using SimpleRecord/Table for reference catalogs)
    

    81c6063a

    commit 81c6063a32883b748f3770b7124d74ced7b480f5
    Author: Jose Garmilla 
    Date:   Thu Jun 12 16:14:39 2014 -0400
    
        Implement and test includeMismatches option in MatchControl object
    

    b7624bb3

    commit b7624bb36ee62931224ca8c29763d5364ae270ce
    Author: Jim Bosch 
    Date:   Tue Feb 21 19:48:03 2012 -0500
    
        reimplemented matching to work on arbitrary records rather than sources; need to modify source matching to delegate to it
    

    3252a40a

    commit 3252a40ad55222b882acf14d2f7cf0f3fe80f585
    Author: Robert Lupton the Good 
    Date:   Tue Jun 10 15:00:58 2014 -0400
    
        Added MatchControl and implemented it for matchXY and MatchRaDec
        
        N.b. added some missing tests on matchXY, although it is unchanged by this
        changeset
    

    4900a14b

    commit 4900a14b62b47e2d9d3c00e8db7e515f76700df5
    Author: Jim Bosch 
    Date:   Wed Feb 22 23:36:01 2012 -0500
    
        refactored SourceMatch to support matching arbitrary Record objects with explicit keys for coordinate and ID fields
    

    Commits in /Users/nate/repos_lsst/afw/

    4c363d4e

    commit 4c363d4e26003e91da9c9731de483546f68950f9
    Author: Jim Bosch 
    Date:   Fri Feb 24 16:50:39 2012 -0500
    
        more refactoring of matching; should finally be usable with meas_astrom (using SimpleRecord/Table for reference catalogs)
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    b7624bb3

    commit b7624bb36ee62931224ca8c29763d5364ae270ce
    Author: Jim Bosch 
    Date:   Tue Feb 21 19:48:03 2012 -0500
    
        reimplemented matching to work on arbitrary records rather than sources; need to modify source matching to delegate to it
    

    4900a14b

    commit 4900a14b62b47e2d9d3c00e8db7e515f76700df5
    Author: Jim Bosch 
    Date:   Wed Feb 22 23:36:01 2012 -0500
    
        refactored SourceMatch to support matching arbitrary Record objects with explicit keys for coordinate and ID fields
    

    Return to list

    python/lsst/afw/display/saturated.cc

    Diff:

                    /**
                     * \file
                     *
                     * Handle saturated pixels when making colour images
                     */
                    #include "boost/format.hpp"
                    #include "lsst/utils/ieee.h"
                    #include "lsst/afw/detection.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "Rgb.h"
                    
                    namespace lsst { namespace afw { namespace display {
                    
                    namespace {
                        template 
                        class SetPixels : public detection::FootprintFunctor {
                        public:
                            explicit SetPixels(ImageT const& img     // The image the source lives in
                                              ) : detection::FootprintFunctor(img), _value(0) {}
                    
                            void setValue(float value) { _value = value; }
                    
                            // method called for each pixel by apply()
                            void operator()(typename ImageT::xy_locator loc,        // locator pointing at the pixel
                                            int,                                    // column-position of pixel
                                            int                                     // row-position of pixel
                                           ) {
                                *loc = _value;
                            }
                        private:
                            float _value;
                        };
                    }
                    
                    template
                    void
                    replaceSaturatedPixels(ImageT & rim,    // R image (e.g. i)
                                           ImageT & gim,    // G image (e.g. r)
                                           ImageT & bim,    // B image (e.g. g)
                                           int borderWidth, // width of border used to estimate colour of saturated regions
                                           float saturatedPixelValue // the brightness of a saturated pixel, once fixed
                                          )
                    {
                        int const width = rim.getWidth(), height = rim.getHeight();
                        int const x0 = rim.getX0(), y0 = rim.getY0();
                    
                        if (width != gim.getWidth() || height != gim.getHeight() || x0 != gim.getX0() || y0 != gim.getY0()) {
    
    48 6295076e - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    48 7e2503b6 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("R image has different size/origin from G image " "(%dx%d+%d+%d v. %dx%d+%d+%d") % width % height % x0 % y0 % gim.getWidth() % gim.getHeight() % gim.getX0() % gim.getY0())); } if (width != bim.getWidth() || height != bim.getHeight() || x0 != bim.getX0() || y0 != bim.getY0()) {
    56 6295076e - throw LSST_EXCEPT(pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    56 7e2503b6 + throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("R image has different size/origin from B image " "(%dx%d+%d+%d v. %dx%d+%d+%d") % width % height % x0 % y0 % bim.getWidth() % bim.getHeight() % bim.getX0() % bim.getY0())); } bool const useMaxPixel = !utils::isfinite(saturatedPixelValue); SetPixels setR(*rim.getImage()), setG(*gim.getImage()), setB(*bim.getImage()); // functors used to set pixel values // Find all the saturated pixels in any of the three image int const npixMin = 1; // minimum number of pixels in an object afw::image::MaskPixel const SAT = rim.getMask()->getPlaneBitMask("SAT"); detection::Threshold const satThresh(SAT, detection::Threshold::BITMASK); detection::FootprintSet sat(*rim.getMask(), satThresh, npixMin); sat.merge(detection::FootprintSet(*gim.getMask(), satThresh, npixMin)); sat.merge(detection::FootprintSet(*bim.getMask(), satThresh, npixMin)); // go through the list of saturated regions, determining the mean colour of the surrounding pixels typedef detection::FootprintSet::FootprintList FootprintList; PTR(FootprintList) feet = sat.getFootprints(); for (FootprintList::const_iterator ptr = feet->begin(), end = feet->end(); ptr != end; ++ptr) { PTR(detection::Footprint) const foot = *ptr; PTR(detection::Footprint) const bigFoot = growFootprint(*foot, borderWidth); double sumR = 0, sumG = 0, sumB = 0; // sum of all non-saturated adjoining pixels double maxR = 0, maxG = 0, maxB = 0; // maximum of non-saturated adjoining pixels for (detection::Footprint::SpanList::const_iterator sptr = bigFoot->getSpans().begin(), send = bigFoot->getSpans().end(); sptr != send; ++sptr) { PTR(detection::Span) const span = *sptr; int const y = span->getY() - y0; if (y < 0 || y >= height) { continue; } int sx0 = span->getX0() - x0; if (sx0 < 0) { sx0 = 0; } int sx1 = span->getX1() - x0; if (sx1 >= width) { sx1 = width - 1; } for (typename ImageT::iterator rptr = rim.at(sx0, y), rend = rim.at(sx1 + 1, y), gptr = gim.at(sx0, y), bptr = bim.at(sx0, y); rptr != rend; ++rptr, ++gptr, ++bptr) { if (!((rptr.mask() | gptr.mask() | bptr.mask()) & SAT)) { float val = rptr.image(); sumR += val; if (val > maxR) { maxR = val; } val = gptr.image(); sumG += val; if (val > maxG) { maxG = val; } val = bptr.image(); sumB += val; if (val > maxB) { maxB = val; } } } } // OK, we have the mean fluxes for the pixels surrounding this set of saturated pixels // so we can figure out the proper values to use for the saturated ones float R = 0, G = 0, B = 0; // mean intensities if (sumR + sumB + sumG > 0) { if (sumR > sumG) { if (sumR > sumB) { R = useMaxPixel ? maxR : saturatedPixelValue; G = (R*sumG)/sumR; B = (R*sumB)/sumR; } else { B = useMaxPixel ? maxB : saturatedPixelValue; R = (B*sumR)/sumB; G = (B*sumG)/sumB; } } else { if (sumG > sumB) { G = useMaxPixel ? maxG : saturatedPixelValue; R = (G*sumR)/sumG; B = (G*sumB)/sumG; } else { B = useMaxPixel ? maxB : saturatedPixelValue; R = (B*sumR)/sumB; G = (B*sumG)/sumB; } } } // Now that we know R, G, and B we can fix the values setR.setValue(R); setR.apply(*foot); setG.setValue(G); setG.apply(*foot); setB.setValue(B); setB.apply(*foot); } } template void replaceSaturatedPixels(image::MaskedImage & rim, image::MaskedImage & gim, image::MaskedImage & bim, int borderWidth, float saturatedPixelValue ); }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6295076e

    commit 6295076e1f08c8b3bdde0e21a7adee46ec1bdb51
    Author: Robert Lupton the Good 
    Date:   Wed Mar 18 21:23:49 2015 -0700
    
        Changes to back out LSST changes with exception names and testing
    

    Commits in /Users/nate/repos_lsst/afw/

    7e2503b6

    commit 7e2503b6b492a50a007c974e9a05a2cc64fd0138
    Author: Robert Lupton the Good 
    Date:   Mon Mar 16 18:01:42 2015 -0400
    
        Initial port/rewrite from afw_extensions_rgb
        
        With changes from code reviews squashed in
    

    Return to list

    src/formatters/TanWcsFormatter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    /** @file
                     * @brief Implementation of TanWcsFormatter class
                     *
                     * @author $Author$
                     * @version $Revision$
                     * @date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * @ingroup afw
                     */
                    
                    #ifndef __GNUC__
                    #  define __attribute__(x) /*NOTHING*/
                    #endif
                    static char const* SVNid __attribute__((unused)) = "$Id$";
                    
                    //#include "boost/serialization/shared_ptr.hpp"
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "wcslib/wcs.h"
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/daf/persistence/PropertySetFormatter.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/formatters/ImageFormatter.h"
                    #include "lsst/afw/formatters/MaskedImageFormatter.h"
                    #include "lsst/afw/formatters/TanWcsFormatter.h"
                    #include "lsst/afw/image/TanWcs.h"
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.TanWcsFormatter", level, s);
                    }
                    
                    
                    namespace afwForm = lsst::afw::formatters;
                    namespace afwImg = lsst::afw::image;
                    namespace dafBase = lsst::daf::base;
                    namespace dafPersist = lsst::daf::persistence;
                    namespace pexPolicy = lsst::pex::policy;
                    namespace pexExcept = lsst::pex::exceptions;
                    
                    
                    dafPersist::FormatterRegistration afwForm::TanWcsFormatter::registration(
                        "TanWcs", typeid(afwImg::TanWcs), createInstance);
                    
                    afwForm::TanWcsFormatter::TanWcsFormatter(
                        pexPolicy::Policy::Ptr) :
                        dafPersist::Formatter(typeid(this)) {
                    }
                    
                    afwForm::TanWcsFormatter::~TanWcsFormatter(void) {
                    }
                    
                    void afwForm::TanWcsFormatter::write(
                        dafBase::Persistable const* persistable,
                        dafPersist::Storage::Ptr storage,
                        dafBase::PropertySet::Ptr) {
                        execTrace("TamWcsFormatter write start");
                        afwImg::TanWcs const* ip = dynamic_cast(persistable);
                        if (ip == 0) {
    
    93 0198c5d8 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Persisting non-TanWcs");
    ? ---------
    93 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Persisting non-TanWcs");
    } if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { execTrace("TanWcsFormatter write BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & *ip; execTrace("TanWcsFormatter write end"); return; }
    102 0198c5d8 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Unrecognized Storage for TanWcs");
    ? ---------
    102 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Unrecognized Storage for TanWcs");
    } dafBase::Persistable* afwForm::TanWcsFormatter::read( dafPersist::Storage::Ptr storage, dafBase::PropertySet::Ptr additionalData) { execTrace("TanWcsFormatter read start"); if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { afwImg::TanWcs* ip = new afwImg::TanWcs; execTrace("TanWcsFormatter read BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getIArchive() & *ip; execTrace("TanWcsFormatter read end"); return ip; } else if (typeid(*storage) == typeid(dafPersist::FitsStorage)) { execTrace("TanWcsFormatter read FitsStorage"); dafPersist::FitsStorage* fits = dynamic_cast(storage.get()); int hdu = additionalData->get("hdu", 0); dafBase::PropertySet::Ptr md = afwImg::readMetadata(fits->getPath(), hdu); afwImg::TanWcs* ip = new afwImg::TanWcs(md); execTrace("TanWcsFormatter read end"); return ip; }
    127 0198c5d8 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Unrecognized Storage for TanWcs");
    ? ---------
    127 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Unrecognized Storage for TanWcs");
    } void afwForm::TanWcsFormatter::update( dafBase::Persistable*, dafPersist::Storage::Ptr, dafBase::PropertySet::Ptr) {
    134 0198c5d8 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Unexpected call to update for TanWcs");
    ? ---------
    134 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Unexpected call to update for TanWcs");
    } /// Provide a function to serialise an Eigen::Matrix so we can persist the SIP matrices template void serializeEigenArray(Archive& ar, Eigen::Matrix& m) { int rows = m.rows(); int cols = m.cols(); ar & rows & cols; if (Archive::is_loading::value) { m = Eigen::Matrix(rows, cols); } for (int j = 0; j < m.cols(); ++j) { for (int i = 0; i < m.rows(); ++i) { ar & m(i,j); } } } static void encodeSipHeader(lsst::daf::base::PropertySet::Ptr wcsProps, std::string const& which, ///< Either A,B, Ap or Bp Eigen::Matrix const& m) { int order = m.rows(); if (m.cols() != order) {
    160 0b63a043 - throw LSST_EXCEPT(pexExcept::DomainErrorException,
    ? ---------
    160 21597d88 + throw LSST_EXCEPT(pexExcept::DomainError,
    "sip" + which + " matrix is not square"); } if (order > 0) { order -= 1; // match SIP convention wcsProps->add(which + "_ORDER", static_cast(order)); for (int i = 0; i <= order; ++i) { for (int j = 0; j <= order; ++j) { double val = m(i, j); if (val != 0.0) { wcsProps->add((boost::format("%1%_%2%_%3%") % which % i % j).str(), val); } } } } } dafBase::PropertyList::Ptr afwForm::TanWcsFormatter::generatePropertySet(afwImg::TanWcs const& wcs) { // Only generates properties for the first wcsInfo. dafBase::PropertyList::Ptr wcsProps(new dafBase::PropertyList()); if (wcs._wcsInfo == NULL) { // nothing to add return wcsProps; } wcsProps->add("NAXIS", wcs._wcsInfo[0].naxis, "number of data axes"); wcsProps->add("EQUINOX", wcs._wcsInfo[0].equinox, "Equinox of coordinates"); wcsProps->add("RADESYS", std::string(wcs._wcsInfo[0].radesys), "Coordinate system for equinox"); wcsProps->add("CRPIX1", wcs._wcsInfo[0].crpix[0], "WCS Coordinate reference pixel"); wcsProps->add("CRPIX2", wcs._wcsInfo[0].crpix[1], "WCS Coordinate reference pixel"); wcsProps->add("CD1_1", wcs._wcsInfo[0].cd[0], "WCS Coordinate scale matrix"); wcsProps->add("CD1_2", wcs._wcsInfo[0].cd[1], "WCS Coordinate scale matrix"); wcsProps->add("CD2_1", wcs._wcsInfo[0].cd[2], "WCS Coordinate scale matrix"); wcsProps->add("CD2_2", wcs._wcsInfo[0].cd[3], "WCS Coordinate scale matrix"); wcsProps->add("CRVAL1", wcs._wcsInfo[0].crval[0], "WCS Ref value (RA in decimal degrees)"); wcsProps->add("CRVAL2", wcs._wcsInfo[0].crval[1], "WCS Ref value (DEC in decimal degrees)"); wcsProps->add("CUNIT1", std::string(wcs._wcsInfo[0].cunit[0])); wcsProps->add("CUNIT2", std::string(wcs._wcsInfo[0].cunit[1])); //Hack. Because wcslib4.3 gets confused when it's passed RA---TAN-SIP, //we set the value of ctypes to just RA---TAN, regardless of whether //the SIP types are present. But when we persist to a file, we need to //check whether the SIP polynomials were actually there and correct //ctypes if necessary. Bad things will happen if someone tries to //use a system other than RA---TAN and DEC--TAN std::string ctype1(wcs._wcsInfo[0].ctype[0]); std::string ctype2(wcs._wcsInfo[0].ctype[1]); if (wcs._hasDistortion) { if (ctype1.rfind("-SIP") == std::string::npos) { ctype1 += "-SIP"; } if (ctype2.rfind("-SIP") == std::string::npos) { ctype2 += "-SIP"; } encodeSipHeader(wcsProps, "A", wcs._sipA); encodeSipHeader(wcsProps, "B", wcs._sipB); encodeSipHeader(wcsProps, "AP", wcs._sipAp); encodeSipHeader(wcsProps, "BP", wcs._sipBp); } wcsProps->add("CTYPE1", ctype1, "WCS Coordinate type"); wcsProps->add("CTYPE2", ctype2, "WCS Coordinate type"); return wcsProps; } template void afwForm::TanWcsFormatter::delegateSerialize( Archive& ar, int const, dafBase::Persistable* persistable) { execTrace("TanWcsFormatter delegateSerialize start"); afwImg::TanWcs* ip = dynamic_cast(persistable); if (ip == 0) {
    234 0198c5d8 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Serializing non-TanWcs");
    ? ---------
    234 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Serializing non-TanWcs");
    } // Serialize most fields normally ar & ip->_nWcsInfo & ip->_relax; ar & ip->_wcsfixCtrl & ip->_wcshdrCtrl & ip->_nReject; ar & ip->_coordSystem; ar & ip->_hasDistortion; if(ip->_hasDistortion) { serializeEigenArray(ar, ip->_sipA); serializeEigenArray(ar, ip->_sipAp); serializeEigenArray(ar, ip->_sipB); serializeEigenArray(ar, ip->_sipBp); } // If we are loading, create the array of Wcs parameter structs if (Archive::is_loading::value) { ip->_wcsInfo = reinterpret_cast(malloc(ip->_nWcsInfo * sizeof(wcsprm))); } for (int i = 0; i < ip->_nWcsInfo; ++i) { // If we are loading, initialize the struct first if (Archive::is_loading::value) { ip->_wcsInfo[i].flag = -1; wcsini(1, 2, &(ip->_wcsInfo[i])); } // Serialize only critical Wcs parameters ar & ip->_wcsInfo[i].naxis; ar & ip->_wcsInfo[i].equinox; ar & ip->_wcsInfo[i].radesys; ar & ip->_wcsInfo[i].crpix[0]; ar & ip->_wcsInfo[i].crpix[1]; ar & ip->_wcsInfo[i].cd[0]; ar & ip->_wcsInfo[i].cd[1]; ar & ip->_wcsInfo[i].cd[2]; ar & ip->_wcsInfo[i].cd[3]; ar & ip->_wcsInfo[i].crval[0]; ar & ip->_wcsInfo[i].crval[1]; ar & ip->_wcsInfo[i].cunit[0]; ar & ip->_wcsInfo[i].cunit[1]; ar & ip->_wcsInfo[i].ctype[0]; ar & ip->_wcsInfo[i].ctype[1]; ar & ip->_wcsInfo[i].altlin; // If we are loading, compute intermediate values given those above if (Archive::is_loading::value) { ip->_wcsInfo[i].flag = 0; wcsset(&(ip->_wcsInfo[i])); } } execTrace("TanWcsFormatter delegateSerialize end"); } template void afwForm::TanWcsFormatter::delegateSerialize( boost::archive::text_oarchive & , int, dafBase::Persistable*); template void afwForm::TanWcsFormatter::delegateSerialize( boost::archive::text_iarchive & , int, dafBase::Persistable*); template void afwForm::TanWcsFormatter::delegateSerialize( boost::archive::binary_oarchive & , int, dafBase::Persistable*); template void afwForm::TanWcsFormatter::delegateSerialize( boost::archive::binary_iarchive & , int, dafBase::Persistable*); dafPersist::Formatter::Ptr afwForm::TanWcsFormatter::createInstance( pexPolicy::Policy::Ptr policy) { return dafPersist::Formatter::Ptr(new afwForm::TanWcsFormatter(policy)); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0198c5d8

    commit 0198c5d858dc4627757f8052f34ba35e74f583f6
    Author: fergal 
    Date:   Fri Feb 19 21:26:32 2010 +0000
    
        Various syntax changes to get sources to compile.
    

    0b63a043

    commit 0b63a0434d89dd25964154c767884cbebb2d2b00
    Author: fergal 
    Date:   Thu Feb 18 21:09:43 2010 +0000
    
        Added a formatter for TanWcs
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/image/wcs.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /************************************************************************************************************/
                    
                    %import "lsst/afw/table/io/ioLib.i"
                    
                    %declareTablePersistable(Wcs, lsst::afw::image::Wcs);
                    %declareTablePersistable(TanWcs, lsst::afw::image::TanWcs);
                    
                    %ignore lsst::afw::image::NoWcs;
                    
                    %{
                    #include "boost/shared_ptr.hpp"
                    #include "lsst/afw/image/Wcs.h"
                    #include "lsst/afw/image/TanWcs.h"
    
    38 a0b9d98c + #include "lsst/afw/image/DistortedTanWcs.h"
    %} %shared_ptr(lsst::afw::image::XYTransformFromWcsPair);
    42 a0b9d98c + %shared_ptr(lsst::afw::image::DistortedTanWcs);
    %include "lsst/afw/image/Wcs.h" %include "lsst/afw/image/TanWcs.h"
    46 a0b9d98c + %include "lsst/afw/image/DistortedTanWcs.h"
    %lsst_persistable(lsst::afw::image::Wcs); %lsst_persistable(lsst::afw::image::TanWcs); %inline %{ #include #include #include #include #include "lsst/daf/persistence/PropertySetFormatter.h" #include std::string pickleMetadata(CONST_PTR(lsst::daf::base::PropertySet) header) { std::stringstream ss; boost::archive::binary_oarchive ar(ss); ar << *header; return ss.str(); } PTR(lsst::daf::base::PropertySet) unpickleMetadata(std::string const& pick) { std::stringstream ss(pick); boost::archive::binary_iarchive ar(ss); PTR(lsst::daf::base::PropertySet) header = boost::make_shared(); ar >> *header; return header; } %} %pythoncode %{ def unpickleWcs(pick): header = unpickleMetadata(pick) return makeWcs(header) %} %extend lsst::afw::image::Wcs { %pythoncode %{ def __reduce__(self): self.getFitsMetadata() return (unpickleWcs, (pickleMetadata(self.getFitsMetadata()),),) %} } %newobject makeWcs; %useValueEquality(lsst::afw::image::Wcs); // ---------------------------------------------------------- // THIS CASE API IS DEPRECATED IN FAVOR OF %castShared %inline %{ lsst::afw::image::TanWcs::Ptr cast_TanWcs(lsst::afw::image::Wcs::Ptr wcs) { lsst::afw::image::TanWcs::Ptr tanWcs = boost::dynamic_pointer_cast(wcs); if(tanWcs.get() == NULL) {
    97 ffe52cae - throw(LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException, "Up cast failed"));
    ? ^^^^^^ ^
    100 21597d88 + throw(LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, "Up cast failed"));
    ? ^^ ^ } return tanWcs; } %} // ---------------------------------------------------------- %castShared(lsst::afw::image::TanWcs, lsst::afw::image::Wcs)
    108 a0b9d98c + %castShared(lsst::afw::image::DistortedTanWcs, lsst::afw::image::Wcs)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ffe52cae

    commit ffe52cae65bf288168469877735132eece5c6eca
    Author: Jim Bosch 
    Date:   Sat Feb 25 12:39:04 2012 -0500
    
        moved Wcs and TanWcs into their own swig .i file so we can %import them without %importing all of afw/imageLib
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    a0b9d98c

    commit a0b9d98c33134ce69b177a9b6b6260de9f2bccfd
    Author: Russell Owen 
    Date:   Thu Jan 22 17:41:16 2015 -0800
    
        Added DistortedTanWcs and a unit test.
        
        fixup! Added DistortedTanWcs and a preliminary unit test.
        
        Fixed some incorrect names in DistortedTanWcs and improved argument names accordingly.
        
        Ignore _build files
    

    Return to list

    src/detection/Peak.cc

    Diff:

                    // -*- lsst-c++ -*-
                    /*
                     * LSST Data Management System
                     * Copyright 2008-2014 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    #include 
                    
                    #include "lsst/afw/table/io/FitsWriter.h"
                    #include "lsst/afw/detection/Peak.h"
                    #include "lsst/afw/table/detail/Access.h"
                    
                    namespace lsst { namespace afw { namespace detection {
                    
                    //-----------------------------------------------------------------------------------------------------------
                    //----- Private PeakTable/Record classes ---------------------------------------------------------------
                    //-----------------------------------------------------------------------------------------------------------
                    
                    // These private derived classes are what you actually get when you do PeakTable::make; like the
                    // private classes in BaseTable.cc, it's more convenient to have an extra set of trivial derived
                    // classes than to do a lot of friending.
                    
                    namespace {
                    
                    class PeakTableImpl;
                    
                    class PeakRecordImpl : public PeakRecord {
                    public:
                    
                        explicit PeakRecordImpl(PTR(PeakTable) const & table) : PeakRecord(table) {}
                    
                    };
                    
                    class PeakTableImpl : public PeakTable {
                    public:
                    
                        explicit PeakTableImpl(afw::table::Schema const & schema, PTR(afw::table::IdFactory) const & idFactory) :
                            PeakTable(schema, idFactory)
                        {}
                    
                        PeakTableImpl(PeakTableImpl const & other) : PeakTable(other) {}
                    
                    private:
                    
                        virtual PTR(afw::table::BaseTable) _clone() const {
                            return boost::make_shared(*this);
                        }
                    
                        virtual PTR(afw::table::BaseRecord) _makeRecord() {
                            PTR(PeakRecord) record = boost::make_shared(getSelf());
                            if (getIdFactory()) record->setId((*getIdFactory())());
                            return record;
                        }
                    
                    };
                    
                    } // anonymous
                    
                    //-----------------------------------------------------------------------------------------------------------
                    //----- PeakFitsWriter ---------------------------------------------------------------------------------
                    //-----------------------------------------------------------------------------------------------------------
                    
                    // A custom FitsWriter for Peak - this just sets the AFW_TYPE key to PEAK, which should ensure
                    // we use PeakFitsReader to read it.
                    
                    namespace {
                    
                    class PeakFitsWriter : public afw::table::io::FitsWriter {
                    public:
                    
                        explicit PeakFitsWriter(Fits * fits, int flags) : afw::table::io::FitsWriter(fits, flags) {}
                    
                    protected:
                    
                        virtual void _writeTable(CONST_PTR(afw::table::BaseTable) const & table, std::size_t nRows);
                    
                    };
                    
                    void PeakFitsWriter::_writeTable(CONST_PTR(afw::table::BaseTable) const & t, std::size_t nRows) {
                        CONST_PTR(PeakTable) table = boost::dynamic_pointer_cast(t);
                        if (!table) {
                            throw LSST_EXCEPT(
    
    99 6ac35e07 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    99 44b7b576 + lsst::pex::exceptions::LogicError,
    "Cannot use a PeakFitsWriter on a non-Peak table." ); } afw::table::io::FitsWriter::_writeTable(table, nRows); _fits->writeKey("AFW_TYPE", "PEAK", "Tells lsst::afw to load this as a Peak table."); } } // anonymous //----------------------------------------------------------------------------------------------------------- //----- PeakFitsReader --------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------- // A custom FitsReader for PeakTable/Record - this gets registered with name SIMPLE, so it should get used // whenever we read a table with AFW_TYPE set to that value. namespace { class PeakFitsReader : public afw::table::io::FitsReader { public: explicit PeakFitsReader(Fits * fits, PTR(afw::table::io::InputArchive) archive, int flags) : afw::table::io::FitsReader(fits, archive, flags) {} protected: virtual PTR(afw::table::BaseTable) _readTable(); }; PTR(afw::table::BaseTable) PeakFitsReader::_readTable() { PTR(daf::base::PropertyList) metadata = boost::make_shared(); _fits->readMetadata(*metadata, true); afw::table::Schema schema(*metadata, true);
    134 6ac35e07 - PTR(PeakTable) table = PeakTable::make(schema, PTR(afw::table::IdFactory)());
    ? ^^^^ ------- --------------
    134 804ff0da + PTR(PeakTable) table = PeakTable::make(schema, false);
    ? ^ + _startRecords(*table); if (metadata->exists("AFW_TYPE")) metadata->remove("AFW_TYPE"); table->setMetadata(metadata); return table; } // registers the reader so FitsReader::make can use it. static afw::table::io::FitsReader::FactoryT referenceFitsReaderFactory("PEAK"); } // anonymous //----------------------------------------------------------------------------------------------------------- //----- PeakTable/Record member function implementations ----------------------------------------------- //----------------------------------------------------------------------------------------------------------- PeakRecord::PeakRecord(PTR(PeakTable) const & table) : BaseRecord(table) {} std::ostream & operator<<(std::ostream & os, PeakRecord const & record) { return os << (boost::format("%d: (%d,%d) (%.3f,%.3f)") % record.getId() % record.getIx() % record.getIy() % record.getFx() % record.getFy()); } PTR(PeakTable) PeakTable::make( afw::table::Schema const & schema, bool forceNewTable ) { typedef std::list< boost::weak_ptr > CachedTableList; static CachedTableList cache; if (!checkSchema(schema)) { throw LSST_EXCEPT(
    167 6ac35e07 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    167 44b7b576 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Schema for Peak must contain at least the keys defined by makeMinimalSchema()." ); } if (forceNewTable) { return boost::make_shared(schema, afw::table::IdFactory::makeSimple()); } CachedTableList::iterator iter = cache.begin(); while (iter != cache.end()) { PTR(PeakTable) p = iter->lock(); if (!p) { iter = cache.erase(iter); } else { if (p->getSchema().compare(schema, afw::table::Schema::IDENTICAL) == afw::table::Schema::IDENTICAL) { // Move the one we found to the front of the list, so it's easier to find // the same thing repeatedly if (iter != cache.begin()) { cache.splice(cache.begin(), cache, iter); } return p; } ++iter; } } // No match: we create a new table and put it in the cache PTR(PeakTable) newTable = boost::make_shared( schema, afw::table::IdFactory::makeSimple() ); cache.push_front(newTable); return newTable; } PeakTable::PeakTable(afw::table::Schema const & schema, PTR(afw::table::IdFactory) const & idFactory) : afw::table::BaseTable(schema), _idFactory(idFactory) {} PeakTable::PeakTable(PeakTable const & other) : afw::table::BaseTable(other), _idFactory(other._idFactory ? other._idFactory->clone() : other._idFactory) {} PeakTable::MinimalSchema::MinimalSchema() { id = schema.addField("id", "unique ID"); fx = schema.addField("f.x", "subpixel column position", "pixels"); fy = schema.addField("f.y", "subpixel row position", "pixels"); ix = schema.addField("i.x", "column position of highest pixel", "pixels"); iy = schema.addField("i.y", "row position of highest pixel", "pixels"); peakValue = schema.addField("peakValue", "value of [smoothed] image at peak position", "dn"); schema.getCitizen().markPersistent(); } PeakTable::MinimalSchema & PeakTable::getMinimalSchema() { static MinimalSchema it; return it; } PTR(afw::table::io::FitsWriter) PeakTable::makeFitsWriter(fits::Fits * fitsfile, int flags) const { return boost::make_shared(fitsfile, flags); } } // namespace detection namespace table { template class CatalogT; template class CatalogT; }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6ac35e07

    commit 6ac35e07a70a600e59ed290a1b8fb3173bdbf21d
    Author: Jim Bosch 
    Date:   Thu Nov 13 16:22:23 2014 -0500
    
        Replace Peak with PeakRecord
        
        By using afw::table objects to store Peaks, we allow additional
        information to be added to Peaks without requiring further changes
        to persistence.
    

    Commits in /Users/nate/repos_lsst/afw/

    44b7b576

    commit 44b7b576400aaf0a24c413114e047ccf3f34a29b
    Author: Lauren MacArthur 
    Date:   Thu Apr 2 17:39:06 2015 -0400
    
        Remove trailing Exception in exception names
    

    804ff0da

    commit 804ff0da0146053804743f6c040230bf278281fd
    Author: Jim Bosch 
    Date:   Tue Apr 14 17:15:46 2015 -0400
    
        Fix constructor args for PeakTable.
        
        The IdFactory being passed here was a copy/paste artifact that
        dates back to when PeakTable was created by copying
        SimpleTable.  It had gone unnoticed until now because
        shared_ptrs can evaluate to bool, but the behavior in C++11
        (with explicit conversions) is apparently a bit different.
    

    Return to list

    tests/heavyFootprint.py

    Diff:

    1 c6616c8e - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for HeavyFootprints Run with: heavyFootprint.py or python >>> import heavyFootprint; heavyFootprint.run() """ import numpy as np
    36 766d540b - import math, sys, os
    37 e3849974 + import os
    import unittest import lsst.utils.tests as tests import lsst.pex.logging as logging import lsst.afw.image as afwImage import lsst.afw.detection as afwDetect import lsst.afw.geom as afwGeom import lsst.afw.display.ds9 as ds9 try: type(verbose) except NameError: verbose = 0 logging.Debug("afwDetect.Footprint", verbose) try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class HeavyFootprintTestCase(tests.TestCase): """A test case for HeavyFootprint""" def setUp(self): self.mi = afwImage.MaskedImageF(20, 10) self.objectPixelVal = (10, 0x1, 100) self.foot = afwDetect.Footprint() for y, x0, x1 in [(2, 10, 13), (3, 11, 14)]: self.foot.addSpan(y, x0, x1) for x in range(x0, x1 + 1): self.mi.set(x, y, self.objectPixelVal) def tearDown(self): del self.foot del self.mi def testCreate(self): """Check that we can create a HeavyFootprint""" imi = self.mi.Factory(self.mi, True) # copy of input image hfoot = afwDetect.makeHeavyFootprint(self.foot, self.mi) self.assertNotEqual(hfoot.getId(), None) # check we can call a base-class method # # Check we didn't modify the input image # self.assertTrue(np.all(np.equal(self.mi.getImage().getArray(), imi.getImage().getArray()))) omi = self.mi.Factory(self.mi.getDimensions()) omi.set((1, 0x4, 0.1)) hfoot.insert(omi) if display: ds9.mtv(imi, frame=0, title="input") ds9.mtv(omi, frame=1, title="output") for s in self.foot.getSpans(): y = s.getY() for x in range(s.getX0(), s.getX1() + 1): self.assertEqual(imi.get(x, y), omi.get(x, y)) # Check that we can call getImageArray(), etc arr = hfoot.getImageArray() print arr # Check that it's iterable for x in arr: pass arr = hfoot.getMaskArray() print arr for x in arr: pass arr = hfoot.getVarianceArray() print arr # Check that it's iterable for x in arr: pass def testSetFootprint(self): """Check that we can create a HeavyFootprint and set the pixels under it""" ctrl = afwDetect.HeavyFootprintCtrl() ctrl.setModifySource(afwDetect.HeavyFootprintCtrl.SET) # clear the pixels in the Footprint ctrl.setMaskVal(self.objectPixelVal[1]) hfoot = afwDetect.makeHeavyFootprint(self.foot, self.mi, ctrl) # # Check that we cleared all the pixels # self.assertEqual(np.min(self.mi.getImage().getArray()), 0.0) self.assertEqual(np.max(self.mi.getImage().getArray()), 0.0) self.assertEqual(np.min(self.mi.getMask().getArray()), 0.0) self.assertEqual(np.max(self.mi.getMask().getArray()), 0.0) self.assertEqual(np.min(self.mi.getVariance().getArray()), 0.0) self.assertEqual(np.max(self.mi.getVariance().getArray()), 0.0) def testMakeHeavy(self): """Test that we can make a FootprintSet heavy""" fs = afwDetect.FootprintSet(self.mi, afwDetect.Threshold(1)) ctrl = afwDetect.HeavyFootprintCtrl(afwDetect.HeavyFootprintCtrl.NONE) fs.makeHeavy(self.mi, ctrl) if display: ds9.mtv(self.mi, frame=0, title="input") #ds9.mtv(omi, frame=1, title="output") omi = self.mi.Factory(self.mi.getDimensions()) for foot in fs.getFootprints(): self.assertNotEqual(afwDetect.cast_HeavyFootprint(foot, self.mi), None) afwDetect.cast_HeavyFootprint(foot, self.mi).insert(omi) for foot in fs.getFootprints(): self.assertNotEqual(afwDetect.HeavyFootprintF.cast(foot), None) afwDetect.HeavyFootprintF.cast(foot).insert(omi) self.assertTrue(np.all(np.equal(self.mi.getImage().getArray(), omi.getImage().getArray()))) def testXY0(self): """Test that inserting a HeavyFootprint obeys XY0""" fs = afwDetect.FootprintSet(self.mi, afwDetect.Threshold(1)) fs.makeHeavy(self.mi) bbox = afwGeom.BoxI(afwGeom.PointI(9, 1), afwGeom.ExtentI(7, 4)) omi = self.mi.Factory(self.mi, bbox, afwImage.LOCAL, True) omi.set((0, 0x0, 0)) for foot in fs.getFootprints(): afwDetect.cast_HeavyFootprint(foot, self.mi).insert(omi) if display: ds9.mtv(self.mi, frame=0, title="input") ds9.mtv(omi, frame=1, title="sub")
    177 0bbe11b7 - submi = self.mi.Factory(self.mi, bbox)
    178 eea3eb4a + submi = self.mi.Factory(self.mi, bbox, afwImage.LOCAL)
    ? ++++++++++++++++ self.assertTrue(np.all(np.equal(submi.getImage().getArray(), omi.getImage().getArray()))) def testCast_HeavyFootprint(self): """Test that we can cast a Footprint to a HeavyFootprint""" hfoot = afwDetect.makeHeavyFootprint(self.foot, self.mi) ctrl = afwDetect.HeavyFootprintCtrl(afwDetect.HeavyFootprintCtrl.NONE) hfoot = afwDetect.makeHeavyFootprint(self.foot, self.mi, ctrl) # # This isn't quite a full test, as hfoot is already a HeavyFootprint, # the complete test is in testMakeHeavy # self.assertNotEqual(afwDetect.cast_HeavyFootprint(hfoot, self.mi), None, "Cast to the right sort of HeavyFootprint") self.assertNotEqual(afwDetect.HeavyFootprintF.cast(hfoot), None, "Cast to the right sort of HeavyFootprint") self.assertEqual(afwDetect.cast_HeavyFootprint(self.foot, self.mi), None, "Can't cast a Footprint to a HeavyFootprint") self.assertEqual(afwDetect.HeavyFootprintI.cast(hfoot), None, "Cast to the wrong sort of HeavyFootprint") def testMergeHeavyFootprints(self): mi = afwImage.MaskedImageF(20, 10) objectPixelVal = (42, 0x9, 400) foot = afwDetect.Footprint() for y, x0, x1 in [(1, 9, 12), (2, 12, 13), (3, 11, 15)]: foot.addSpan(y, x0, x1) for x in range(x0, x1 + 1): mi.set(x, y, objectPixelVal) hfoot1 = afwDetect.makeHeavyFootprint(self.foot, self.mi) hfoot2 = afwDetect.makeHeavyFootprint(foot, mi) hfoot1.normalize() hfoot2.normalize() hsum = afwDetect.mergeHeavyFootprintsF(hfoot1, hfoot2) bb = hsum.getBBox() self.assertEquals(bb.getMinX(), 9) self.assertEquals(bb.getMaxX(), 15) self.assertEquals(bb.getMinY(), 1) self.assertEquals(bb.getMaxY(), 3) msum = afwImage.MaskedImageF(20,10) hsum.insert(msum) sa = msum.getImage().getArray() self.assertTrue(np.all(sa[1, 9:13] == objectPixelVal[0])) self.assertTrue(np.all(sa[2, 12:14] == objectPixelVal[0] + self.objectPixelVal[0])) self.assertTrue(np.all(sa[2, 10:12] == self.objectPixelVal[0])) sv = msum.getVariance().getArray() self.assertTrue(np.all(sv[1, 9:13] == objectPixelVal[2])) self.assertTrue(np.all(sv[2, 12:14] == objectPixelVal[2] + self.objectPixelVal[2])) self.assertTrue(np.all(sv[2, 10:12] == self.objectPixelVal[2])) sm = msum.getMask().getArray() self.assertTrue(np.all(sm[1, 9:13] == objectPixelVal[1])) self.assertTrue(np.all(sm[2, 12:14] == objectPixelVal[1] | self.objectPixelVal[1])) self.assertTrue(np.all(sm[2, 10:12] == self.objectPixelVal[1])) if False: import matplotlib matplotlib.use('Agg') import pylab as plt im1 = afwImage.ImageF(bb) hfoot1.insert(im1) im2 = afwImage.ImageF(bb) hfoot2.insert(im2) im3 = afwImage.ImageF(bb) hsum.insert(im3) plt.clf() plt.subplot(1,3,1) plt.imshow(im1.getArray(), interpolation='nearest', origin='lower') plt.subplot(1,3,2) plt.imshow(im2.getArray(), interpolation='nearest', origin='lower') plt.subplot(1,3,3) plt.imshow(im3.getArray(), interpolation='nearest', origin='lower') plt.savefig('merge.png') def testFitsPersistence(self): heavy1 = afwDetect.HeavyFootprintF(self.foot) heavy1.getImageArray()[:] = np.random.randn(self.foot.getArea()).astype(np.float32) heavy1.getMaskArray()[:] = np.random.randint(low=0, high=2, size=self.foot.getArea()).astype(np.uint16) heavy1.getVarianceArray()[:] = np.random.randn(self.foot.getArea()).astype(np.float32) filename = "heavyFootprint-testFitsPersistence.fits" heavy1.writeFits(filename) heavy2 = afwDetect.HeavyFootprintF.readFits(filename) self.assertEqual(heavy1.getArea(), heavy2.getArea()) self.assertEqual(list(heavy1.getSpans()), list(heavy2.getSpans())) self.assertEqual(list(heavy1.getPeaks()), list(heavy2.getPeaks())) self.assertClose(heavy1.getImageArray(), heavy2.getImageArray(), rtol=0.0, atol=0.0) self.assertClose(heavy1.getMaskArray(), heavy2.getMaskArray(), rtol=0.0, atol=0.0) self.assertClose(heavy1.getVarianceArray(), heavy2.getVarianceArray(), rtol=0.0, atol=0.0) os.remove(filename) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" tests.init() suites = [] suites += unittest.makeSuite(HeavyFootprintTestCase) suites += unittest.makeSuite(tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    766d540b

    commit 766d540b5aa4fe04bc1542be4d592aec27ee7391
    Author: Jim Bosch 
    Date:   Thu Nov 20 15:20:42 2014 -0500
    
        Add afw::table::io persistence for HeavyFootprint
    

    0bbe11b7

    commit 0bbe11b79145e2542690a41797d663eb41b381b5
    Author: Robert Lupton the Good 
    Date:   Mon Nov 28 15:37:46 2011 -0500
    
        Added test that HeavyFootprints work with subregions
    

    c6616c8e

    commit c6616c8e605e914880d7c1791c3990dabc4f1a6c
    Author: Robert Lupton the Good 
    Date:   Wed Nov 23 17:11:35 2011 -0500
    
        Initial dummy implementation of HeavyFootprint; successfully swigged
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    eea3eb4a

    commit eea3eb4aaa72e0956cce3c5a4bb2c78863540dd3
    Author: Russell Owen 
    Date:   Thu Sep 18 17:23:09 2014 -0700
    
        Respond to review by restoring LOCAL where appropriate.
        Also enhanced documentation in detection.py
    

    e3849974

    commit e384997433cea6e8446bd92f8e5d7cb0db8d95fc
    Author: Jim Bosch 
    Date:   Thu Nov 20 15:20:42 2014 -0500
    
        Add afw::table::io persistence for HeavyFootprint
        
        Conflicts:
            tests/heavyFootprint.py
    

    Return to list

    tests/spatialCell.py

    Diff:

    1 59e9ecb4 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for SpatialCell Run with: python SpatialCell.py or python >>> import SpatialCell; SpatialCell.run() """ import unittest import lsst.utils.tests as utilsTests import lsst.pex.exceptions as pexExcept
    40 20c2c467 - import lsst.afw.image as afwImage
    import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom import testLib def getFlux(x): return 1000 - 10*x #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class SpatialCellTestCase(unittest.TestCase): """A test case for SpatialCell""" def setUp(self): candidateList = afwMath.SpatialCellCandidateList() self.nCandidate = 5 for i in (0, 1, 4, 3, 2): # must be all numbers in range(self.nCandidate) x, y = i, 5*i candidateList.append(testLib.TestCandidate(x, y, getFlux(x))) self.cell = afwMath.SpatialCell("Test", afwGeom.Box2I(), candidateList) self.assertEqual(self.cell.getLabel(), "Test") def tearDown(self): del self.cell def testCandidateList(self): """Check that we can retrieve candidates, and that they are sorted by ranking""" self.assertEqual(self.cell[0].getXCenter(), 0) self.assertEqual(self.cell[1].getXCenter(), 1) self.assertEqual(self.cell[1].getYCenter(), 5) def testBuildCandidateListByInsertion(self): """Build a candidate list by inserting candidates""" self.cell = afwMath.SpatialCell("Test", afwGeom.Box2I()) for x, y in ([5, 0], [1, 1], [2, 2], [0, 0], [4, 4], [3, 4]): self.cell.insertCandidate(testLib.TestCandidate(x, y, getFlux(x))) self.assertEqual(self.cell[0].getXCenter(), 0) def testIterators(self): """Test the SpatialCell iterators""" # # Count the candidates # self.assertEqual(self.cell.size(), self.nCandidate) self.assertEqual(self.cell.end() - self.cell.begin(), self.nCandidate) ptr = self.cell.begin() ptr.__incr__() self.assertEqual(self.cell.end() - ptr, self.nCandidate - 1) self.assertEqual(ptr - self.cell.begin(), 1) # # Now label one candidate as bad # self.cell[2].setStatus(afwMath.SpatialCellCandidate.BAD) self.assertEqual(self.cell.size(), self.nCandidate - 1) self.assertEqual(self.cell.end() - self.cell.begin(), self.nCandidate - 1) self.cell.setIgnoreBad(False) self.assertEqual(self.cell.size(), self.nCandidate) self.assertEqual(self.cell.end() - self.cell.begin(), self.nCandidate) def testGetCandidateById(self): """Check that we can lookup candidates by ID""" id = self.cell[1].getId() self.assertEqual(self.cell.getCandidateById(id).getId(), id) def tst(): self.cell.getCandidateById(-1) # non-existent ID self.assertEqual(self.cell.getCandidateById(-1, True), None)
    118 0a476497 - utilsTests.assertRaisesLsstCpp(self, pexExcept.NotFoundException, tst)
    118 6fc1c3d1 + self.assertRaises(pexExcept.NotFoundError, tst)
    def testSetIteratorBad(self): """Setting a candidate BAD shouldn't stop us seeing the rest of the candidates""" i = 0 for cand in self.cell: if i == 1: cand.setStatus(afwMath.SpatialCellCandidate.BAD) i += 1 self.assertEqual(i, self.nCandidate) def testSortCandidates(self): """Check that we can update ratings and maintain order""" ratings0 = [cand.getCandidateRating() for cand in self.cell] # # Change a rating # i, flux = 1, 9999 self.cell[i].setCandidateRating(flux) ratings0[i] = flux self.assertEqual(ratings0, [cand.getCandidateRating() for cand in self.cell]) self.cell.sortCandidates() self.assertNotEqual(ratings0, [cand.getCandidateRating() for cand in self.cell]) self.assertEqual(sorted(ratings0, lambda a, b: int(b - a)), [cand.getCandidateRating() for cand in self.cell]) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class SpatialCellSetTestCase(unittest.TestCase): """A test case for SpatialCellSet""" def setUp(self): self.cellSet = afwMath.SpatialCellSet(afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(501, 501)), 260, 200) def makeTestCandidateCellSet(self): """Populate a SpatialCellSet""" if False: # Print the bboxes for the cells print for i in range(len(self.cellSet.getCellList())): cell = self.cellSet.getCellList()[i] print i, "%3d,%3d -- %3d,%3d" % (cell.getBBox().getMinX(), cell.getBBox().getMinY(), cell.getBBox().getMaxX(), cell.getBBox().getMaxY()), \ cell.getLabel() self.assertEqual(len(self.cellSet.getCellList()), 6) self.NTestCandidates = 0 # number of candidates for x, y in ([5, 0], [1, 1], [2, 2], [0, 0], [4, 4], [3, 4]): # all in cell0 self.cellSet.insertCandidate(testLib.TestCandidate(x, y, -x)) self.NTestCandidates += 1 self.cellSet.insertCandidate(testLib.TestCandidate(305, 0, 100)) # in cell1 self.NTestCandidates += 1 self.cellSet.insertCandidate(testLib.TestCandidate(500, 500, 100)) # the top right corner of cell5 self.NTestCandidates += 1 def tearDown(self): del self.cellSet def testNoCells(self): """Test that we check for a request to make a SpatialCellSet with no cells""" def tst(): afwMath.SpatialCellSet(afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(500, 500)), 0, 3)
    185 6fc337ad - utilsTests.assertRaisesLsstCpp(self, pexExcept.LengthErrorException, tst)
    ? ^^^ ^^^^^^ ------- ------ ---------
    185 6fc1c3d1 + self.assertRaises(pexExcept.LengthError, tst)
    ? ^^ ^ def testInsertCandidate(self): """Insert candidates into the SpatialCellSet""" self.makeTestCandidateCellSet() def tst(): self.cellSet.insertCandidate(testLib.TestCandidate(501, 501, 100)) # Doesn't fit
    194 4023160c - utilsTests.assertRaisesLsstCpp(self, pexExcept.OutOfRangeException, tst)
    194 6fc1c3d1 + self.assertRaises(pexExcept.OutOfRangeError, tst)
    # # OK, the SpatialCellList is populated # cell0 = self.cellSet.getCellList()[0] self.assertFalse(cell0.empty()) self.assertEqual(cell0[0].getXCenter(), 0.0) self.assertEqual(self.cellSet.getCellList()[1][0].getXCenter(), 305.0) self.assertTrue(self.cellSet.getCellList()[2].empty()) def tst1(): self.cellSet.getCellList()[2][0] self.assertRaises(IndexError, tst1) def tst2(): self.cellSet.getCellList()[2].begin().__deref__()
    212 a7aa0c91 - utilsTests.assertRaisesLsstCpp(self, pexExcept.NotFoundException, tst2)
    212 6fc1c3d1 + self.assertRaises(pexExcept.NotFoundError, tst2)
    self.assertFalse(self.cellSet.getCellList()[5].empty()) def testVisitor(self): """Test the candidate visitors""" self.makeTestCandidateCellSet() visitor = testLib.TestCandidateVisitor() self.cellSet.visitCandidates(visitor) self.assertEqual(visitor.getN(), self.NTestCandidates) self.cellSet.visitCandidates(visitor, 1) self.assertEqual(visitor.getN(), 3) def testGetCandidateById(self): """Check that we can lookup candidates by ID""" self.makeTestCandidateCellSet() # # OK, the SpatialCellList is populated # id = self.cellSet.getCellList()[0][1].getId() self.assertEqual(self.cellSet.getCandidateById(id).getId(), id) def tst(): self.cellSet.getCandidateById(-1) # non-existent ID self.assertEqual(self.cellSet.getCandidateById(-1, True), None)
    243 0a476497 - utilsTests.assertRaisesLsstCpp(self, pexExcept.NotFoundException, tst)
    243 6fc1c3d1 + self.assertRaises(pexExcept.NotFoundError, tst)
    def testSpatialCell(self): dx, dy, sx, sy = 100, 100, 50, 50 for x0, y0 in [(0, 0), (100, 100)]: # only works for tests where dx,dx is some multiple of sx,sy assert(dx//sx == float(dx)/float(sx)) assert(dy//sy == float(dy)/float(sy)) bbox = afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Extent2I(dx, dy)) cset = afwMath.SpatialCellSet(bbox, sx, sy) for cell in cset.getCellList(): label = cell.getLabel() nx, ny = [int(z) for z in label.split()[1].split('x')] cbbox = cell.getBBox() self.assertEqual(cbbox.getMinX(), nx*sx + x0) self.assertEqual(cbbox.getMinY(), ny*sy + y0) self.assertEqual(cbbox.getMaxX(), (nx+1)*sx + x0 - 1) self.assertEqual(cbbox.getMaxY(), (ny+1)*sy + y0 - 1) def testSortCandidates(self): """Check that we can update ratings and maintain order""" self.makeTestCandidateCellSet() cell1 = self.cellSet.getCellList()[0] self.assertFalse(cell1.empty()) ratings0 = [cand.getCandidateRating() for cand in cell1] # # Change a rating # i, flux = 1, 9999 cell1[i].setCandidateRating(flux) ratings0[i] = flux self.assertEqual(ratings0, [cand.getCandidateRating() for cand in cell1]) self.cellSet.sortCandidates() self.assertNotEqual(ratings0, [cand.getCandidateRating() for cand in cell1]) self.assertEqual(sorted(ratings0, lambda a, b: int(b - a)), [cand.getCandidateRating() for cand in cell1]) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class TestMaskedImageCandidateCase(unittest.TestCase): """A test case for TestMaskedImageCandidate""" def setUp(self): self.cellSet = afwMath.SpatialCellSet(afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(501, 501)), 2, 3) def tearDown(self): del self.cellSet def testInsertCandidate(self): """Test that we can use SpatialCellMaskedImageCandidate""" flux = 10 self.cellSet.insertCandidate(testLib.TestMaskedImageCandidate(0, 0, flux)) cand = self.cellSet.getCellList()[0][0] # # Swig doesn't know that we're a SpatialCellMaskedImageCandidate; all it knows is that we have # a SpatialCellCandidate, and SpatialCellCandidates don't know about getMaskedImage; so cast the # pointer to SpatialCellMaskedImageCandidate > and all will be well; # cand = afwMath.SpatialCellMaskedImageCandidateF.cast(cand) width, height = 15, 21 cand.setWidth(width) cand.setHeight(height) im = cand.getMaskedImage().getImage() self.assertEqual(im.get(0, 0), flux) # This is how TestMaskedImageCandidate sets its pixels self.assertEqual(im.getWidth(), width) self.assertEqual(im.getHeight(), height) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(SpatialCellTestCase) suites += unittest.makeSuite(SpatialCellSetTestCase) suites += unittest.makeSuite(TestMaskedImageCandidateCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0a476497

    commit 0a476497955b44e2cf971712345df0d09f57dc08
    Author: rhl 
    Date:   Fri Oct 23 19:49:18 2009 +0000
    
        Add getCandidateById; #993
    

    20c2c467

    commit 20c2c46776ad69164993f9837f347800a80f245b
    Author: jbosch 
    Date:   Fri Mar 4 01:19:01 2011 +0000
    
        afw #1556 - fixed all python unit tests with trivial syntax-related failures, plus a few others
    

    6fc337ad

    commit 6fc337adb1018165c9ff6f94042335462f891015
    Author: rhl 
    Date:   Sun Mar 8 06:20:31 2009 +0000
    
        Implemented a visitor for the Candidates in SpatialCells
    

    59e9ecb4

    commit 59e9ecb4b8031ccae9126e37dcb10accea5ab200
    Author: rhl 
    Date:   Sun Mar 1 16:13:13 2009 +0000
    
        Initial implementation of SpatialCell
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    4023160c

    commit 4023160c92a3f2e7a1520562110db2b78fe0ada3
    Author: rhl 
    Date:   Sun Mar 1 19:11:37 2009 +0000
    
        Implemented SpatialCellList
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    python/lsst/afw/math/warper.py

    Diff:

                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
    
    22 93d69929 - import sys
    import lsst.pex.config as pexConfig
    24 93d69929 - import lsst.pex.logging as pexLog
    import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.gpu as afwGpu import mathLib __all__ = ["Warper", "WarperConfig"] def computeWarpedBBox(destWcs, srcBBox, srcWcs): """Compute the bounding box of a warped image The bounding box includes all warped pixels and it may be a bit oversize. @param destWcs: WCS of warped exposure @param srcBBox: parent bounding box of unwarped image @param srcWcs: WCS of unwarped image @return destBBox: bounding box of warped exposure """ srcPosBox = afwGeom.Box2D(srcBBox) destPosBox = afwGeom.Box2D() for inX in (srcPosBox.getMinX(), srcPosBox.getMaxX()): for inY in (srcPosBox.getMinY(), srcPosBox.getMaxY()): destPos = destWcs.skyToPixel(srcWcs.pixelToSky(afwGeom.Point2D(inX, inY))) destPosBox.include(destPos) destBBox = afwGeom.Box2I(destPosBox, afwGeom.Box2I.EXPAND) return destBBox _DefaultInterpLength = 10 _DefaultCacheSize = 0 class WarperConfig(pexConfig.Config): warpingKernelName = pexConfig.ChoiceField( dtype = str, doc = "Warping kernel", default = "lanczos4", allowed = { "bilinear": "bilinear interpolation", "lanczos3": "Lanczos kernel of order 3", "lanczos4": "Lanczos kernel of order 4", "lanczos5": "Lanczos kernel of order 5", } ) maskWarpingKernelName = pexConfig.ChoiceField( dtype = str, doc = "Warping kernel for mask (use warpingKernelName if '')", default = "bilinear", allowed = { "": "use the regular warping kernel for the mask plane, as well as the image and variance planes", "bilinear": "bilinear interpolation", "lanczos3": "Lanczos kernel of order 3", "lanczos4": "Lanczos kernel of order 4", "lanczos5": "Lanczos kernel of order 5", } ) interpLength = pexConfig.Field( dtype = int, doc = "interpLength argument to lsst.afw.math.warpExposure", default = _DefaultInterpLength, ) cacheSize = pexConfig.Field( dtype = int, doc = "cacheSize argument to lsst.afw.math.SeparableKernel.computeCache", default = _DefaultCacheSize, ) devicePreference = pexConfig.Field( dtype = int, doc = "use GPU acceleration?", default = afwGpu.DEFAULT_DEVICE_PREFERENCE, ) growFullMask = pexConfig.Field( dtype = int, doc = "mask bits to grow to full width of image/variance kernel,", default = afwImage.MaskU.getPlaneBitMask("EDGE"), ) class Warper(object): """Warp images """ ConfigClass = WarperConfig def __init__(self, warpingKernelName, interpLength = _DefaultInterpLength, cacheSize = _DefaultCacheSize, maskWarpingKernelName = "", devicePreference = afwGpu.DEFAULT_DEVICE_PREFERENCE, growFullMask = afwImage.MaskU.getPlaneBitMask("EDGE"), ): """Create a Warper Inputs: - warpingKernelName: argument to lsst.afw.math.makeWarpingKernel - interpLength: interpLength argument to lsst.afw.warpExposure - cacheSize: size of computeCache - maskWarpingKernelName: name of mask warping kernel (if "" then use warpingKernelName); an argument to lsst.afw.math.makeWarpingKernel """ self._warpingControl = mathLib.WarpingControl( warpingKernelName, maskWarpingKernelName, cacheSize, interpLength, devicePreference, growFullMask) @classmethod def fromConfig(cls, config): """Create a Warper from a config @param config: an instance of Warper.ConfigClass """ return cls( warpingKernelName = config.warpingKernelName, maskWarpingKernelName = config.maskWarpingKernelName, interpLength = config.interpLength, cacheSize = config.cacheSize, devicePreference = config.devicePreference, growFullMask = config.growFullMask, ) def getWarpingKernel(self): """Get the warping kernel""" return self._warpingControl.getWarpingKernel() def getMaskWarpingKernel(self): """Get the mask warping kernel""" return self._warpingControl.getMaskWarpingKernel() def warpExposure(self, destWcs, srcExposure, border=0, maxBBox=None, destBBox=None): """Warp an exposure @param destWcs: WCS of warped exposure @param srcExposure: exposure to warp @param border: grow bbox of warped exposure by this amount in all directions (int pixels); if negative then the bbox is shrunk; border is applied before maxBBox; ignored if destBBox is not None @param maxBBox: maximum allowed parent bbox of warped exposure (an afwGeom.Box2I or None); if None then the warped exposure will be just big enough to contain all warped pixels; if provided then the warped exposure may be smaller, and so missing some warped pixels; ignored if destBBox is not None @param destBBox: exact parent bbox of warped exposure (an afwGeom.Box2I or None); if None then border and maxBBox are used to determine the bbox, otherwise border and maxBBox are ignored @return destExposure: warped exposure (of same type as srcExposure) @note: calls mathLib.warpExposure insted of self.warpImage because the former copies attributes such as Calib, and that should be done in one place """ destBBox = self._computeDestBBox( destWcs = destWcs, srcImage = srcExposure.getMaskedImage(), srcWcs = srcExposure.getWcs(), border = border, maxBBox = maxBBox, destBBox = destBBox, ) destExposure = srcExposure.Factory(destBBox, destWcs) mathLib.warpExposure(destExposure, srcExposure, self._warpingControl) return destExposure def warpImage(self, destWcs, srcImage, srcWcs, border=0, maxBBox=None, destBBox=None): """Warp an image or masked image @param destWcs: WCS of warped image @param srcImage: image or masked image to warp @param srcWcs: WCS of image @param border: grow bbox of warped image by this amount in all directions (int pixels); if negative then the bbox is shrunk; border is applied before maxBBox; ignored if destBBox is not None @param maxBBox: maximum allowed parent bbox of warped image (an afwGeom.Box2I or None); if None then the warped image will be just big enough to contain all warped pixels; if provided then the warped image may be smaller, and so missing some warped pixels; ignored if destBBox is not None @param destBBox: exact parent bbox of warped image (an afwGeom.Box2I or None); if None then border and maxBBox are used to determine the bbox, otherwise border and maxBBox are ignored @return destImage: warped image or masked image (of same type as srcImage) """ destBBox = self._computeDestBBox( destWcs = destWcs, srcImage = srcImage, srcWcs = srcWcs, border = border, maxBBox = maxBBox, destBBox = destBBox, ) destImage = srcImage.Factory(destBBox) mathLib.warpImage(destImage, destWcs, srcImage, srcWcs, self._warpingControl) return destImage def _computeDestBBox(self, destWcs, srcImage, srcWcs, border, maxBBox, destBBox): """Process destBBox argument for warpImage and warpExposure @param destWcs: WCS of warped image @param srcImage: image or masked image to warp @param srcWcs: WCS of image @param border: grow bbox of warped image by this amount in all directions (int pixels); if negative then the bbox is shrunk; border is applied before maxBBox; ignored if destBBox is not None @param maxBBox: maximum allowed parent bbox of warped image (an afwGeom.Box2I or None); if None then the warped image will be just big enough to contain all warped pixels; if provided then the warped image may be smaller, and so missing some warped pixels; ignored if destBBox is not None @param destBBox: exact parent bbox of warped image (an afwGeom.Box2I or None); if None then border and maxBBox are used to determine the bbox, otherwise border and maxBBox are ignored """ if destBBox is None: # warning: == None fails due to Box2I.__eq__ destBBox = computeWarpedBBox(destWcs, srcImage.getBBox(afwImage.PARENT), srcWcs) if border: destBBox.grow(border) if maxBBox is not None: destBBox.clip(maxBBox) return destBBox

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    93d69929

    commit 93d69929172539e2c698b13759a6c6fdaa33b56b
    Author: rowen 
    Date:   Tue Mar 15 21:04:17 2011 +0000
    
        Move coadd_utils Warp here as afwMath.Warper
    

    Commits in /Users/nate/repos_lsst/afw/

    Return to list

    python/lsst/afw/cameraGeom/utils.py

    Diff:

                    #!/usr/bin/env python
                    
                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    
                    """
                    Support for cameraGeom
                    """
    
    28 61a76714 -
    28 8b4a97d8 + from __future__ import division
    import math
    30 61a76714 - import os
    31 61a76714 - import sys
    32 61a76714 - import unittest
    33 08da793e - import numpy as np
    ? ------
    30 c856a32c + import numpy
    31 9372e552 + import itertools
    34 b3296b1d - try:
    35 b3296b1d - import pyfits
    36 b3296b1d - except ImportError:
    37 b3296b1d - pyfits = None
    39 8933e1bd - import lsst.daf.persistence as dafPersist
    40 993791af - import lsst.pex.policy as pexPolicy
    import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.math as afwMath
    44 61a76714 - import lsst.afw.cameraGeom as cameraGeom
    36 c856a32c + import lsst.daf.base as dafBase
    38 1ff73d16 + from .rotateBBoxBy90 import rotateBBoxBy90
    39 1ff73d16 + from .assembleImage import assembleAmplifierImage, assembleAmplifierRawImage
    40 b4f73cbf + from .cameraGeomLib import PUPIL, FOCAL_PLANE
    41 61a76714 +
    46 61a76714 - import lsst.afw.display.ds9 as ds9
    ? ---- ^ ^
    42 bde0ab27 + import lsst.afw.display as afwDisplay
    ? ^^^^^ ^^^^ import lsst.afw.display.utils as displayUtils
    44 d21f3141 +
    try: type(display) except NameError: display = False
    52 97dea9da - force = False
    54 61a76714 - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    50 297a2be9 + def prepareWcsData(wcs, amp, isTrimmed=True):
    51 545f4dc9 + """!Put Wcs from an Amp image into CCD coordinates
    56 61a76714 - class GetCcdImage(object):
    57 61a76714 - """A class to return an Image of a given Ccd"""
    53 545f4dc9 + @param[in, out] wcs WCS object to modify in place
    54 545f4dc9 + @param[in] amp Amp object to use
    55 545f4dc9 + @param[in] isTrimmed Is the image to which the WCS refers trimmed of non-imaging pixels?
    56 b6ce1d15 + """
    57 b6ce1d15 + if not amp.getHasRawInfo():
    58 b6ce1d15 + raise RuntimeError("Cannot modify wcs without raw amp information")
    59 9d2d359a + if isTrimmed:
    60 9d2d359a + ampBox = amp.getRawDataBBox()
    61 9d2d359a + else:
    62 9d2d359a + ampBox = amp.getRawBBox()
    63 297a2be9 + wcs.flipImage(amp.getRawFlipX(), amp.getRawFlipY(), ampBox.getDimensions())
    64 297a2be9 + #Shift WCS for trimming
    65 297a2be9 + wcs.shiftReferencePixel(-ampBox.getMinX(), -ampBox.getMinY())
    66 297a2be9 + #Account for shift of amp data in larger ccd matrix
    67 b6ce1d15 + offset = amp.getRawXYOffset()
    68 f8333aa0 + wcs.shiftReferencePixel(offset.getX(), offset.getY())
    70 545f4dc9 + def plotFocalPlane(camera, pupilSizeDeg_x, pupilSizeDeg_y, dx=0.1, dy=0.1, figsize=(10., 10.),
    71 545f4dc9 + showFig=True, savePath=None):
    72 545f4dc9 + """!Make a plot of the focal plane along with a set points that sample the Pupil
    59 97dea9da - def __init__(self, imageFile=None):
    60 61a76714 - self.imageFile = imageFile
    61 993791af - self.isTrimmed = False
    62 97dea9da - self.isRaw = True
    64 1f7e505a - def getImage(self, ccd, amp=None, imageFactory=afwImage.ImageU):
    65 61a76714 - """Return the image of the chip with cameraGeom.Id == id; if provided only read the given BBox"""
    74 545f4dc9 + @param[in] camera a camera object
    75 545f4dc9 + @param[in] pupilSizeDeg_x Amount of the pupil to sample in x in degrees
    76 545f4dc9 + @param[in] pupilSizeDeg_y Amount of the pupil to sample in y in degrees
    77 545f4dc9 + @param[in] dx Spacing of sample points in x in degrees
    78 545f4dc9 + @param[in] dy Spacing of sample points in y in degrees
    79 545f4dc9 + @param[in] figsize matplotlib style tuple indicating the size of the figure in inches
    80 545f4dc9 + @param[in] showFig Display the figure on the screen?
    81 545f4dc9 + @param[in] savePath If not None, save a copy of the figure to this name
    82 d21f3141 + """
    83 c856a32c + try:
    84 c856a32c + from matplotlib.patches import Polygon
    85 c856a32c + from matplotlib.collections import PatchCollection
    86 c856a32c + import matplotlib.pyplot as plt
    87 c856a32c + except ImportError:
    88 c856a32c + raise ImportError("Can't run plotFocalPlane: matplotlib has not been set up")
    89 d21f3141 + pupil_gridx, pupil_gridy = numpy.meshgrid(numpy.arange(0., pupilSizeDeg_x+dx, dx) - pupilSizeDeg_x/2.,
    90 d21f3141 + numpy.arange(0., pupilSizeDeg_y+dy, dy) - pupilSizeDeg_y/2.)
    91 d21f3141 + xs = []
    92 d21f3141 + ys = []
    93 d21f3141 + pcolors = []
    94 d21f3141 + for pos in zip(pupil_gridx.flatten(), pupil_gridy.flatten()):
    95 d21f3141 + posRad = afwGeom.Point2D(math.radians(pos[0]), math.radians(pos[1]))
    96 d21f3141 + cp = camera.makeCameraPoint(posRad, PUPIL)
    97 d21f3141 + ncp = camera.transform(cp, FOCAL_PLANE)
    98 d21f3141 + xs.append(ncp.getPoint().getX())
    99 d21f3141 + ys.append(ncp.getPoint().getY())
    100 d21f3141 + dets = camera.findDetectors(cp)
    101 d21f3141 + if len(dets) > 0:
    102 d21f3141 + pcolors.append('w')
    103 d21f3141 + else:
    104 d21f3141 + pcolors.append('k')
    67 82325a24 - return self.getImageFromFilename(self.imageFile, ccd, amp, imageFactory=imageFactory)
    107 d21f3141 + colorMap = {0:'b', 1:'y', 2:'g', 3:'r'}
    69 1f7e505a - def getImageFromFilename(self, fileName, ccd, amp=None, hdu=0, imageFactory=afwImage.ImageU,
    70 1f7e505a - oneAmpPerFile=False):
    71 82325a24 - """Return the image of the chip with cameraGeom.Id == id; if provided only read the given BBox"""
    73 993791af - if amp:
    74 993791af - if self.isTrimmed:
    75 3b1e6cc7 - bbox = amp.getElectronicDataSec()
    109 d21f3141 + patches = []
    110 d21f3141 + colors = []
    111 1ff73d16 + plt.figure(figsize=figsize)
    112 d21f3141 + ax = plt.gca()
    113 d21f3141 + xvals = []
    114 d21f3141 + yvals = []
    115 d21f3141 + for det in camera:
    116 d21f3141 + corners = [(c.getX(), c.getY()) for c in det.getCorners(FOCAL_PLANE)]
    117 d21f3141 + for corner in corners:
    118 d21f3141 + xvals.append(corner[0])
    119 d21f3141 + yvals.append(corner[1])
    120 d21f3141 + colors.append(colorMap[det.getType()])
    121 d21f3141 + patches.append(Polygon(corners, True))
    122 d21f3141 + center = det.getOrientation().getFpPosition()
    123 20d15f9f + ax.text(center.getX(), center.getY(), det.getName(), horizontalalignment='center', size=6)
    124 d21f3141 +
    125 c856a32c + patchCollection = PatchCollection(patches, alpha=0.6, facecolor=colors)
    126 c856a32c + ax.add_collection(patchCollection)
    127 d21f3141 + ax.scatter(xs, ys, s=10, alpha=.7, linewidths=0., c=pcolors)
    128 d21f3141 + ax.set_xlim(min(xvals) - abs(0.1*min(xvals)), max(xvals) + abs(0.1*max(xvals)))
    129 d21f3141 + ax.set_ylim(min(yvals) - abs(0.1*min(yvals)), max(yvals) + abs(0.1*max(yvals)))
    130 d21f3141 + ax.set_xlabel('Focal Plane X (mm)')
    131 d21f3141 + ax.set_ylabel('Focal Plane Y (mm)')
    132 d21f3141 + if savePath is not None:
    133 d21f3141 + plt.savefig(savePath)
    134 d21f3141 + if showFig:
    135 d21f3141 + plt.show()
    136 d21f3141 +
    137 e0fa1c0b + def makeImageFromAmp(amp, imValue=None, imageFactory=afwImage.ImageU, markSize=10, markValue=0,
    138 e0fa1c0b + scaleGain = lambda gain: (gain*1000)//10):
    139 545f4dc9 + """!Make an image from an amp object
    140 545f4dc9 +
    141 545f4dc9 + Since images are integer images by default, the gain needs to be scaled to give enough dynamic range
    142 545f4dc9 + to see variation from amp to amp. The scaling algorithm is assignable.
    143 545f4dc9 +
    144 545f4dc9 + @param[in] amp Amp record to use for constructing the raw amp image
    145 545f4dc9 + @param[in] imValue Value to assign to the constructed image scaleGain(gain) is used if not set
    146 545f4dc9 + @param[in] imageFactory Type of image to construct
    147 545f4dc9 + @param[in] markSize Size of mark at read corner in pixels
    148 545f4dc9 + @param[in] markValue Value of pixels in the read corner mark
    149 545f4dc9 + @param[in] scaleGain The function by which to scale the gain
    150 f6e303b1 + @return an untrimmed amp image
    151 f6e303b1 + """
    152 9372e552 + if not amp.getHasRawInfo():
    153 5261ebd8 + raise RuntimeError("Can't create a raw amp image without raw amp information")
    154 9372e552 + bbox = amp.getRawBBox()
    155 9372e552 + dbbox = amp.getRawDataBBox()
    156 9372e552 + img = imageFactory(bbox)
    157 9372e552 + if imValue is None:
    158 e0fa1c0b + img.set(scaleGain(amp.getGain()))
    159 61a76714 + else:
    160 9372e552 + img.set(imValue)
    161 c856a32c + #Set the first pixel read to a different value
    162 9372e552 + markbbox = afwGeom.Box2I()
    163 9372e552 + if amp.getReadoutCorner() == 0:
    164 9372e552 + markbbox.include(dbbox.getMin())
    165 9372e552 + markbbox.include(dbbox.getMin()+afwGeom.Extent2I(markSize, markSize))
    166 9372e552 + elif amp.getReadoutCorner() == 1:
    167 9372e552 + cornerPoint = afwGeom.Point2I(dbbox.getMaxX(), dbbox.getMinY())
    168 9372e552 + markbbox.include(cornerPoint)
    169 9372e552 + markbbox.include(cornerPoint + afwGeom.Extent2I(-markSize, markSize))
    170 9372e552 + elif amp.getReadoutCorner() == 2:
    171 9372e552 + cornerPoint = afwGeom.Point2I(dbbox.getMax())
    172 9372e552 + markbbox.include(cornerPoint)
    173 9372e552 + markbbox.include(cornerPoint + afwGeom.Extent2I(-markSize, -markSize))
    174 9372e552 + elif amp.getReadoutCorner() == 3:
    175 9372e552 + cornerPoint = afwGeom.Point2I(dbbox.getMinX(), dbbox.getMaxY())
    176 9372e552 + markbbox.include(cornerPoint)
    177 9372e552 + markbbox.include(cornerPoint + afwGeom.Extent2I(markSize, -markSize))
    178 439c701f + else:
    179 9372e552 + raise RuntimeError("Could not set readout corner")
    180 9372e552 + mimg = imageFactory(img, markbbox, False)
    181 9372e552 + mimg.set(markValue)
    182 9372e552 + return img
    183 82325a24 +
    184 9372e552 + def calcRawCcdBBox(ccd):
    185 545f4dc9 + """!Calculate the raw ccd bounding box
    186 545f4dc9 +
    187 545f4dc9 + @param[in] ccd Detector for with to calculate the un-trimmed bounding box
    188 bde0ab27 + @return Box2I of the un-trimmed Detector,
    189 bde0ab27 + or None if there is not enough information to calculate raw BBox
    190 f6e303b1 + """
    191 9372e552 + bbox = afwGeom.Box2I()
    192 9372e552 + for amp in ccd:
    193 9372e552 + if not amp.getHasRawInfo():
    194 36730423 + return None
    195 9372e552 + tbbox = amp.getRawBBox()
    196 9372e552 + tbbox.shift(amp.getRawXYOffset())
    197 9372e552 + bbox.include(tbbox)
    198 9372e552 + return bbox
    199 9372e552 +
    200 bde0ab27 + def makeImageFromCcd(ccd, isTrimmed=True, showAmpGain=True, imageFactory=afwImage.ImageU, rcMarkSize=10,
    201 bde0ab27 + binSize=1):
    202 545f4dc9 + """!Make an Image of a Ccd
    203 545f4dc9 +
    204 545f4dc9 + @param[in] ccd Detector to use in making the image
    205 545f4dc9 + @param[in] isTrimmed Assemble a trimmed Detector image if True
    206 545f4dc9 + @param[in] showAmpGain Use the per amp gain to color the pixels in the image
    207 545f4dc9 + @param[in] imageFactory Image type to generate
    208 545f4dc9 + @param[in] rcMarkSize Size of the mark to make in the amp images at the read corner
    209 545f4dc9 + @param[in] binSize Bin the image by this factor in both dimensions
    210 f6e303b1 + @return Image of the Detector
    211 d21f3141 + """
    212 d21f3141 + ampImages = []
    213 9372e552 + index = 0
    214 9372e552 + if isTrimmed:
    215 9372e552 + bbox = ccd.getBBox()
    216 9372e552 + else:
    217 9372e552 + bbox = calcRawCcdBBox(ccd)
    218 d21f3141 + for amp in ccd:
    219 9372e552 + if amp.getHasRawInfo():
    220 9372e552 + if showAmpGain:
    221 9372e552 + ampImages.append(makeImageFromAmp(amp, imageFactory=imageFactory, markSize=rcMarkSize))
    else:
    77 3b1e6cc7 - bbox = amp.getElectronicAllPixels()
    223 bde0ab27 + ampImages.append(makeImageFromAmp(amp, imValue=(index+1)*1000,
    224 bde0ab27 + imageFactory=imageFactory, markSize=rcMarkSize))
    225 9372e552 + index += 1
    226 9372e552 +
    227 9372e552 + if len(ampImages) > 0:
    228 9372e552 + ccdImage = imageFactory(bbox)
    229 9372e552 + for ampImage, amp in itertools.izip(ampImages, ccd):
    230 9372e552 + if isTrimmed:
    231 1ff73d16 + assembleAmplifierImage(ccdImage, ampImage, amp)
    78 993791af - else:
    232 9372e552 + else:
    ? ++++
    79 993791af - bbox = ccd.getAllPixels()
    233 1ff73d16 + assembleAmplifierRawImage(ccdImage, ampImage, amp)
    234 08da793e + else:
    235 9372e552 + if not isTrimmed:
    236 9372e552 + raise RuntimeError("Cannot create untrimmed CCD without amps with raw information")
    237 9372e552 + ccdImage = imageFactory(ccd.getBBox())
    238 c856a32c + ccdImage = afwMath.binImage(ccdImage, binSize)
    239 1f7e505a + return ccdImage
    81 61a76714 - md = None
    82 82325a24 - return imageFactory(fileName, hdu, md, bbox)
    241 ff18f270 + class FakeImageDataSource(object):
    242 d1d2fb23 + """A class to retrieve synthetic images for display by the show* methods"""
    243 ff18f270 + def __init__(self, isTrimmed=True, showAmpGain=True, markSize=10, markValue=0,
    244 ff18f270 + ampImValue=None, scaleGain = lambda gain: (gain*1000)//10):
    245 545f4dc9 + """!Construct a FakeImageDataSource
    247 545f4dc9 + @param[in] isTrimmed Should amps be trimmed?
    248 545f4dc9 + @param[in] showAmpGain color the amp segments with the gain of the amp
    249 545f4dc9 + @param[in] markSize size of the side of the box used to mark the read corner
    250 545f4dc9 + @param[in] markValue value to assing the read corner mark
    251 545f4dc9 + @param[in] ampImValue Value to assing to amps. scaleGain(gain) is used if None
    252 545f4dc9 + @param[in] scaleGain function to scale the gain by
    84 993791af - def setTrimmed(self, doTrim):
    85 993791af - self.isTrimmed = doTrim
    86 61a76714 -
    87 51d10d66 - class ButlerImage(GetCcdImage):
    88 993791af - """A class to return an Image of a given Ccd based on its cameraGeometry"""
    89 fd901390 -
    90 426eecd3 - def __init__(self, butler=None, type="raw", isTrimmed=True,
    91 08da793e - gravity=None, background=np.nan, *args, **kwargs):
    92 08da793e - """Initialise
    93 08da793e - gravity If the image returned by the butler is trimmed (e.g. some of the SuprimeCam CCDs)
    94 08da793e - Specify how to fit the image into the available space; N => align top, W => align left
    95 08da793e - background The value of any pixels that lie outside the CCDs
    """
    97 51d10d66 - super(ButlerImage, self).__init__(*args)
    self.isTrimmed = isTrimmed
    255 ff18f270 + self.showAmpGain = showAmpGain
    256 ff18f270 + self.markSize = markSize
    257 ff18f270 + self.markValue = markValue
    258 ff18f270 + self.ampImValue = ampImValue
    259 ff18f270 + self.scaleGain = scaleGain
    99 51d10d66 - self.type = type
    100 51d10d66 - self.butler = butler
    101 51d10d66 - self.kwargs = kwargs
    102 51d10d66 - self.isRaw = False
    103 08da793e - self.gravity = gravity
    104 08da793e - self.background = background
    106 51d10d66 - def getImage(self, ccd, amp=None, imageFactory=afwImage.ImageU):
    107 fd901390 - """Return an image of the specified amp in the specified ccd"""
    261 ff18f270 + def getCcdImage(self, det, imageFactory, binSize):
    262 545f4dc9 + """!Return a CCD image for the detector
    264 d1d2fb23 + @param[in] det: Detector to use for making the image
    265 d1d2fb23 + @param[in] imageFactory: image constructor for making the image
    266 d1d2fb23 + @param[in] binSize: number of pixels per bin axis
    267 d1d2fb23 + """
    268 bde0ab27 + return makeImageFromCcd(det, isTrimmed=self.isTrimmed, showAmpGain=self.showAmpGain,
    269 bde0ab27 + imageFactory=imageFactory, binSize=binSize)
    109 426eecd3 - im = None
    110 426eecd3 - if self.butler is not None:
    111 426eecd3 - try:
    112 426eecd3 - im = self.butler.get(self.type, ccd=ccd.getId().getSerial(),
    113 426eecd3 - **self.kwargs).getMaskedImage().getImage()
    114 426eecd3 - except Exception, e:
    115 426eecd3 - pass
    271 ff18f270 + def getAmpImage(self, amp, imageFactory):
    272 545f4dc9 + """!Return an amp segment image
    117 426eecd3 - if im is None:
    118 702f617d - return afwImage.ImageF(*ccd.getAllPixels(self.isTrimmed).getDimensions())
    119 51d10d66 -
    120 51d10d66 - if self.type == "raw":
    121 51d10d66 - im = im.convertF()
    122 3b1e6cc7 - else:
    123 51d10d66 - return im
    125 51d10d66 - trim = True
    126 51d10d66 - ccdImage = im.Factory(ccd.getAllPixels(trim))
    274 545f4dc9 + @param[in] amp AmpInfoTable for this amp
    275 545f4dc9 + @param[in] imageFactory image constructor fo making the imag
    276 d1d2fb23 + """
    277 bde0ab27 + ampImage = makeImageFromAmp(amp, imValue=self.ampImValue, imageFactory=imageFactory,
    278 bde0ab27 + markSize=self.markSize,
    279 ff18f270 + markValue=self.markValue, scaleGain=self.scaleGain)
    280 ff18f270 + if self.isTrimmed:
    281 ff18f270 + ampImage = ampImage.Factory(ampImage, amp.getRawDataBBox(), False)
    282 ff18f270 + return ampImage
    284 bde0ab27 + def overlayCcdBoxes(ccd, untrimmedCcdBbox, nQuarter, isTrimmed, ccdOrigin, display, binSize):
    285 bde0ab27 + """!Overlay bounding boxes on an image display
    286 545f4dc9 +
    287 545f4dc9 + @param[in] ccd Detector to iterate for the amp bounding boxes
    288 545f4dc9 + @param[in] untrimmedCcdBbox Bounding box of the un-trimmed Detector
    289 545f4dc9 + @param[in] nQuarter number of 90 degree rotations to apply to the bounding boxes
    290 545f4dc9 + @param[in] isTrimmed Is the Detector image over which the boxes are layed trimmed?
    291 545f4dc9 + @param[in] ccdOrigin Detector origin relative to the parent origin if in a larger pixel grid
    292 bde0ab27 + @param[in] display image display to display on
    293 545f4dc9 + @param[in] binSize binning factor
    294 f6e303b1 + """
    295 bde0ab27 + with afwDisplay.Buffering():
    296 9372e552 + ccdDim = untrimmedCcdBbox.getDimensions()
    297 1ff73d16 + ccdBbox = rotateBBoxBy90(untrimmedCcdBbox, nQuarter, ccdDim)
    128 51d10d66 - for a in ccd:
    298 9372e552 + for amp in ccd:
    ? ++
    129 51d10d66 - if trim:
    ? ^
    299 9372e552 + if isTrimmed:
    ? ^^^ +++
    300 9372e552 + ampbbox = amp.getBBox()
    130 51d10d66 - bias = im.Factory(im, a.getDiskBiasSec())
    131 51d10d66 -
    132 51d10d66 - sim = im.Factory(im, a.getDiskDataSec())
    133 51d10d66 -
    134 51d10d66 - sim -= afwMath.makeStatistics(bias, afwMath.MEANCLIP).getValue()
    135 51d10d66 -
    136 51d10d66 - a.setTrimmed(True)
    137 51d10d66 -
    138 51d10d66 - sub = ccdImage.Factory(ccdImage, a.getAllPixels(trim))
    139 51d10d66 -
    140 51d10d66 - sub <<= a.prepareAmpData(sim)
    141 51d10d66 - sub /= a.getElectronicParams().getGain()
    142 51d10d66 -
    143 51d10d66 - return ccdImage
    144 61a76714 -
    145 61a76714 - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    146 61a76714 -
    147 021325b8 - def mergeGeomDefaults(cameraGeomPolicy):
    148 021325b8 - policyFile = pexPolicy.DefaultPolicyFile("afw", "CameraGeomDictionary.paf", "policy")
    149 021325b8 - defPolicy = pexPolicy.Policy.createPolicy(policyFile, policyFile.getRepositoryPath(), True)
    150 021325b8 -
    151 021325b8 - cameraGeomPolicy.mergeDefaults(defPolicy.getDictionary())
    152 021325b8 -
    153 021325b8 - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    154 021325b8 -
    155 021325b8 - def getGeomPolicy(cameraGeomPolicy):
    156 021325b8 - """Return a Policy describing a Camera's geometry given a filename; the Policy will be validated using the
    157 021325b8 - dictionary, and defaults will be supplied. If you pass a Policy, it will be validated and completed.
    158 021325b8 - """
    159 d30faf6b -
    160 d30faf6b - policyFile = pexPolicy.DefaultPolicyFile("afw", "CameraGeomDictionary.paf", "policy")
    161 d30faf6b - defPolicy = pexPolicy.Policy.createPolicy(policyFile, policyFile.getRepositoryPath(), True)
    162 d30faf6b -
    163 021325b8 - if isinstance(cameraGeomPolicy, pexPolicy.Policy):
    164 021325b8 - geomPolicy = cameraGeomPolicy
    165 021325b8 - else:
    166 021325b8 - if os.path.exists(cameraGeomPolicy):
    167 021325b8 - geomPolicy = pexPolicy.Policy.createPolicy(cameraGeomPolicy)
    168 021325b8 - else:
    169 021325b8 - policyFile = pexPolicy.DefaultPolicyFile("afw", cameraGeomPolicy, "examples")
    170 021325b8 - geomPolicy = pexPolicy.Policy.createPolicy(policyFile, policyFile.getRepositoryPath(), True)
    171 d30faf6b -
    172 d30faf6b - geomPolicy.mergeDefaults(defPolicy.getDictionary())
    173 d30faf6b -
    174 d30faf6b - return geomPolicy
    175 d30faf6b -
    176 d30faf6b - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    177 d30faf6b -
    178 f9281729 - def makeLinearityFromPolicy(linPol, gain=1.0):
    179 4ce2709b - """Make and return a Linearity object from a suitable policy"""
    180 a9c01489 - assert linPol.get("type") == "PROPORTIONAL", "Checked in CameraGeomDictionary.paf"
    181 4ce2709b -
    182 f9281729 - threshold = linPol.get("threshold")
    183 f9281729 - maxCorrectable = linPol.get("maxCorrectable")
    184 f9281729 - coefficient = linPol.get("coefficient")
    185 f9281729 -
    186 f9281729 - if linPol.get("intensityUnits") == "ELECTRONS":
    187 f9281729 - threshold = int(threshold/gain + 0.5)
    188 f9281729 - maxCorrectable = int(maxCorrectable/gain + 0.5)
    189 f9281729 - coefficient /= gain
    190 f9281729 - else:
    191 f9281729 - assert linPol.get("intensityUnits") == "DN", "Checked in CameraGeomDictionary.paf"
    192 f9281729 -
    193 4ce2709b - return cameraGeom.Linearity(cameraGeom.Linearity.PROPORTIONAL,
    194 f9281729 - threshold, maxCorrectable, coefficient)
    195 4ce2709b -
    196 4ce2709b -
    197 31bfc9f3 - def makeCcd(geomPolicy, ccdId=None, ccdInfo=None, defectDict={}, ccdDescription=None):
    198 61a76714 - """Build a Ccd from a set of amplifiers given a suitable pex::Policy
    199 61a76714 -
    200 61a76714 - If ccdInfo is provided it's set to various facts about the CCDs which are used in unit tests. Note
    201 61a76714 - in particular that it has an entry ampSerial which is a single-element list, the amplifier serial counter
    202 61a76714 - """
    203 31bfc9f3 - ccdPol = None
    204 31bfc9f3 - if ccdDescription:
    205 31bfc9f3 - try:
    206 31bfc9f3 - tId = cameraGeom.Id(ccdDescription.get("serial"), ccdDescription.get("name"))
    207 31bfc9f3 - except Exception, e:
    208 31bfc9f3 - tId = cameraGeom.Id(0, "unknown")
    209 31bfc9f3 - if ccdId:
    210 31bfc9f3 - if not tId == ccdId:
    211 31bfc9f3 - raise("Identifiers don't agree -- Passed: %s, Policy: %s"%(ccdId.__str__(), tId.__str__()))
    212 31bfc9f3 - else:
    213 31bfc9f3 - ccdId = tId
    214 31bfc9f3 - ccdTempArr = geomPolicy.getArray("Ccd")
    215 31bfc9f3 - for ct in ccdTempArr:
    216 31bfc9f3 - if ct.get("ptype") == ccdDescription.get("ptype"):
    217 31bfc9f3 - ccdPol = ct
    218 31bfc9f3 - else:
    219 31bfc9f3 - ccdPol = geomPolicy.get("Ccd")
    220 31bfc9f3 - if not ccdPol:
    221 31bfc9f3 - raise("No valid CCD policy found")
    222 61a76714 - pixelSize = ccdPol.get("pixelSize")
    223 ee28a753 - offsetUnit = ccdPol.get('offsetUnit')
    224 0b8fe106 -
    225 61a76714 - nCol = ccdPol.get("nCol")
    226 61a76714 - nRow = ccdPol.get("nRow")
    227 31bfc9f3 - ccdType = ccdPol.get("ptype")
    228 61a76714 - if not ccdId:
    229 61a76714 - try:
    230 61a76714 - ccdId = cameraGeom.Id(ccdPol.get("serial"), ccdPol.get("name"))
    231 61a76714 - except Exception, e:
    232 61a76714 - ccdId = cameraGeom.Id(0, "unknown")
    233 516257ea - #
    234 516257ea - # Find the proper electronic parameters. The Ccd name may be specified as "*" to match all detectors,
    235 516257ea - # a feature that's probably mostly useful for testing
    236 516257ea - #
    237 516257ea - electronicPol = geomPolicy.get("Electronic")
    238 516257ea - electronics = {}
    239 516257ea - for pol in electronicPol.getArray("Raft"):
    240 516257ea - for pol in pol.getArray("Ccd"):
    241 516257ea - electronicCcdName = pol.get("name")
    242 31bfc9f3 - electronicCcdType = pol.get("ptype")
    243 31bfc9f3 - if electronicCcdName in ("*", ccdId.getName()) and electronicCcdType == ccdType:
    244 516257ea - electronics["ccdName"] = electronicCcdName
    245 516257ea - for p in pol.getArray("Amp"):
    246 20ad51f1 - electronics[tuple(p.getArray("index"))] = p
    247 516257ea - break
    248 516257ea - #
    249 516257ea - # Actually build the Ccd
    250 516257ea - #
    251 61a76714 - ccd = cameraGeom.Ccd(ccdId, pixelSize)
    252 439c701f - for k in defectDict.keys():
    253 439c701f - if ccdId == k:
    254 439c701f - ccd.setDefects(defectDict[k])
    255 2706712c - else:
    256 2706712c - pass
    257 61a76714 -
    258 61a76714 - if nCol*nRow != len(ccdPol.getArray("Amp")):
    259 97dea9da - msg = "Expected location of %d amplifiers, got %d" % (nCol*nRow, len(ccdPol.getArray("Amp")))
    260 97dea9da -
    261 97dea9da - if force:
    262 97dea9da - print >> sys.stderr, msg
    263 97dea9da - else:
    264 97dea9da - raise RuntimeError, msg
    265 61a76714 -
    266 61a76714 - if ccdInfo is None:
    267 61a76714 - ampSerial = [0]
    268 61a76714 - else:
    269 61a76714 - ampSerial = ccdInfo.get("ampSerial", [0])
    270 516257ea - ampSerial0 = None # used in testing
    271 61a76714 -
    272 61a76714 - readoutCorners = dict(LLC = cameraGeom.Amp.LLC,
    273 61a76714 - LRC = cameraGeom.Amp.LRC,
    274 61a76714 - ULC = cameraGeom.Amp.ULC,
    275 61a76714 - URC = cameraGeom.Amp.URC)
    276 e68d3975 -
    277 e68d3975 - diskCoordSys = dict(AMP = cameraGeom.Amp.AMP,
    278 e68d3975 - SENSOR = cameraGeom.Amp.SENSOR,
    279 e68d3975 - CAMERA = cameraGeom.Amp.CAMERA)
    280 e68d3975 -
    281 61a76714 - for ampPol in ccdPol.getArray("Amp"):
    282 516257ea - if ampPol.exists("serial"):
    283 516257ea - serial = ampPol.get("serial")
    284 516257ea - ampSerial[0] = serial
    285 516257ea - else:
    286 516257ea - serial = ampSerial[0]
    287 516257ea - ampSerial[0] += 1
    288 516257ea -
    289 516257ea - if ampSerial0 is None:
    290 516257ea - ampSerial0 = serial
    291 516257ea -
    292 20ad51f1 - Col, Row = index = tuple(ampPol.getArray("index"))
    293 31bfc9f3 - ampType = ampPol.get("ptype")
    294 31bfc9f3 - flipLR = ampPol.get("flipLR")
    295 e68d3975 - try:
    296 e68d3975 - coordSys = diskCoordSys[ampPol.get("diskCoordSys").upper()]
    297 e68d3975 -
    298 e68d3975 - except Exception, e:
    299 e68d3975 - raise("Coordinate system specified in the policy must be one of: %s"%(",".join(diskCoordSys.keys())))
    300 31bfc9f3 - nQuarterAmp = ampPol.get("nQuarter")
    301 31bfc9f3 - hdu = ampPol.get("hdu")
    302 61a76714 -
    303 61a76714 - if Col not in range(nCol) or Row not in range(nRow):
    304 97dea9da - msg = "Amp location %d, %d is not in 0..%d, 0..%d" % (Col, Row, nCol, nRow)
    305 97dea9da - if force:
    306 97dea9da - print >> sys.stderr, msg
    307 97dea9da - continue
    else:
    302 9372e552 + ampbbox = amp.getRawBBox()
    303 9372e552 + ampbbox.shift(amp.getRawXYOffset())
    309 97dea9da - raise RuntimeError, msg
    310 61a76714 -
    311 516257ea - try:
    312 20ad51f1 - ePol = electronics[index]
    313 516257ea - gain = ePol.get("gain")
    314 516257ea - readNoise = ePol.get("readNoise")
    315 516257ea - saturationLevel = ePol.get("saturationLevel")
    316 516257ea - except KeyError:
    317 516257ea - if electronics.get("ccdName") != "*":
    318 516257ea - raise RuntimeError, ("Unable to find electronic info for Ccd \"%s\", Amp %s" %
    319 516257ea - (ccd.getId(), serial))
    320 516257ea - gain, readNoise, saturationLevel = 0, 0, 0
    321 61a76714 - #
    322 61a76714 - # Now lookup properties common to all the CCD's amps
    323 61a76714 - #
    324 31bfc9f3 - ampPolArr = geomPolicy.getArray("Amp")
    325 31bfc9f3 - ampPol = None
    326 31bfc9f3 - for p in ampPolArr:
    327 31bfc9f3 - if p.get("ptype") == ampType:
    328 31bfc9f3 - ampPol = p
    329 31bfc9f3 - if ampPol is None:
    330 31bfc9f3 - raise RuntimeError, ("Unable to find bounding box info for Amp: %i, %i in Ccd \"%s\""%(Col, Row, ccd.getId()))
    331 31bfc9f3 -
    332 31bfc9f3 - minx, miny, maxx, maxy = tuple(ampPol.getArray("datasec"))
    333 31bfc9f3 - dataSec = afwGeom.Box2I(afwGeom.Point2I(minx, miny), afwGeom.Point2I(maxx, maxy))
    334 31bfc9f3 - minx, miny, maxx, maxy = tuple(ampPol.getArray("biassec"))
    335 31bfc9f3 - biasSec = afwGeom.Box2I(afwGeom.Point2I(minx, miny), afwGeom.Point2I(maxx, maxy))
    336 31bfc9f3 - eWidth = ampPol.get("ewidth")
    337 31bfc9f3 - eHeight = ampPol.get("eheight")
    338 3b1e6cc7 - allPixelsInAmp = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(eWidth, eHeight))
    339 61a76714 -
    340 61a76714 - eParams = cameraGeom.ElectronicParams(gain, readNoise, saturationLevel)
    341 ac97fc48 - amp = cameraGeom.Amp(cameraGeom.Id(serial, "ID%d" % serial, Col, Row),
    342 3b1e6cc7 - allPixelsInAmp, biasSec, dataSec, eParams)
    343 3b1e6cc7 - #The following maps how the amp pixels must be changed to go from electronic (on disk) coordinates
    344 3b1e6cc7 - #to detector coordinates. This also sets the readout corner.
    345 e68d3975 - amp.setElectronicToChipLayout(afwGeom.Point2I(Col, Row), nQuarterAmp, flipLR, coordSys)
    346 7ffd25c1 - #
    347 7ffd25c1 - # Actually add amp to the Ccd
    348 7ffd25c1 - #
    349 83689a40 - ccd.addAmp(amp)
    350 61a76714 - #
    351 4ce2709b - # Read any linearity information
    352 4ce2709b - #
    353 4ce2709b - # Start by looking for our CCD, then (failing that) for the default, with CCD serial number -1,
    354 4ce2709b - #
    355 a9c01489 - def findLinearity(serial):
    356 a9c01489 - pol = [pol for pol in geomPolicy.get("Linearity").getArray("Ccd") if pol.get("serial") == serial]
    357 a9c01489 - if not pol:
    358 a9c01489 - return None
    359 a9c01489 -
    360 a9c01489 - if len(pol) != 1:
    361 a9c01489 - raise RuntimeError("Found more than one Linearity for serial %d" % (serial))
    362 a9c01489 - return pol[0]
    363 a9c01489 -
    364 a9c01489 - linearityPolicy = findLinearity(ccdId.getSerial())
    365 a9c01489 - if not linearityPolicy:
    366 a9c01489 - linearityPolicy = findLinearity(-1)
    367 4ce2709b - #
    368 4ce2709b - # If we have a policy, set the linearity parameters
    369 4ce2709b - #
    370 a9c01489 - if linearityPolicy:
    371 a9c01489 - linPols = {}
    372 a9c01489 - for policy in linearityPolicy.getArray("Amp"):
    373 a9c01489 - linPols[policy.get("serial")] = policy
    374 a9c01489 -
    375 4ce2709b - for amp in ccd:
    376 f9281729 - ep = amp.getElectronicParams()
    377 a9c01489 - try:
    378 f9281729 - lin = makeLinearityFromPolicy(linPols[amp.getId().getSerial()], gain=ep.getGain())
    379 a9c01489 - except KeyError:
    380 a9c01489 - continue
    381 f9281729 - ep.setLinearity(lin)
    382 4ce2709b - #
    383 61a76714 - # Information for the test code
    384 61a76714 - #
    385 61a76714 - if ccdInfo is not None:
    386 31bfc9f3 - width, height = tuple(dataSec.getDimensions())
    387 61a76714 - ccdInfo.clear()
    388 61a76714 - ccdInfo["ampSerial"] = ampSerial
    389 61a76714 - ccdInfo["name"] = ccd.getId().getName()
    390 61a76714 - ccdInfo["ampWidth"], ccdInfo["ampHeight"] = width, height
    391 61a76714 - ccdInfo["width"], ccdInfo["height"] = nCol*eWidth, nRow*eHeight
    392 61a76714 - ccdInfo["trimmedWidth"], ccdInfo["trimmedHeight"] = nCol*width, nRow*height
    393 61a76714 - ccdInfo["pixelSize"] = pixelSize
    394 ee28a753 - ccdInfo["offsetUnit"] = offsetUnit
    395 61a76714 - ccdInfo["ampIdMin"] = ampSerial0
    396 61a76714 - ccdInfo["ampIdMax"] = ampSerial[0] - 1
    397 61a76714 -
    398 61a76714 - return ccd
    399 61a76714 -
    400 2706712c - def makeRaft(geomPolicy, raftId=None, raftInfo=None, defectDict={}):
    401 61a76714 - """Build a Raft from a set of CCDs given a suitable pex::Policy
    402 61a76714 -
    403 61a76714 - If raftInfo is provided it's set to various facts about the Rafts which are used in unit tests. Note in
    404 61a76714 - particular that it has an entry ampSerial which is a single-element list, the amplifier serial counter
    405 61a76714 - """
    406 61a76714 -
    407 61a76714 - if raftInfo is None:
    408 018ddb66 - ccdInfo = {}
    409 61a76714 - else:
    410 61a76714 - ccdInfo = {"ampSerial" : raftInfo.get("ampSerial", [0])}
    411 61a76714 -
    412 77729dfe - if raftId and geomPolicy.isArray("Raft"):
    413 73bee471 - raftPol = None
    414 73bee471 - for p in geomPolicy.getArray("Raft"):
    415 73bee471 - if p.exists("name"): # Build an Id from available information
    416 73bee471 - if p.exists("serial"):
    417 73bee471 - rid = cameraGeom.Id(p.get("serial"), p.get("name"))
    418 73bee471 - else:
    419 73bee471 - rid = cameraGeom.Id(p.get("name"))
    420 73bee471 - elif p.exists("serial"):
    421 73bee471 - rid = cameraGeom.Id(p.get("serial"))
    422 73bee471 - else:
    423 73bee471 - raise RuntimeError, "Please provide a raft name, a raft serial, or both"
    424 73bee471 -
    425 73bee471 - if rid == raftId:
    426 73bee471 - raftPol = p
    427 73bee471 - break
    428 73bee471 -
    429 73bee471 - if not raftPol:
    430 73bee471 - raise RuntimeError, ("I can't find Raft %s" % raftId)
    431 73bee471 - else:
    432 73bee471 - raftPol = geomPolicy.get("Raft")
    433 73bee471 -
    434 61a76714 - nCol = raftPol.get("nCol")
    435 61a76714 - nRow = raftPol.get("nRow")
    436 61a76714 - if not raftId:
    437 61a76714 - try:
    438 61a76714 - raftId = cameraGeom.Id(raftPol.get("serial"), raftPol.get("name"))
    439 61a76714 - except Exception, e:
    440 61a76714 - raftId = cameraGeom.Id(0, "unknown")
    441 7ffd25c1 - #
    442 7ffd25c1 - # Build the Raft
    443 7ffd25c1 - #
    444 61a76714 - raft = cameraGeom.Raft(raftId, nCol, nRow)
    445 61a76714 -
    446 61a76714 - if nCol*nRow != len(raftPol.getArray("Ccd")):
    447 9ea37372 - if False: # many cameras don't use filled rafts at the edge (e.g. HSC)
    448 9ea37372 - msg = "Expected location of %d Ccds, got %d" % (nCol*nRow, len(raftPol.getArray("Ccd")))
    449 9ea37372 -
    450 9ea37372 - if force:
    451 9ea37372 - print >> sys.stderr, msg
    452 9ea37372 - else:
    453 9ea37372 - raise RuntimeError, msg
    454 61a76714 -
    455 61a76714 - for ccdPol in raftPol.getArray("Ccd"):
    456 ee28a753 - Col, Row = ccdPol.getArray("index")
    457 ee28a753 - xc, yc = ccdPol.getArray("offset")
    458 ee28a753 -
    459 61a76714 - nQuarter = ccdPol.get("nQuarter")
    460 df438a72 - pitch, roll, yaw = [afwGeom.Angle(a, afwGeom.degrees) for a in ccdPol.getArray("orientation")]
    461 61a76714 -
    462 61a76714 - if Col not in range(nCol) or Row not in range(nRow):
    463 97dea9da - msg = "Ccd location %d, %d is not in 0..%d, 0..%d" % (Col, Row, nCol, nRow)
    464 97dea9da - if force:
    465 97dea9da - print >> sys.stderr, msg
    466 97dea9da - continue
    467 97dea9da - else:
    468 97dea9da - raise RuntimeError, msg
    469 61a76714 -
    470 61a76714 - ccdId = cameraGeom.Id(ccdPol.get("serial"), ccdPol.get("name"))
    471 31bfc9f3 - ccd = makeCcd(geomPolicy, ccdDescription=ccdPol, ccdId=ccdId, ccdInfo=ccdInfo, defectDict=defectDict)
    472 ee28a753 - pixelSize = ccd.getPixelSize()
    473 ee28a753 -
    474 ee28a753 - offsetUnit = ccdInfo["offsetUnit"]
    475 ee28a753 - if offsetUnit == 'pixels':
    476 ee28a753 - xc *= pixelSize
    477 ee28a753 - yc *= pixelSize
    478 ee28a753 -
    479 c9c89e06 - raft.addDetector(afwGeom.Point2I(Col, Row),
    480 ee28a753 - cameraGeom.FpPoint(xc, yc),
    481 61a76714 - cameraGeom.Orientation(nQuarter, pitch, roll, yaw), ccd)
    482 61a76714 -
    483 61a76714 - if raftInfo is not None:
    484 61a76714 - # Guess the gutter between detectors
    485 61a76714 - if (Col, Row) == (0, 0):
    486 61a76714 - xGutter, yGutter = xc, yc
    487 61a76714 - elif (Col, Row) == (nCol - 1, nRow - 1):
    488 61a76714 - if nCol == 1:
    489 61a76714 - xGutter = 0.0
    490 61a76714 - else:
    491 6b9ab890 - xGutter = (xc - xGutter)/float(nCol - 1) - ccd.getSize().getMm()[0]
    492 61a76714 -
    493 61a76714 - if nRow == 1:
    494 61a76714 - yGutter = 0.0
    495 61a76714 - else:
    496 6b9ab890 - yGutter = (yc - yGutter)/float(nRow - 1) - ccd.getSize().getMm()[1]
    497 61a76714 -
    498 61a76714 - if raftInfo is not None:
    499 61a76714 - raftInfo.clear()
    500 61a76714 - raftInfo["ampSerial"] = ccdInfo["ampSerial"]
    501 61a76714 - raftInfo["name"] = raft.getId().getName()
    502 61a76714 - raftInfo["pixelSize"] = ccd.getPixelSize()
    503 61a76714 - raftInfo["width"] = nCol*ccd.getAllPixels(True).getWidth()
    504 61a76714 - raftInfo["height"] = nRow*ccd.getAllPixels(True).getHeight()
    505 6b9ab890 - raftInfo["widthMm"] = nCol*ccd.getSize().getMm()[0] + (nCol - 1)*xGutter
    506 6b9ab890 - raftInfo["heightMm"] = nRow*ccd.getSize().getMm()[1] + (nRow - 1)*yGutter
    507 61a76714 -
    508 61a76714 - return raft
    509 61a76714 -
    510 61a76714 - def makeCamera(geomPolicy, cameraId=None, cameraInfo=None):
    511 61a76714 - """Build a Camera from a set of Rafts given a suitable pex::Policy
    512 61a76714 -
    513 61a76714 - If cameraInfo is provided it's set to various facts about the Camera which are used in unit tests. Note in
    514 61a76714 - particular that it has an entry ampSerial which is a single-element list, the amplifier serial counter
    515 61a76714 - """
    516 61a76714 - if cameraInfo is None:
    517 61a76714 - raftInfo = None
    518 61a76714 - else:
    519 61a76714 - raftInfo = {"ampSerial" : cameraInfo.get("ampSerial", [0])}
    520 61a76714 -
    521 61a76714 - cameraPol = geomPolicy.get("Camera")
    522 61a76714 - nCol = cameraPol.get("nCol")
    523 61a76714 - nRow = cameraPol.get("nRow")
    524 61a76714 -
    525 61a76714 - if not cameraId:
    526 61a76714 - cameraId = cameraGeom.Id(cameraPol.get("serial"), cameraPol.get("name"))
    527 61a76714 - camera = cameraGeom.Camera(cameraId, nCol, nRow)
    528 2706712c -
    529 2706712c - if geomPolicy.get("Defects").get("Raft").get("Ccd").isPolicy("Defect"):
    530 439c701f - defDict = makeDefects(geomPolicy)
    531 439c701f - else:
    532 439c701f - defDict = {}
    533 439c701f -
    534 61a76714 - for raftPol in cameraPol.getArray("Raft"):
    535 61a76714 - Col, Row = raftPol.getArray("index")
    536 61a76714 - xc, yc = raftPol.getArray("offset")
    537 61a76714 - raftId = cameraGeom.Id(raftPol.get("serial"), raftPol.get("name"))
    538 439c701f - raft = makeRaft(geomPolicy, raftId, raftInfo, defectDict=defDict)
    539 c9c89e06 - camera.addDetector(afwGeom.Point2I(Col, Row),
    540 e88ff0cd - cameraGeom.FpPoint(afwGeom.Point2D(xc, yc)),
    541 6b9ab890 - cameraGeom.Orientation(), raft)
    542 61a76714 -
    543 61a76714 - if cameraInfo is not None:
    544 61a76714 - # Guess the gutter between detectors
    545 61a76714 - if (Col, Row) == (0, 0):
    546 61a76714 - xGutter, yGutter = xc, yc
    547 61a76714 - elif (Col, Row) == (nCol - 1, nRow - 1):
    548 61a76714 - if nCol == 1:
    549 61a76714 - xGutter = 0.0
    550 61a76714 - else:
    551 6b9ab890 - xGutter = (xc - xGutter)/float(nCol - 1) - raft.getSize().getMm()[0]
    552 61a76714 -
    553 61a76714 - if nRow == 1:
    554 61a76714 - yGutter = 0.0
    555 61a76714 - else:
    556 6b9ab890 - yGutter = (yc - yGutter)/float(nRow - 1) - raft.getSize().getMm()[1]
    557 61a76714 -
    558 24436bda -
    559 24436bda - #######################
    560 24436bda - # get the distortion
    561 24436bda - distortPolicy = cameraPol.get('Distortion')
    562 24436bda - distortActive = distortPolicy.get('active')
    563 24436bda - activePolicy = distortPolicy.get(distortActive)
    564 24436bda -
    565 24436bda - distort = None
    566 24436bda - if distortActive == "NullDistortion":
    567 ee28a753 - distort = cameraGeom.NullDistortion()
    568 24436bda - elif distortActive == "RadialPolyDistortion":
    569 ee28a753 - coeffs = activePolicy.getArray('coeffs')
    570 d7ff8a52 - coefficientsDistort = activePolicy.get('coefficientsDistort')
    571 ee28a753 - distort = cameraGeom.RadialPolyDistortion(coeffs, coefficientsDistort)
    572 24436bda - camera.setDistortion(distort)
    573 24436bda -
    574 24436bda -
    575 61a76714 - if cameraInfo is not None:
    576 61a76714 - cameraInfo.clear()
    577 61a76714 - cameraInfo["ampSerial"] = raftInfo["ampSerial"]
    578 61a76714 - cameraInfo["name"] = camera.getId().getName()
    579 61a76714 - cameraInfo["width"] = nCol*raft.getAllPixels().getWidth()
    580 61a76714 - cameraInfo["height"] = nRow*raft.getAllPixels().getHeight()
    581 61a76714 - cameraInfo["pixelSize"] = raft.getPixelSize()
    582 6b9ab890 - cameraInfo["widthMm"] = nCol*raft.getSize().getMm()[0] + (nCol - 1)*xGutter
    583 6b9ab890 - cameraInfo["heightMm"] = nRow*raft.getSize().getMm()[1] + (nRow - 1)*yGutter
    584 61a76714 -
    585 61a76714 - return camera
    586 61a76714 -
    587 61a76714 - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    588 61a76714 -
    589 426eecd3 - def makeAmpImageFromCcd(amp, imageSource=ButlerImage(), isTrimmed=None, imageFactory=afwImage.ImageU):
    590 82325a24 - """Make an Image of an Amp"""
    591 82325a24 -
    592 82325a24 - return imageSource.getImage(amp, imageFactory=imageFactory)
    593 82325a24 -
    594 426eecd3 - def makeImageFromCcd(ccd, imageSource=ButlerImage(), amp=None,
    595 08da793e - isTrimmed=None, correctGain = False, imageFactory=afwImage.ImageU, bin=1,
    596 08da793e - display=False):
    597 e193729a - """Make an Image of a Ccd (or just a single amp)
    598 e193729a - """
    599 61a76714 -
    600 61a76714 - if isTrimmed is None:
    601 61a76714 - isTrimmed = ccd.isTrimmed()
    602 08da793e - if imageSource:
    603 08da793e - imageSource.setTrimmed(isTrimmed)
    604 61a76714 -
    605 82325a24 - if amp:
    606 82325a24 - ampImage = imageFactory(amp.getAllPixels(isTrimmed).getDimensions())
    607 82325a24 - ampImage <<= imageSource.getImage(ccd, amp, imageFactory=imageFactory)
    608 82325a24 -
    609 17aa5ab7 - if bin > 1:
    610 97dea9da - ampImage = afwMath.binImage(ampImage, bin)
    611 97dea9da -
    612 82325a24 - return ampImage
    613 e193729a - #
    614 e2db5f35 - # If the image is raw it may need to be assembled into a full sensor. The Amp object knows
    615 e2db5f35 - # the coordinates system in which the data is being stored on disk. Since all bounding box
    616 e2db5f35 - # information is held in camera coordinates, there is no need to rotate the image after assembly.
    617 e193729a - #
    618 08da793e - if imageSource:
    619 08da793e - if imageSource.isRaw:
    620 08da793e - ccdImage = imageFactory(ccd.getAllPixels(isTrimmed))
    621 08da793e - for a in ccd:
    622 08da793e - im = ccdImage.Factory(ccdImage, a.getAllPixels(isTrimmed), afwImage.LOCAL)
    623 08da793e - im <<= imageSource.getImage(ccd, a, imageFactory=imageFactory)
    624 08da793e - else:
    625 08da793e - ccdImage = imageSource.getImage(ccd, imageFactory=imageFactory)
    626 08da793e - if correctGain:
    627 08da793e - for a in ccd:
    628 08da793e - samp = ccdImage.Factory(ccdImage, a.getAllPixels(True))
    629 08da793e - samp /= a.getElectronicParams().getGain()
    630 97dea9da -
    631 08da793e - if bin > 1:
    632 08da793e - ccdImage = afwMath.binImage(ccdImage, bin)
    633 08da793e - if display:
    634 08da793e - showCcd(ccd, ccdImage=ccdImage, isTrimmed=isTrimmed)
    635 08da793e - else:
    636 08da793e - dims = ccd.getAllPixels(isTrimmed).getDimensions()
    637 08da793e - ccdImage = imageFactory(dims[0]//bin, dims[1]//bin)
    638 08da793e -
    639 1f7e505a - return ccdImage
    640 61a76714 -
    641 64a9e1e1 - def trimExposure(ccdImage, ccd=None):
    642 64a9e1e1 - """Trim a raw CCD Exposure"""
    643 64a9e1e1 -
    644 64a9e1e1 - if not ccd:
    645 64a9e1e1 - ccd = cameraGeom.cast_Ccd(ccdImage.getDetector())
    646 64a9e1e1 -
    647 a8f86353 - dim = ccd.getAllPixelsNoRotation(True).getDimensions()
    648 a8f86353 - trimmedImage = ccdImage.Factory(dim)
    649 64a9e1e1 - for a in ccd:
    650 a8f86353 - data = ccdImage.Factory(ccdImage, a.getDataSec(False), afwImage.LOCAL).getMaskedImage()
    651 a8f86353 - tdata = trimmedImage.Factory(trimmedImage, a.getDataSec(True), afwImage.LOCAL).getMaskedImage()
    652 64a9e1e1 - tdata <<= data
    653 64a9e1e1 -
    654 64a9e1e1 - ccd.setTrimmed(True)
    655 64a9e1e1 - return trimmedImage
    656 64a9e1e1 -
    657 e193729a - def showCcd(ccd, ccdImage="", amp=None, ccdOrigin=None, isTrimmed=None, frame=None, overlay=True, bin=1):
    658 993791af - """Show a CCD on ds9. If cameraImage is "", an image will be created based on the properties
    659 61a76714 - of the detectors"""
    660 912ae9b0 -
    661 08da793e - if ccdOrigin is None:
    662 08da793e - ccdOrigin = afwGeom.PointD(0, 0)
    663 08da793e - else:
    664 08da793e - ccdOrigin = ccd.getPositionFromPixel(afwGeom.PointD(0, 0)).getMm() # + afwGeom.ExtentD(ccdOrigin)
    665 08da793e -
    666 61a76714 - if isTrimmed is None:
    667 61a76714 - isTrimmed = ccd.isTrimmed()
    668 61a76714 -
    669 61a76714 - if ccdImage == "":
    670 97dea9da - ccdImage = makeImageFromCcd(ccd, bin=bin)
    671 61a76714 -
    672 993791af - if ccdImage:
    673 61a76714 - title = ccd.getId().getName()
    674 82325a24 - if amp:
    675 82325a24 - title += ":%d" % amp.getId().getSerial()
    676 61a76714 - if isTrimmed:
    677 61a76714 - title += "(trimmed)"
    678 61a76714 - ds9.mtv(ccdImage, frame=frame, title=title)
    679 61a76714 -
    680 61a76714 - if not overlay:
    681 61a76714 - return
    682 61a76714 -
    683 546bbd40 - with ds9.Buffering():
    684 546bbd40 - if amp:
    685 546bbd40 - bboxes = [(amp.getAllPixels(isTrimmed), 0.49, None),]
    686 546bbd40 - xy0 = bboxes[0][0].getMin()
    687 546bbd40 - if not isTrimmed:
    688 546bbd40 - bboxes.append((amp.getBiasSec(), 0.49, ds9.RED))
    689 546bbd40 - bboxes.append((amp.getDataSec(), 0.49, ds9.BLUE))
    690 546bbd40 -
    691 546bbd40 - for bbox, borderWidth, ctype in bboxes:
    692 546bbd40 - bbox = bbox.clone()
    693 546bbd40 - bbox.shift(-afwGeom.ExtentI(xy0))
    694 546bbd40 - displayUtils.drawBBox(bbox, borderWidth=borderWidth, ctype=ctype, frame=frame, bin=bin)
    695 546bbd40 -
    696 546bbd40 - return
    697 546bbd40 -
    698 546bbd40 - nQuarter = ccd.getOrientation().getNQuarter()
    699 546bbd40 - # ccdDim = cameraGeom.rotateBBoxBy90(ccd.getAllPixels(isTrimmed), nQuarter,
    700 546bbd40 - # ccd.getAllPixels(isTrimmed).getDimensions()).getDimensions()
    701 546bbd40 - for a in ccd:
    702 546bbd40 - bbox = a.getAllPixels(isTrimmed)
    703 546bbd40 - # if nQuarter != 0:
    ? -
    304 9372e552 + if nQuarter != 0:
    704 546bbd40 - # bbox = cameraGeom.rotateBBoxBy90(bbox, nQuarter, ccdDim)
    305 1ff73d16 + ampbbox = rotateBBoxBy90(ampbbox, nQuarter, ccdDim)
    706 546bbd40 - displayUtils.drawBBox(bbox, origin=ccdOrigin, borderWidth=0.49,
    307 9372e552 + displayUtils.drawBBox(ampbbox, origin=ccdOrigin, borderWidth=0.49,
    ? +++
    707 546bbd40 - frame=frame, bin=bin)
    ? ^^ ^^ ^^ ^^
    308 bde0ab27 + display=display, bin=binSize)
    ? ^^^^^ ^ ^^^^^ ^ ++++
    709 546bbd40 - if not isTrimmed:
    710 546bbd40 - for bbox, ctype in ((a.getBiasSec(), ds9.RED), (a.getDataSec(), ds9.BLUE)):
    310 9372e552 + if not isTrimmed and amp.getHasRawInfo():
    311 bde0ab27 + for bbox, ctype in ((amp.getRawHorizontalOverscanBBox(), afwDisplay.RED),
    312 bde0ab27 + (amp.getRawDataBBox(), afwDisplay.BLUE),
    313 bde0ab27 + (amp.getRawVerticalOverscanBBox(), afwDisplay.MAGENTA),
    314 bde0ab27 + (amp.getRawPrescanBBox(), afwDisplay.YELLOW)):
    315 9372e552 + if amp.getRawFlipX():
    316 9372e552 + bbox.flipLR(amp.getRawBBox().getDimensions().getX())
    317 9372e552 + if amp.getRawFlipY():
    318 9372e552 + bbox.flipTB(amp.getRawBBox().getDimensions().getY())
    319 9372e552 + bbox.shift(amp.getRawXYOffset())
    711 546bbd40 - # if nQuarter != 0:
    ? -
    320 9372e552 + if nQuarter != 0:
    712 546bbd40 - # bbox = cameraGeom.rotateBBoxBy90(bbox, nQuarter, ccdDim)
    ? - -----------
    321 1ff73d16 + bbox = rotateBBoxBy90(bbox, nQuarter, ccdDim)
    713 546bbd40 - displayUtils.drawBBox(bbox, origin=ccdOrigin,
    322 bde0ab27 + displayUtils.drawBBox(bbox, origin=ccdOrigin, borderWidth=0.49, ctype=ctype,
    ? +++++++++++++++++++++++++++++++
    714 546bbd40 - borderWidth=0.49, ctype=ctype, frame=frame, bin=bin)
    323 bde0ab27 + display=display, bin=binSize)
    # Label each Amp
    716 546bbd40 - ap = a.getAllPixels(isTrimmed)
    717 546bbd40 - xc, yc = (ap.getMin()[0] + ap.getMax()[0])//2, (ap.getMin()[1] +
    325 9372e552 + xc, yc = (ampbbox.getMin()[0] + ampbbox.getMax()[0])//2, (ampbbox.getMin()[1] +
    ? + ++++ + ++++ + ++++
    718 546bbd40 - ap.getMax()[1])//2
    326 9372e552 + ampbbox.getMax()[1])//2
    ? + ++++
    719 546bbd40 - cen = afwGeom.Point2I(xc, yc)
    # # Rotate the amp labels too # if nQuarter == 0: c, s = 1, 0 elif nQuarter == 1: c, s = 0, -1 elif nQuarter == 2: c, s = -1, 0 elif nQuarter == 3: c, s = 0, 1 c, s = 1, 0
    732 546bbd40 - ccdHeight = ccd.getAllPixels(isTrimmed).getHeight()
    ? ^^^^^^^^^ --------------
    339 9372e552 + ccdHeight = ccdBbox.getHeight()
    ? ^^^
    733 546bbd40 - ccdWidth = ccd.getAllPixels(isTrimmed).getWidth()
    ? ^^^^^^^^^ --------------
    340 9372e552 + ccdWidth = ccdBbox.getWidth()
    ? ^^^ xc -= 0.5*ccdHeight yc -= 0.5*ccdWidth xc, yc = 0.5*ccdHeight + c*xc + s*yc, 0.5*ccdWidth + -s*xc + c*yc if ccdOrigin: xc += ccdOrigin[0] yc += ccdOrigin[1]
    349 bde0ab27 + display.dot(str(amp.getName()), xc/binSize, yc/binSize, textAngle=nQuarter*90)
    743 546bbd40 - ds9.dot(str(ccd.findAmp(cen).getId().getSerial()), xc/bin, yc/bin, frame=frame)
    744 61a76714 -
    745 546bbd40 - displayUtils.drawBBox(ccd.getAllPixels(isTrimmed), origin=ccdOrigin,
    ? ^^^^^^^^^ --------------
    351 9372e552 + displayUtils.drawBBox(ccdBbox, origin=ccdOrigin,
    ? ^^^
    746 546bbd40 - borderWidth=0.49, ctype=ds9.MAGENTA, frame=frame, bin=bin)
    ? ^ ^ ^^ ^^ ^^ ^^
    352 bde0ab27 + borderWidth=0.49, ctype=afwDisplay.MAGENTA, display=display, bin=binSize)
    ? ^^^^^ ^^^^ ^^^^^ ^ ^^^^^ ^ ++++
    748 426eecd3 - def makeImageFromRaft(raft, imageSource=ButlerImage(), raftCenter=None,
    354 bde0ab27 + def showAmp(amp, imageSource=FakeImageDataSource(isTrimmed=False), display=None, overlay=True,
    749 97dea9da - imageFactory=afwImage.ImageU, bin=1):
    ? ---------- -------
    355 bde0ab27 + imageFactory=afwImage.ImageU):
    750 61a76714 - """Make an Image of a Raft"""
    356 bde0ab27 + """!Show an amp in an image display
    752 97dea9da - if raftCenter is None:
    753 3b1e6cc7 - raftCenter = afwGeom.Point2I(raft.getAllPixels().getDimensions()[0]//2,
    754 1dc2df23 - raft.getAllPixels().getDimensions()[1]//2)
    358 545f4dc9 + @param[in] amp amp record to use in display
    359 545f4dc9 + @param[in] imageSource Source for getting the amp image. Must have a getAmpImage method.
    360 bde0ab27 + @param[in] display image display to use
    361 545f4dc9 + @param[in] overlay Overlay bounding boxes?
    362 545f4dc9 + @param[in] imageFactory Type of image to display (only used if ampImage is None)
    363 f6e303b1 + """
    365 bde0ab27 + if not display:
    366 bde0ab27 + display = afwDisplay.getDisplay()
    756 3b1e6cc7 - dimensions = afwGeom.Extent2I(raft.getAllPixels().getDimensions()[0]//bin,
    757 3b1e6cc7 - raft.getAllPixels().getDimensions()[1]//bin)
    758 3b1e6cc7 - raftImage = imageFactory(dimensions)
    368 ff18f270 + ampImage = imageSource.getAmpImage(amp, imageFactory=imageFactory)
    369 ff18f270 + ampImSize = ampImage.getDimensions()
    370 9372e552 + title = amp.getName()
    371 bde0ab27 + display.mtv(ampImage, title=title)
    372 9372e552 + if overlay:
    373 bde0ab27 + with afwDisplay.Buffering():
    374 ff18f270 + if amp.getHasRawInfo() and ampImSize == amp.getRawBBox().getDimensions():
    375 bde0ab27 + bboxes = [(amp.getRawBBox(), 0.49, afwDisplay.GREEN),]
    376 9372e552 + xy0 = bboxes[0][0].getMin()
    377 bde0ab27 + bboxes.append((amp.getRawHorizontalOverscanBBox(), 0.49, afwDisplay.RED))
    378 bde0ab27 + bboxes.append((amp.getRawDataBBox(), 0.49, afwDisplay.BLUE))
    379 bde0ab27 + bboxes.append((amp.getRawPrescanBBox(), 0.49, afwDisplay.YELLOW))
    380 bde0ab27 + bboxes.append((amp.getRawVerticalOverscanBBox(), 0.49, afwDisplay.MAGENTA))
    760 61a76714 - for det in raft:
    761 61a76714 - ccd = cameraGeom.cast_Ccd(det)
    762 61a76714 -
    763 61a76714 - bbox = ccd.getAllPixels(True)
    764 3b1e6cc7 - cen = ccd.getCenterPixel()
    765 1dc2df23 - origin = afwGeom.Point2I(cen)
    766 1dc2df23 - origin -= bbox.getDimensions()/2
    767 1dc2df23 - origin += afwGeom.Extent2I(raftCenter)
    768 3b1e6cc7 - dims = afwGeom.Extent2I(bbox.getDimensions()[0]//bin,
    769 1dc2df23 - bbox.getDimensions()[1]//bin)
    770 c9c89e06 - bbox = afwGeom.Box2I(afwGeom.Point2I((origin.getX() + bbox.getMinX())//bin,
    771 3263f939 - (origin.getY() + bbox.getMinY())//bin),
    772 3b1e6cc7 - dims)
    773 61a76714 -
    774 a8f86353 - ccdImage = raftImage.Factory(raftImage, bbox, afwImage.LOCAL)
    775 08da793e -
    776 08da793e - dataImage = makeImageFromCcd(ccd, imageSource, imageFactory=imageFactory, isTrimmed=True, bin=bin)
    777 08da793e -
    778 08da793e - if ccdImage.getDimensions() == dataImage.getDimensions():
    779 08da793e - ccdImage <<= dataImage
    780 08da793e - else:
    781 08da793e - delta = ccdImage.getDimensions() - dataImage.getDimensions()
    782 08da793e -
    783 08da793e - if imageSource.gravity == "N":
    784 08da793e - x0, y0 = delta[0]//2, delta[1]
    785 08da793e - elif imageSource.gravity == "S":
    786 08da793e - x0, y0 = delta[0]//2, 0
    787 08da793e - elif imageSource.gravity == "E":
    788 08da793e - x0, y0 = delta[0], delta[1]//2
    789 08da793e - elif imageSource.gravity == "W":
    790 08da793e - x0, y0 = 0, delta[1]//2
    else:
    382 9372e552 + bboxes = [(amp.getBBox(), 0.49, None),]
    383 9372e552 + xy0 = bboxes[0][0].getMin()
    792 08da793e - x0, y0 = delta[0]//2, delta[1]//2
    793 08da793e - subCcdImage = ccdImage.Factory(ccdImage, afwGeom.BoxI(afwGeom.PointI(x0, y0), dataImage.getDimensions()))
    794 08da793e - subCcdImage <<= dataImage
    795 08da793e - del subCcdImage
    797 61a76714 - return raftImage
    385 9372e552 + for bbox, borderWidth, ctype in bboxes:
    386 9372e552 + if bbox.isEmpty():
    387 9372e552 + continue
    388 9372e552 + bbox = afwGeom.Box2I(bbox)
    389 9372e552 + bbox.shift(-afwGeom.ExtentI(xy0))
    390 bde0ab27 + displayUtils.drawBBox(bbox, borderWidth=borderWidth, ctype=ctype, display=display)
    799 426eecd3 - def showRaft(raft, imageSource=ButlerImage(), raftOrigin=None, frame=None, overlay=True, bin=1):
    800 993791af - """Show a Raft on ds9.
    392 bde0ab27 + def showCcd(ccd, imageSource=FakeImageDataSource(), display=None, overlay=True,
    393 bde0ab27 + imageFactory=afwImage.ImageU, binSize=1, inCameraCoords=False):
    394 bde0ab27 + """!Show a CCD on display
    802 97dea9da - If imageSource isn't None, create an image using the images specified by imageSource"""
    803 61a76714 -
    804 08da793e - if raftOrigin is None:
    396 545f4dc9 + @param[in] ccd Detector to use in display
    397 545f4dc9 + @param[in] imageSource Source for producing images to display. Must have a getCcdImage method.
    398 bde0ab27 + @param[in] display image display to use
    399 545f4dc9 + @param[in] overlay Show amp bounding boxes on the displayed image?
    400 545f4dc9 + @param[in] imageFactory The image factory to use in generating the images.
    401 545f4dc9 + @param[in] binSize Binning factor
    402 545f4dc9 + @param[in] inCameraCoords Show the Detector in camera coordinates?
    403 f6e303b1 + """
    805 08da793e - raftOrigin = afwGeom.PointD(0, 0)
    ? ^^^^^^^^ ^ -
    404 9372e552 + ccdOrigin = afwGeom.Point2I(0,0)
    ? ^^^ ^^
    806 08da793e - else:
    807 08da793e - raftOrigin = raft.getPositionFromPixel(afwGeom.PointD(0, 0)).getMm()
    405 9372e552 + nQuarter = 0
    406 ff18f270 + ccdImage = imageSource.getCcdImage(ccd, imageFactory=imageFactory, binSize=binSize)
    408 ff18f270 + ccdBbox = ccdImage.getBBox()
    409 ff18f270 + if ccdBbox.getDimensions() == ccd.getBBox().getDimensions():
    410 ff18f270 + isTrimmed = True
    809 c9c89e06 - raftCenter = afwGeom.Point2I(raft.getAllPixels().getDimensions()/2)
    810 08da793e - raftCenter += afwGeom.ExtentI(int(raftOrigin[0]), int(raftOrigin[1]))
    811 61a76714 -
    812 fd901390 - if imageSource is None:
    813 fd901390 - raftImage = None
    814 97dea9da - elif isinstance(imageSource, GetCcdImage):
    815 97dea9da - raftImage = makeImageFromRaft(raft, imageSource=imageSource, raftCenter=raftCenter, bin=bin)
    else:
    817 97dea9da - raftImage = imageSource
    412 ff18f270 + isTrimmed = False
    819 fd901390 - if raftImage:
    820 61a76714 - ds9.mtv(raftImage, frame=frame, title=raft.getId().getName())
    414 9372e552 + if inCameraCoords:
    415 1ff73d16 + nQuarter = ccd.getOrientation().getNQuarter()
    416 9372e552 + ccdImage = afwMath.rotateImageBy90(ccdImage, nQuarter)
    417 9372e552 + title = ccd.getName()
    418 9372e552 + if isTrimmed:
    419 9372e552 + title += "(trimmed)"
    420 bde0ab27 + display.mtv(ccdImage, title=title)
    822 993791af - if not raftImage and not overlay:
    823 993791af - return
    422 9372e552 + if overlay:
    423 bde0ab27 + overlayCcdBoxes(ccd, ccdBbox, nQuarter, isTrimmed, ccdOrigin, display, binSize)
    425 20d15f9f + def getCcdInCamBBoxList(ccdList, binSize, pixelSize_o, origin):
    426 545f4dc9 + """!Get the bounding boxes of a list of Detectors within a camera sized pixel grid
    825 546bbd40 - with ds9.Buffering():
    826 546bbd40 - for det in raft:
    827 546bbd40 - ccd = cameraGeom.cast_Ccd(det)
    829 546bbd40 - bbox = ccd.getAllPixels(True)
    830 08da793e - origin = ccd.getPositionFromPixel(afwGeom.PointD(0, 0)).getMm()
    831 08da793e - #origin -= afwGeom.ExtentD(raftCenter)
    428 545f4dc9 + @param[in] ccdList List of Detector
    429 545f4dc9 + @param[in] binSize Binning factor
    430 545f4dc9 + @param[in] pixelSize_o Size of the pixel in mm.
    431 545f4dc9 + @param[in] origin origin of the camera pixel grid in pixels
    432 f6e303b1 + @return a list of bounding boxes in camera pixel coordinates
    433 f6e303b1 + """
    434 20d15f9f + boxList = []
    435 20d15f9f + for ccd in ccdList:
    436 20d15f9f + if not pixelSize_o == ccd.getPixelSize():
    437 bde0ab27 + raise RuntimeError(
    438 bde0ab27 + "Cameras with detectors with different pixel scales are not currently supported")
    833 546bbd40 - if True:
    834 546bbd40 - name = ccd.getId().getName()
    835 546bbd40 - else:
    836 546bbd40 - name = str(ccd.getCenter())
    440 20d15f9f + dbbox = afwGeom.Box2D()
    441 20d15f9f + for corner in ccd.getCorners(FOCAL_PLANE):
    442 20d15f9f + dbbox.include(corner)
    443 20d15f9f + llc = dbbox.getMin()
    444 20d15f9f + nQuarter = ccd.getOrientation().getNQuarter()
    445 20d15f9f + cbbox = ccd.getBBox()
    446 f6e303b1 + ex = cbbox.getDimensions().getX()//binSize
    447 f6e303b1 + ey = cbbox.getDimensions().getY()//binSize
    448 20d15f9f + bbox = afwGeom.Box2I(cbbox.getMin(), afwGeom.Extent2I(int(ex), int(ey)))
    449 20d15f9f + bbox = rotateBBoxBy90(bbox, nQuarter, bbox.getDimensions())
    450 bde0ab27 + bbox.shift(afwGeom.Extent2I(int(llc.getX()//pixelSize_o.getX()/binSize),
    451 bde0ab27 + int(llc.getY()//pixelSize_o.getY()/binSize)))
    452 20d15f9f + bbox.shift(afwGeom.Extent2I(-int(origin.getX()//binSize), -int(origin.getY())//binSize))
    453 20d15f9f + boxList.append(bbox)
    454 20d15f9f + return boxList
    838 546bbd40 - ds9.dot(name, (origin[0] + 0.5*bbox.getWidth())/bin,
    839 546bbd40 - (origin[1] + 0.4*bbox.getHeight())/bin, frame=frame)
    456 20d15f9f + def getCameraImageBBox(camBbox, pixelSize, bufferSize):
    457 545f4dc9 + """!Get the bounding box of a camera sized image in pixels
    841 546bbd40 - showCcd(ccd, None, isTrimmed=True, frame=frame, ccdOrigin=origin, overlay=overlay, bin=bin)
    459 545f4dc9 + @param[in] camBbox Camera bounding box in focal plane coordinates (mm)
    460 545f4dc9 + @param[in] pixelSize Size of a detector pixel in mm
    461 545f4dc9 + @param[in] bufferSize Buffer around edge of image in pixels
    462 d00b5062 + @return the resulting bounding box
    463 f6e303b1 + """
    464 bde0ab27 + pixMin = afwGeom.Point2I(int(camBbox.getMinX()//pixelSize.getX()),
    465 bde0ab27 + int(camBbox.getMinY()//pixelSize.getY()))
    466 bde0ab27 + pixMax = afwGeom.Point2I(int(camBbox.getMaxX()//pixelSize.getX()),
    467 bde0ab27 + int(camBbox.getMaxY()//pixelSize.getY()))
    468 20d15f9f + retBox = afwGeom.Box2I(pixMin, pixMax)
    469 20d15f9f + retBox.grow(bufferSize)
    470 20d15f9f + return retBox
    843 97dea9da - def makeImageFromCamera(camera, imageSource=None, imageFactory=afwImage.ImageU, bin=1):
    472 ff18f270 + def makeImageFromCamera(camera, detectorNameList=None, background=numpy.nan, bufferSize=10,
    473 ff18f270 + imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageU, binSize=1):
    844 61a76714 - """Make an Image of a Camera"""
    ? ---
    474 545f4dc9 + """!Make an Image of a Camera
    ? +
    846 a8f86353 - cameraImage = imageFactory(camera.getAllPixels().getDimensions()/bin)
    847 61a76714 - for det in camera:
    848 61a76714 - raft = cameraGeom.cast_Raft(det);
    849 97dea9da - bbox = raft.getAllPixels()
    850 e193729a - origin = camera.getCenterPixel() + afwGeom.Extent2D(raft.getCenterPixel()) - \
    851 a8f86353 - afwGeom.Extent2D(bbox.getWidth()/2, bbox.getHeight()/2)
    852 3b1e6cc7 - dimensions = afwGeom.Extent2I(bbox.getDimensions()[0]//bin,
    853 3b1e6cc7 - bbox.getDimensions()[1]//bin)
    854 3b1e6cc7 - bbox = afwGeom.Box2I(afwGeom.Point2I(int((origin.getX() + bbox.getMinX())//bin),
    855 3b1e6cc7 - int((origin.getY() + bbox.getMinY())//bin)),
    856 3b1e6cc7 - dimensions)
    476 545f4dc9 + @param[in] camera Camera object to use to make the image
    477 545f4dc9 + @param[in] detectorNameList List of detector names to use in building the image.
    478 d00b5062 + Use all Detectors if None.
    479 545f4dc9 + @param[in] background Value to use where there is no Detector
    480 545f4dc9 + @param[in] bufferSize Size of border in binned pixels to make around the camera image
    481 545f4dc9 + @param[in] imageSource Source to get ccd images. Must have a getCcdImage method
    482 545f4dc9 + @param[in] imageFactory Type of image to build
    483 545f4dc9 + @param[in] binSize bin factor
    484 f6e303b1 + @return an image of the camera
    485 f6e303b1 + """
    486 20d15f9f + if detectorNameList is None:
    487 20d15f9f + ccdList = camera
    488 20d15f9f + else:
    489 20d15f9f + ccdList = [camera[name] for name in detectorNameList]
    491 20d15f9f + if detectorNameList is None:
    492 20d15f9f + camBbox = camera.getFpBBox()
    493 20d15f9f + else:
    494 20d15f9f + camBbox = afwGeom.Box2D()
    495 20d15f9f + for detName in detectorNameList:
    496 20d15f9f + for corner in camera[detName].getCorners(FOCAL_PLANE):
    497 20d15f9f + camBbox.include(corner)
    498 ff18f270 +
    499 f6e303b1 + pixelSize_o = camera[camera.getNameIter().next()].getPixelSize()
    500 cb8ea286 + camBbox = getCameraImageBBox(camBbox, pixelSize_o, bufferSize*binSize)
    501 9372e552 + origin = camBbox.getMin()
    502 bde0ab27 +
    503 ff18f270 + camIm = imageFactory(int(math.ceil(camBbox.getDimensions().getX()/binSize)),
    504 ff18f270 + int(math.ceil(camBbox.getDimensions().getY()/binSize)))
    505 20d15f9f + boxList = getCcdInCamBBoxList(ccdList, binSize, pixelSize_o, origin)
    506 20d15f9f + for det, bbox in itertools.izip(ccdList, boxList):
    507 ff18f270 + im = imageSource.getCcdImage(det, imageFactory, binSize)
    508 1ff73d16 + nQuarter = det.getOrientation().getNQuarter()
    509 9372e552 + im = afwMath.rotateImageBy90(im, nQuarter)
    858 a8f86353 - im = cameraImage.Factory(cameraImage, bbox, afwImage.LOCAL)
    ? --- --- --- ---
    510 9372e552 + imView = camIm.Factory(camIm, bbox, afwImage.LOCAL)
    ? ++++
    511 9372e552 + imView <<= im
    860 fd901390 - im <<= makeImageFromRaft(raft, imageSource,
    861 c2030ec8 - raftCenter=None,
    513 9372e552 + return camIm
    514 9372e552 +
    515 bde0ab27 + def showCamera(camera, imageSource=FakeImageDataSource(), imageFactory=afwImage.ImageU,
    516 bde0ab27 + detectorNameList=None, binSize=10, bufferSize=10, frame=None, overlay=True, title="",
    517 bde0ab27 + ctype=afwDisplay.GREEN, textSize=1.25, originAtCenter=True, display=None, **kwargs):
    518 bde0ab27 + """!Show a Camera on display, with the specified display
    519 545f4dc9 +
    520 545f4dc9 + The rotation of the sensors is snapped to the nearest multiple of 90 deg.
    521 545f4dc9 + Also note that the pixel size is constant over the image array. The lower left corner (LLC) of each
    522 545f4dc9 + sensor amp is snapped to the LLC of the pixel containing the LLC of the image.
    523 39ce81bb + if overlay show the IDs and detector boundaries
    524 545f4dc9 +
    525 545f4dc9 + @param[in] camera Camera to show
    526 545f4dc9 + @param[in] imageSource Source to get Ccd images from. Must have a getCcdImage method.
    527 545f4dc9 + @param[in] imageFactory Type of image to make
    528 545f4dc9 + @param[in] detectorNameList List of names of Detectors to use. If None use all
    529 545f4dc9 + @param[in] binSize bin factor
    530 545f4dc9 + @param[in] bufferSize size of border in binned pixels to make around camera image.
    531 bde0ab27 + @param[in] frame specify image display (@deprecated; new code should use display)
    532 545f4dc9 + @param[in] overlay Overlay Detector IDs and boundaries?
    533 bde0ab27 + @param[in] title Title in display
    534 545f4dc9 + @param[in] ctype Color to use when drawing Detector boundaries
    535 545f4dc9 + @param[in] textSize Size of detector labels
    536 bde0ab27 + @param[in] originAtCenter Put origin of the camera WCS at the center of the image? Else it will be LL
    537 bde0ab27 + @param[in] display image display on which to display
    538 545f4dc9 + @param[in] **kwargs all remaining keyword arguments are passed to makeImageFromCamera
    539 d00b5062 + @return the mosaic image
    540 f6e303b1 + """
    541 bde0ab27 + display = displayUtils.getDisplay(display, frame)
    542 bde0ab27 +
    543 cb8ea286 + if binSize < 1:
    544 cb8ea286 + binSize = 1
    545 20d15f9f + cameraImage = makeImageFromCamera(camera, detectorNameList=detectorNameList, bufferSize=bufferSize,
    862 97dea9da - imageFactory=imageFactory, bin=bin)
    ? ^
    546 bde0ab27 + imageSource=imageSource, imageFactory=imageFactory, binSize=binSize,
    ? ++++++++++++++++++++++++++++++ ++++ ^^^^^
    863 7250716d - serial = raft.getId().getSerial()
    864 e193729a - im += serial if serial > 0 else 0
    547 bde0ab27 + **kwargs)
    548 f6e303b1 +
    549 20d15f9f + if detectorNameList is None:
    550 f6e303b1 + ccdList = [camera[name] for name in camera.getNameIter()]
    551 20d15f9f + else:
    552 20d15f9f + ccdList = [camera[name] for name in detectorNameList]
    553 20d15f9f +
    554 20d15f9f + if detectorNameList is None:
    555 20d15f9f + camBbox = camera.getFpBBox()
    556 20d15f9f + else:
    557 20d15f9f + camBbox = afwGeom.Box2D()
    558 20d15f9f + for detName in detectorNameList:
    559 20d15f9f + for corner in camera[detName].getCorners(FOCAL_PLANE):
    560 20d15f9f + camBbox.include(corner)
    561 23a9616a + pixelSize = ccdList[0].getPixelSize()
    562 23a9616a + if originAtCenter:
    563 8b4a97d8 + #Can't divide SWIGGED extent type things when division is imported
    564 8b4a97d8 + #from future. This is DM-83
    565 8b4a97d8 + ext = cameraImage.getBBox().getDimensions()
    566 8b4a97d8 +
    567 8b4a97d8 + wcsReferencePixel = afwGeom.PointI(ext.getX()//2, ext.getY()//2)
    568 23a9616a + else:
    569 23a9616a + wcsReferencePixel = afwGeom.Point2I(0,0)
    570 23a9616a + wcs = makeFocalPlaneWcs(pixelSize*binSize, wcsReferencePixel)
    571 23a9616a + if title == "":
    572 23a9616a + title = camera.getName()
    573 bde0ab27 + display.mtv(cameraImage, title=title, wcs=wcs)
    574 d5210db5 +
    575 20d15f9f + if overlay:
    576 bde0ab27 + with afwDisplay.Buffering():
    577 cb8ea286 + camBbox = getCameraImageBBox(camBbox, pixelSize, bufferSize*binSize)
    578 726f34b1 + bboxList = getCcdInCamBBoxList(ccdList, binSize, pixelSize, camBbox.getMin())
    579 726f34b1 + for bbox, ccd in itertools.izip(bboxList, ccdList):
    580 726f34b1 + nQuarter = ccd.getOrientation().getNQuarter()
    581 726f34b1 + # borderWidth to 0.5 to align with the outside edge of the pixel
    582 bde0ab27 + displayUtils.drawBBox(bbox, borderWidth=0.5, ctype=ctype, display=display)
    583 726f34b1 + dims = bbox.getDimensions()
    584 bde0ab27 + display.dot(ccd.getName(), bbox.getMinX()+dims.getX()/2, bbox.getMinY()+dims.getY()/2,
    585 bde0ab27 + ctype=ctype, size=textSize, textAngle=nQuarter*90)
    return cameraImage
    589 23a9616a + def makeFocalPlaneWcs(pixelSize, referencePixel):
    868 426eecd3 - def showCamera(camera, imageSource=ButlerImage(), imageFactory=afwImage.ImageF,
    869 08da793e - bin=1, border=5, frame=None, overlay=True, title="", ctype=ds9.GREEN, names=False):
    870 08da793e - """Show a Camera on ds9 (with the specified frame); if overlay show the IDs and detector boundaries
    871 fd901390 -
    872 fd901390 - If imageSource is provided its getImage method will be called to return a CCD image (e.g. a
    873 fd901390 - cameraGeom.GetCcdImage object); if it is "", an image will be created based on the properties
    874 fd901390 - of the detectors"""
    875 08da793e - #
    876 08da793e - # Figure out how big an image I need, and where the CCDs fit
    877 08da793e - #
    878 08da793e - cameraBbox = afwGeom.BoxI()
    879 08da793e - ccdBboxes = {}
    880 08da793e - for raft in camera:
    881 08da793e - raft = cameraGeom.cast_Raft(raft)
    882 08da793e - for ccd in raft:
    883 08da793e - ccd = cameraGeom.cast_Ccd(ccd)
    884 08da793e - ccd.setTrimmed(True)
    885 08da793e -
    886 08da793e - width, height = ccd.getAllPixels(True).getDimensions()
    887 61a76714 -
    888 08da793e - bbox = afwGeom.BoxI()
    889 08da793e - for x, y in ((0.0,0.0), (0.0, height - 1), (width - 1, height - 1), (width - 1, 0.0), (0.0, 0.0)):
    890 fb65d5ca - position = ccd.getPositionFromPixel(afwGeom.Point2D(x,y)).getPixels(ccd.getPixelSize())
    891 08da793e - bbox.include(afwGeom.PointI(int(position.getX()//bin), int(position.getY()//bin)))
    892 61a76714 -
    893 08da793e - cameraBbox.include(bbox)
    894 08da793e - ccdBboxes[ccd.getId().getSerial()] = bbox
    895 61a76714 -
    896 08da793e - cameraBbox.include(afwGeom.PointI(-border, -border))
    897 08da793e - cameraBbox.grow(afwGeom.ExtentI( border, border))
    898 61a76714 -
    899 370e2d32 - cameraImage = imageFactory(cameraBbox)
    900 08da793e - cameraImage.set(imageSource.background if imageSource else np.nan)
    901 546bbd40 -
    902 08da793e - for raft in camera:
    903 08da793e - raft = cameraGeom.cast_Raft(raft)
    904 08da793e - for ccd in raft:
    905 08da793e - ccd = cameraGeom.cast_Ccd(ccd)
    906 2ebad60d -
    907 08da793e - serialNo = ccd.getId().getSerial()
    908 08da793e - ccdImage = cameraImage.Factory(cameraImage, ccdBboxes[serialNo], afwImage.PARENT)
    909 08da793e - dataImage = makeImageFromCcd(ccd, imageSource, imageFactory=imageFactory, isTrimmed=True, bin=bin)
    910 61a76714 -
    911 08da793e - if ccdImage.getDimensions() == dataImage.getDimensions():
    912 08da793e - ccdImage <<= dataImage
    913 08da793e - else:
    914 08da793e - delta = ccdImage.getDimensions() - dataImage.getDimensions()
    915 08da793e -
    916 08da793e - if imageSource:
    917 08da793e - if imageSource.gravity == "N":
    918 08da793e - x0, y0 = delta[0]//2, delta[1]
    919 08da793e - elif imageSource.gravity == "S":
    920 08da793e - x0, y0 = delta[0]//2, 0
    921 08da793e - elif imageSource.gravity == "E":
    922 08da793e - x0, y0 = delta[0], delta[1]//2
    923 08da793e - elif imageSource.gravity == "W":
    924 08da793e - x0, y0 = 0, delta[1]//2
    925 08da793e - else:
    926 08da793e - x0, y0 = delta[0]//2, delta[1]//2
    927 08da793e - else:
    928 08da793e - assert bin > 1
    929 08da793e - x0, y0 = 0, 0 # rounding error in binning
    930 fb65d5ca -
    931 fb65d5ca - subCcdImage = ccdImage.Factory(ccdImage,
    932 fb65d5ca - afwGeom.BoxI(afwGeom.PointI(x0, y0), dataImage.getDimensions()))
    933 08da793e - subCcdImage <<= dataImage
    934 08da793e - del subCcdImage
    935 08da793e - #
    936 08da793e - # We've got the image, add a WCS
    937 08da793e - #
    938 08da793e - if frame is not None:
    939 08da793e - wcs = makeFocalPlaneWcs(camera)
    940 08da793e -
    941 08da793e - ds9.mtv(cameraImage, title=title, frame=frame, wcs=wcs)
    942 08da793e -
    943 08da793e - if overlay:
    944 08da793e - xy0 = afwGeom.ExtentI(cameraImage.getXY0())
    945 08da793e -
    946 08da793e - with ds9.Buffering():
    947 08da793e - for raft in camera:
    948 08da793e - raft = cameraGeom.cast_Raft(raft)
    949 08da793e - for ccd in raft:
    950 08da793e - ccd = cameraGeom.cast_Ccd(ccd)
    951 08da793e -
    952 08da793e - serialNo = ccd.getId().getSerial()
    953 08da793e -
    954 08da793e - bbox = ccdBboxes[serialNo]
    955 08da793e - displayUtils.drawBBox(bbox, origin=-xy0, borderWidth=0.49,
    956 08da793e - ctype=ctype, frame=frame)
    957 08da793e -
    958 08da793e - xy = [0, 0]
    959 08da793e - for i in range(2):
    960 08da793e - xy[i] = 0.5*(bbox.getMin()[i] + bbox.getMax()[i]) - xy0[i]
    961 08da793e -
    962 08da793e - ds9.dot(ccd.getId().getName() if names else str(serialNo), *xy,
    963 08da793e - ctype=ctype, frame=frame)
    964 08da793e -
    965 51d10d66 - return cameraImage
    966 51d10d66 -
    967 08da793e - def makeFocalPlaneWcs(camera):
    968 08da793e - """Make a WCS for the focal plane geometry (i.e. returning positions in "mm")"""
    ? ---
    590 545f4dc9 + """!Make a WCS for the focal plane geometry (i.e. returning positions in "mm")
    ? +
    969 08da793e - import lsst.daf.base as dafBase
    971 08da793e - ccd = cameraGeom.cast_Ccd(list(cameraGeom.cast_Raft(list(camera)[0]))[0]) # some random CCD
    592 545f4dc9 + @param[in] pixelSize Size of the image pixels in physical units
    593 545f4dc9 + @param[in] referencePixel Pixel for origin of WCS
    594 23a9616a + @return Wcs object for mapping between pixels and focal plane.
    595 23a9616a + """
    md = dafBase.PropertySet()
    598 23a9616a + if referencePixel is None:
    974 08da793e - pix = afwGeom.PointD(0,0)
    ? ^
    599 23a9616a + referencePixel = afwGeom.PointD(0,0)
    ? ^^^^^^^^^^^^^^ ++
    975 08da793e - fpPos = ccd.getPositionFromPixel(pix).getMm()
    976 2ebad60d -
    for i in range(2):
    978 08da793e - md.set("CRPOS%d" % i, pix[i])
    601 23a9616a + md.set("CRPIX%d"%(i+1), referencePixel[i])
    979 08da793e - md.set("CRVAL%d" % i, fpPos[i])
    ? - ^ ^^^^^^^^
    602 23a9616a + md.set("CRVAL%d"%(i+1), 0.)
    ? ^ +++ ^^
    980 08da793e - md.set("CDELT1", ccd.getPixelSize())
    ? ^^^^^^^^ ^^
    603 23a9616a + md.set("CDELT1", pixelSize[0])
    ? ^ ^^^
    604 23a9616a + md.set("CDELT2", pixelSize[1])
    605 f6e303b1 + md.set("CTYPE1", "CAMERA_X")
    606 f6e303b1 + md.set("CTYPE2", "CAMERA_Y")
    607 f6e303b1 + md.set("CUNIT1", "mm")
    608 f6e303b1 + md.set("CUNIT2", "mm")
    return afwImage.makeWcs(md)
    612 9372e552 + def findAmp(ccd, pixelPosition):
    984 61a76714 - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    985 61a76714 -
    986 82325a24 - def showMosaic(fileName, geomPolicy=None, camera=None,
    987 97dea9da - display=True, what=cameraGeom.Camera, id=None, overlay=False, describe=False, doTrim=False,
    988 97dea9da - imageFactory=afwImage.ImageU, bin=1, frame=None):
    989 97dea9da - """Return a mosaic for a given snapshot of the sky; if display is true, also show it on ds9
    990 993791af -
    991 993791af - The camera geometry is defined by cameraGeomPolicyFile; raft IDs etc. are drawn on ds9 if overlay is True;
    992 993791af - The camera (or raft) is described if describe is True
    993 993791af -
    994 993791af - You may set what to a type (e.g. cameraGeom.Ccd) to display that type; if provided id will be obeyed
    995 993791af -
    996 d30faf6b - If relevant (for e.g. a Ccd) doTrim is applied to the Detector.
    997 993791af - """
    998 993791af -
    999 82325a24 - if isinstance(fileName, GetCcdImage):
    1000 82325a24 - imageSource = fileName
    1001 82325a24 - elif isinstance(fileName, str):
    1002 993791af - imageSource = GetCcdImage(fileName) # object that understands the CCD <--> HDU mapping
    1003 993791af - else:
    1004 993791af - imageSource = None
    1005 82325a24 -
    1006 82325a24 - if imageSource:
    1007 82325a24 - imageSource.setTrimmed(doTrim)
    1008 993791af -
    1009 82325a24 - if not camera:
    1010 82325a24 - camera = makeCamera(geomPolicy)
    1011 993791af -
    1012 82325a24 - if what == cameraGeom.Amp:
    1013 82325a24 - if id is None:
    1014 82325a24 - ccd = makeCcd(geomPolicy)
    1015 c5e868b7 - else:
    1016 82325a24 - ccd = findCcd(camera, id[0])
    1017 82325a24 - amp = [a for a in ccd if a.getId() == id[1]][0]
    1018 82325a24 -
    1019 82325a24 - if not amp:
    1020 82325a24 - raise RuntimeError, "Failed to find Amp %s" % id
    1021 82325a24 -
    1022 82325a24 - ccd.setTrimmed(doTrim)
    1023 82325a24 -
    1024 97dea9da - outImage = makeImageFromCcd(ccd, imageSource, amp=amp, imageFactory=imageFactory, bin=bin)
    1025 82325a24 - if display:
    1026 97dea9da - showCcd(ccd, outImage, amp=amp, overlay=overlay, frame=frame, bin=bin)
    1027 82325a24 - elif what == cameraGeom.Ccd:
    1028 82325a24 - if id is None:
    1029 c5e868b7 - ccd = makeCcd(geomPolicy)
    1030 82325a24 - else:
    1031 82325a24 - ccd = findCcd(camera, id)
    1032 c5e868b7 -
    1033 993791af - if not ccd:
    1034 993791af - raise RuntimeError, "Failed to find Ccd %s" % id
    1035 993791af -
    1036 993791af - ccd.setTrimmed(doTrim)
    1037 993791af -
    1038 97dea9da - outImage = makeImageFromCcd(ccd, imageSource, imageFactory=imageFactory, bin=bin)
    1039 993791af - if display:
    1040 97dea9da - showCcd(ccd, outImage, overlay=overlay, frame=frame, bin=bin)
    1041 993791af - elif what == cameraGeom.Raft:
    1042 c5e868b7 - if id:
    1043 c5e868b7 - raft = findRaft(camera, id)
    1044 c5e868b7 - else:
    1045 c5e868b7 - raft = makeRaft(geomPolicy)
    1046 993791af - if not raft:
    1047 993791af - raise RuntimeError, "Failed to find Raft %s" % id
    1048 993791af -
    1049 97dea9da - outImage = makeImageFromRaft(raft, imageSource, imageFactory=imageFactory, bin=bin)
    1050 993791af - if display:
    1051 97dea9da - showRaft(raft, outImage, overlay=overlay, frame=frame, bin=bin)
    1052 993791af -
    1053 993791af - if describe:
    1054 993791af - print describeRaft(raft)
    1055 82325a24 - elif what == cameraGeom.Camera:
    1056 97dea9da - outImage = makeImageFromCamera(camera, imageSource, imageFactory=imageFactory, bin=bin)
    1057 993791af - if display:
    1058 97dea9da - showCamera(camera, outImage, overlay=overlay, frame=frame, bin=bin)
    1059 993791af -
    1060 993791af - if describe:
    1061 993791af - print describeCamera(camera)
    1062 82325a24 - else:
    1063 82325a24 - raise RuntimeError, ("I don't know how to display %s" % what)
    1064 993791af -
    1065 97dea9da - return outImage
    1066 97dea9da -
    1067 993791af - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    1068 993791af -
    1069 61a76714 - def describeRaft(raft, indent=""):
    1070 61a76714 - """Describe an entire Raft"""
    1071 61a76714 - descrip = []
    1072 61a76714 -
    1073 6b9ab890 - size = raft.getSize().getMm()
    1074 61a76714 - descrip.append("%sRaft \"%s\", %gx%g BBox %s" % (indent, raft.getId(),
    1075 61a76714 - size[0], size[1], raft.getAllPixels()))
    1076 61a76714 -
    1077 61a76714 - for d in cameraGeom.cast_Raft(raft):
    1078 61a76714 - cenPixel = d.getCenterPixel()
    1079 6b9ab890 - cen = d.getCenter().getMm()
    1080 61a76714 -
    1081 61a76714 - descrip.append("%sCcd: %s (%5d, %5d) %s (%7.1f, %7.1f)" % \
    1082 61a76714 - ((indent + " "),
    1083 61a76714 - d.getAllPixels(True), cenPixel[0], cenPixel[1],
    1084 61a76714 - cameraGeom.ReadoutCorner(d.getOrientation().getNQuarter()), cen[0], cen[1]))
    1085 61a76714 -
    1086 61a76714 - return "\n".join(descrip)
    1087 61a76714 -
    1088 61a76714 - def describeCamera(camera):
    1089 61a76714 - """Describe an entire Camera"""
    1090 61a76714 - descrip = []
    1091 61a76714 -
    1092 6b9ab890 - size = camera.getSize().getMm()
    1093 61a76714 - descrip.append("Camera \"%s\", %gx%g BBox %s" % \
    1094 61a76714 - (camera.getId(), size[0], size[1], camera.getAllPixels()))
    1095 61a76714 -
    1096 61a76714 - for raft in camera:
    1097 61a76714 - descrip.append(describeRaft(raft, " "))
    1098 61a76714 -
    1099 61a76714 - return "\n".join(descrip)
    1100 993791af -
    1101 993791af - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    1102 993791af -
    1103 0f6071dc - def findAmp(parent, ccdId, ix, iy):
    1104 0f6071dc - """Find the Amp with the specified Id within the composite"""
    ? ^^ ---
    613 545f4dc9 + """!Find the Amp with the specified pixel position within the composite
    ? + ^^^^^^^^^^^^^^
    1106 0f6071dc - ccd = findCcd(parent, ccdId)
    615 545f4dc9 + @param[in] ccd Detector to look in
    616 545f4dc9 + @param[in] pixelPosition Point2I containing the pixel position
    617 545f4dc9 + @return Amp record in which pixelPosition falls or None if no Amp found.
    618 f6e303b1 + """
    619 0f6071dc +
    for amp in ccd:
    1108 0f6071dc - if amp.getId().getIndex() == (ix, iy):
    621 9372e552 + if amp.getBBox().contains(pixelPosition):
    return amp return None
    1112 0f6071dc -
    1113 993791af - def findCcd(parent, id):
    1114 993791af - """Find the Ccd with the specified Id within the composite"""
    1115 993791af -
    1116 993791af - if isinstance(parent, cameraGeom.Camera):
    1117 993791af - for d in parent:
    1118 993791af - ccd = findCcd(cameraGeom.cast_Raft(d), id)
    1119 993791af - if ccd:
    1120 993791af - return ccd
    1121 993791af - elif isinstance(parent, cameraGeom.Raft):
    1122 73bee471 - try:
    1123 73bee471 - return cameraGeom.cast_Ccd(parent.findDetector(id))
    1124 73bee471 - except:
    1125 73bee471 - pass
    1126 993791af - else:
    1127 993791af - if parent.getId() == id:
    1128 993791af - return cameraGeom.cast_Ccd(parent)
    1129 993791af -
    1130 993791af - return None
    1131 993791af -
    1132 993791af - def findRaft(parent, id):
    1133 993791af - """Find the Raft with the specified Id within the composite"""
    1134 993791af -
    1135 993791af - if isinstance(parent, cameraGeom.Camera):
    1136 82325a24 - d = parent.findDetector(id)
    1137 82325a24 - if d:
    1138 82325a24 - return cameraGeom.cast_Raft(d)
    1139 993791af - else:
    1140 993791af - if parent.getId() == id:
    1141 993791af - return raft
    1142 993791af -
    1143 993791af - return None
    1144 d30faf6b -
    1145 d30faf6b - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    1146 d30faf6b -
    1147 5919342c - def makeDefectsFromFits(filename):
    1148 5919342c - """Create a dictionary of DefectSets from a fits file with one ccd worth
    1149 5919342c - of defects per extension.
    1150 5919342c -
    1151 b3296b1d - The dictionary is indexed by an Id object --- remember to compare by str(id) not object identity
    1152 5919342c - """
    1153 b3296b1d - if not pyfits:
    1154 624f4cc3 - raise RuntimeError("Import of pyfits failed, so makeDefectsFromFits isn't available")
    1155 b3296b1d -
    1156 5919342c - hdulist = pyfits.open(filename)
    1157 5919342c - defects = {}
    1158 5919342c - for hdu in hdulist[1:]:
    1159 5919342c - id = cameraGeom.Id(hdu.header['serial'], hdu.header['name'])
    1160 5919342c - data = hdu.data
    1161 5919342c - defectList = []
    1162 5919342c - for i in range(len(data)):
    1163 c9c89e06 - bbox = afwGeom.Box2I(
    1164 c9c89e06 - afwGeom.Point2I(int(data[i]['x0']), int(data[i]['y0'])),\
    1165 c9c89e06 - afwGeom.Extent2I(int(data[i]['width']), int(data[i]['height'])))
    1166 5919342c - defectList.append(afwImage.DefectBase(bbox))
    1167 5919342c - defects[id] = defectList
    1168 5919342c - return defects
    1169 5919342c -
    1170 5919342c - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    1171 5919342c -
    1172 d30faf6b - def makeDefects(geomPolicy):
    1173 d30faf6b - """Create a dictionary of DefectSets from a pexPolicy::Policy
    1174 d30faf6b -
    1175 08da793e - The dictionary is indexed by an Id object --- remember to compare by str(id) not object identity
    1176 d30faf6b - """
    1177 d30faf6b -
    1178 d30faf6b - defectsDict = {}
    1179 71da335b - defectListPol = geomPolicy.get("Defects")
    1180 71da335b - for raftPol in defectListPol.getArray("Raft"):
    1181 71da335b - for defectPol in raftPol.getArray("Ccd"):
    1182 71da335b - defects = afwImage.DefectSet()
    1183 71da335b - ccdId = cameraGeom.Id(defectPol.get("serial"), defectPol.get("name"))
    1184 71da335b - defectsDict[ccdId] = defects
    1185 71da335b -
    1186 71da335b - for defect in defectPol.getArray("Defect"):
    1187 71da335b - x0 = defect.get("x0")
    1188 71da335b - y0 = defect.get("y0")
    1189 71da335b -
    1190 71da335b - x1 = y1 = width = height = None
    1191 71da335b - if defect.exists("x1"):
    1192 71da335b - x1 = defect.get("x1")
    1193 71da335b - if defect.exists("y1"):
    1194 71da335b - y1 = defect.get("y1")
    1195 71da335b - if defect.exists("width"):
    1196 71da335b - width = defect.get("width")
    1197 71da335b - if defect.exists("height"):
    1198 71da335b - height = defect.get("height")
    1199 71da335b -
    1200 71da335b - if x1 is None:
    1201 71da335b - if width:
    1202 71da335b - x1 = x0 + width - 1
    1203 71da335b - else:
    1204 71da335b - raise RuntimeError, ("Defect at (%d,%d) for CCD (%s) has no x1/width" % (x0, y0, ccdId))
    1205 d30faf6b - else:
    1206 71da335b - if width:
    1207 71da335b - if x1 != x0 + width - 1:
    1208 71da335b - raise RuntimeError, \
    1209 71da335b - ("Defect at (%d,%d) for CCD (%s) has inconsistent x1/width = %d,%d" % \
    1210 71da335b - (x0, y0, ccdId, x1, width))
    1211 71da335b -
    1212 71da335b - if y1 is None:
    1213 71da335b - if height:
    1214 71da335b - y1 = y0 + height - 1
    1215 71da335b - else:
    1216 71da335b - raise RuntimeError, ("Defect at (%d,%d) for CCD (%s) has no y1/height" % (x0, y0, ccdId))
    1217 d30faf6b - else:
    1218 71da335b - if height:
    1219 71da335b - if y1 != y0 + height - 1:
    1220 71da335b - raise RuntimeError, \
    1221 71da335b - ("Defect at (%d,%d) for CCD (%s) has inconsistent y1/height = %d,%d" % \
    1222 71da335b - (x0, y0, ccdId, y1, height))
    1223 71da335b -
    1224 c9c89e06 - bbox = afwGeom.Box2I(afwGeom.Point2I(x0, y0), afwGeom.Point2I(x1, y1))
    1225 71da335b - defects.push_back(afwImage.DefectBase(bbox))
    1226 71da335b -
    1227 6c5cc14a - return defectsDict
    1228 1f7e505a -
    1229 7ee6e1e3 -
    1230 7ee6e1e3 -
    1231 7ee6e1e3 - def makeDefaultCcd(box, **kwargs):
    1232 7ee6e1e3 - """
    1233 7ee6e1e3 - Make a Ccd object for a Box2I object suitable to be used as Detector in an Exposure
    1234 7ee6e1e3 - **kwargs may specify params needed to construct ElectronicParams, Amp, and Ccd.
    1235 7ee6e1e3 - Defaults are:
    1236 7ee6e1e3 - ElectronicParams: gain (1.0), rdnoise (5.0), saturation (60000)
    1237 7ee6e1e3 - Amp: detId (1), biasSec (empty Box2I), dataSec (Box2I(img.xy0, img.getDimentions()))
    1238 7ee6e1e3 - Ccd: pixelSize (1.0)
    1239 7ee6e1e3 - This is only intented to be a useful factory for Detectors needed to test simple images.
    1240 7ee6e1e3 - """
    1241 7ee6e1e3 -
    1242 7ee6e1e3 - # build the Electronics
    1243 7ee6e1e3 - gain = kwargs.get("gain", 1.0)
    1244 7ee6e1e3 - rdnoise = kwargs.get("rdnoise", 5.0)
    1245 7ee6e1e3 - saturation = kwargs.get("saturation", 60000)
    1246 7ee6e1e3 - elec = cameraGeom.ElectronicParams(gain, rdnoise, saturation)
    1247 7ee6e1e3 -
    1248 7ee6e1e3 - # build the Amp
    1249 7ee6e1e3 - detId = kwargs.get("detId", cameraGeom.Id(1))
    1250 7ee6e1e3 - allPixels = box
    1251 7ee6e1e3 - biasSec = kwargs.get("biasSec", afwGeom.Box2I())
    1252 7ee6e1e3 - dataSec = kwargs.get("dataSec", box)
    1253 7ee6e1e3 - amp = cameraGeom.Amp(detId, allPixels, biasSec, dataSec, elec)
    1254 7ee6e1e3 -
    1255 7ee6e1e3 - # build the Ccd
    1256 7ee6e1e3 - pixelSize = kwargs.get("pixelSize", 1.0)
    1257 7ee6e1e3 - ccd = cameraGeom.Ccd(detId, pixelSize)
    1258 7ee6e1e3 - ccd.addAmp(amp)
    1259 7ee6e1e3 -
    1260 7ee6e1e3 - return ccd
    1261 7ee6e1e3 -
    1262 7ee6e1e3 -
    1263 7ee6e1e3 -
    1264 7ee6e1e3 - def makeCcdFromImage(img, **kwargs):
    1265 7ee6e1e3 - """
    1266 7ee6e1e3 - Make a Ccd object for an afw::Image object suitable to be used as Detector in an Exposure
    1267 7ee6e1e3 - **kwargs may specify params needed to construct Electronics, Amp, and Ccd. Defaults are:
    1268 7ee6e1e3 - Electronics: gain (1.0), rdnoise (5.0), saturation (60000)
    1269 7ee6e1e3 - Amp: detId (1), biasSec (empty Box2I), dataSec (Box2I(img.xy0, img.getDimentions()))
    1270 7ee6e1e3 - Ccd: pixelSize (1.0)
    1271 7ee6e1e3 - This is only intented to be a useful factory for Detectors needed to test simple images.
    1272 7ee6e1e3 - """
    1273 7ee6e1e3 -
    1274 7ee6e1e3 - allPixels = afwGeom.Box2I(img.getXY0(), img.getDimensions())
    1275 7ee6e1e3 -
    1276 7ee6e1e3 - return makeDefaultCcd(allPixels, **kwargs)
    1277 7ee6e1e3 -

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f9281729

    commit f92817291ed0bc71f7928d1fe0107134d7d4a5ac
    Author: Robert Lupton the Good 
    Date:   Sat Jun 1 10:15:19 2013 -0400
    
        Support setting Linearity coefficients in electrons or DN (#2912)
        
        N.b. changed type of threshold/maxCorrectatable from int to float to allow
        old .paf files with non-integral gains to be converted unchanged, and because
        it makes sense anyway.
    

    5919342c

    commit 5919342cf03c9f2086a3dd95b13b36d06027e401
    Author: krughoff 
    Date:   Thu May 6 23:18:42 2010 +0000
    
        Code to read defects from a fits file into a dictionary of defect lists
    

    e68d3975

    commit e68d39756f3f435b93ee1a405e7654227628fabc
    Merge: 31bfc9f 9daf87a
    Author: krughoff 
    Date:   Thu Oct 27 00:34:37 2011 +0000
    
        merge from trunk
    

    2706712c

    commit 2706712c7fadfa21f57158ff4e028e64d840df5b
    Author: krughoff 
    Date:   Thu Apr 29 15:01:07 2010 +0000
    
        Another fix for defects in cameraGeom utils
    

    7ee6e1e3

    commit 7ee6e1e37965e13bc5b82cd2079df7f2fdefd8d7
    Author: Steven Bickerton 
    Date:   Mon Jan 30 22:19:04 2012 -0600
    
        added some helper functions in cameraGeomUtils.
    

    7ffd25c1

    commit 7ffd25c1b6fa71ec4641f4718d6eddc839f7a758
    Author: rhl 
    Date:   Sun Apr 4 15:59:56 2010 +0000
    
        Added support for amps being stored on disk in separate files
    

    20ad51f1

    commit 20ad51f1945ce30ab482e0218261b1e314b25ab3
    Author: rhl 
    Date:   Thu Apr 8 21:04:43 2010 +0000
    
        Join the per-amp data to the Ccd using the amp index, not the serial
    

    a9c01489

    commit a9c01489a4f5c05dd700e5638da310c6d834247d
    Author: Robert Lupton the Good 
    Date:   Sat Apr 20 17:08:13 2013 -0400
    
        Responses to #2681 review
    

    7250716d

    commit 7250716d10b6410c173fa2050ca5801db26b372f
    Author: rhl 
    Date:   Thu Apr 15 19:52:14 2010 +0000
    
        Don't try to add -1 to a U16 image
    

    d7ff8a52

    commit d7ff8a5265f1b964ab3080f4ed0c96f2eaf5c41d
    Author: Robert Lupton the Good 
    Date:   Sat Feb 18 23:06:06 2012 -0500
    
        Rename coefficientsUndistort to coefficientsDistort (and use it correctly --- it was backwards before)
    

    24436bda

    commit 24436bda15d8a14f180541fad9857fc0016f8bc2
    Author: bick 
    Date:   Sat Sep 3 00:23:23 2011 +0000
    
        added tests.
    

    3b1e6cc7

    commit 3b1e6cc71c205b81bc9df76180992bdc69c7d868
    Author: krughoff 
    Date:   Sat Oct 8 00:57:07 2011 +0000
    
        Changes to allow rotation of chips
    

    370e2d32

    commit 370e2d325628c1af7773863813d8608608103e1a
    Author: Paul Price 
    Date:   Mon Apr 22 19:53:56 2013 +0000
    
        cameraGeom: don't hard-code image type for showCamera
    

    e2db5f35

    commit e2db5f350ff2de3f767262cf04f4aee513be725b
    Author: krughoff 
    Date:   Thu Nov 10 23:55:40 2011 +0000
    
        Final changes to geometry before merge
    

    702f617d

    commit 702f617d97a43c1ae82ae49e4feeabe1b6721ecc
    Author: Robert Lupton the Good 
    Date:   Wed Feb 27 22:35:26 2013 -1000
    
        Make a trimmed/untrimmed CCD image if so requested
        
        Needed for the unit tests in tests/cameraGeom,py.  We shgould probably revisit isRaw/isTrimmed which
        predate ButlerImage
    

    546bbd40

    commit 546bbd40e2bfa6d75528497e1099be8b71c14e24
    Author: Robert Lupton the Good 
    Date:   Tue May 8 21:18:04 2012 -0500
    
        Enable ds9 buffering
    

    1dc2df23

    commit 1dc2df23944cd575ebc90e53be329d880c401cca
    Author: krughoff 
    Date:   Tue Oct 11 23:48:23 2011 +0000
    
        Added unit tests for assembly and Box.flip*()
    

    c5e868b7

    commit c5e868b7b00ffc22fcb6941522b22a623b04e33a
    Author: rhl 
    Date:   Fri Jan 15 10:09:01 2010 +0000
    
        Added support for Defects.  N.b. Defect is a base class; the real Defect code is in meas/algorithms which needs to be updated to inherit from afwImage::Defect
    

    31bfc9f3

    commit 31bfc9f31902f0ad236817b57f40e7c2a3f2dbe1
    Merge: 1dc2df2 2fec316
    Author: krughoff 
    Date:   Wed Oct 26 18:30:59 2011 +0000
    
        Camera geometry tests now passing
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    17aa5ab7

    commit 17aa5ab7bfc740da8c91309750f9edd1a535a0ae
    Author: rhl 
    Date:   Tue May 25 23:49:54 2010 +0000
    
        Exposure.getMaskedImage() returned a dangling reference; #1288
    

    97dea9da

    commit 97dea9da821af9732f454a89956c709616970a2e
    Author: rhl 
    Date:   Tue May 25 14:04:50 2010 +0000
    
        1/ Added .isRaw to GetCcdImage to handle reading raw data (i.e. per amp) as opposed to properly-assembled CCD images
        2/ Added bin option to the mosaicing and display code
        3/ Added force variable to allow camera .paf files that specify non-existent Ccds/Rafts (useful for debugging --- you can modify a .paf to specify a smaller mosaic without removing the now-ignored detectors/rafts)
    

    6b9ab890

    commit 6b9ab89018f35300a86e2e17ffd05895f9264480
    Author: Steven Bickerton 
    Date:   Sat Jan 28 22:25:49 2012 -0600
    
        added basic tests.  img distort not great, but working.
    

    ac97fc48

    commit ac97fc48802ae9a8b7333ddf8a8ab51bea064133
    Author: rhl 
    Date:   Tue Apr 6 22:03:14 2010 +0000
    
        Added Id.getIndex(); Detector.getParent()
    

    4ce2709b

    commit 4ce2709b74237e9bf06b7f8a4303762952b320ea
    Author: Robert Lupton the Good 
    Date:   Thu Apr 18 23:41:14 2013 -0400
    
        Added ability to put Linearity data in a camera.paf file
    

    a8f86353

    commit a8f86353b4d794d8e2accd0ce6950e72a06c3f66
    Merge: a128aac 246b6dd
    Author: dubcovsky 
    Date:   Thu Mar 31 20:50:37 2011 +0000
    
        #1556 trunk merged to ticket branch
    

    71da335b

    commit 71da335b264f4d4695ce128924fe9d59914dbf52
    Author: rhl 
    Date:   Tue Feb 9 23:43:36 2010 +0000
    
        Moved DefectList to Defects and made it per Raft/Camera to parallel the Electronics data
    

    51d10d66

    commit 51d10d665e4311610c351994de8006e7a4a981fa
    Author: Robert Lupton the Good 
    Date:   Sun Feb 3 20:12:26 2013 -1000
    
        Teach showCamera about the butler
    

    fb65d5ca

    commit fb65d5cacaeb09d8f082896a90f59b1ce6d56e28
    Author: Robert Lupton the Good 
    Date:   Thu Feb 21 10:10:46 2013 +0900
    
        Fixed showCamera to work with lsstSim as well as SuprimeCam/HSC
    

    439c701f

    commit 439c701fb2f9a53eecb3e5485566ad59dd30057d
    Author: krughoff 
    Date:   Thu Apr 29 00:22:16 2010 +0000
    
        small changes to utils to utilize defects
    

    08da793e

    commit 08da793ef8cb7f9661104d6916f471c1ee895c22
    Author: Robert Lupton the Good 
    Date:   Wed Feb 6 11:46:35 2013 -1000
    
        Rewrote showCamera to put the CCDs in the correct places
        
        Also other cleanup (e.g. imageSource == None works again; we can handle displaying
        the SuprimeCam CCDs which have had the top part (with guider shadows) removed)
    

    73bee471

    commit 73bee4718479496b5cc06780ce97580cce329866
    Author: rhl 
    Date:   Fri Apr 9 06:32:55 2010 +0000
    
        Search policy array for Raft Policy; findDetector throws an exception when it fails
    

    516257ea

    commit 516257ea3393307668454e36a9a51312256a6bf4
    Author: rhl 
    Date:   Thu Feb 4 05:33:08 2010 +0000
    
        Give Amps serial numbers in .paf, and allow per-amp Electronic info
    

    e88ff0cd

    commit e88ff0cd6d8b7e3b4173c8fd71f33e78b407c782
    Author: Steven Bickerton 
    Date:   Tue Jan 31 10:02:20 2012 -0600
    
        split FpPosition to FpPoint/Extent.
    

    624f4cc3

    commit 624f4cc36017052ae547a6a13d699d39bf74a428
    Author: rhl 
    Date:   Sun Sep 18 13:49:13 2011 +0000
    
        Fixed typo; #1768
    

    021325b8

    commit 021325b85cdd4a9eb62b80698a7b63167a9ae00b
    Author: rhl 
    Date:   Tue Apr 27 14:44:03 2010 +0000
    
        Make utils.getGeomPolicy use default policy; use this function in tests
    

    1f7e505a

    commit 1f7e505a716e222d81146ce6bccce4e4f8db5f46
    Author: rhl 
    Date:   Mon May 24 13:33:01 2010 +0000
    
        Change made in error; the problem was due to an incorrect use of trimmed CCD images as raw CCD images.  The proper fix still needs to be applied
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    9ea37372

    commit 9ea3737267a839efa604064ee66161aad677354e
    Author: rhl 
    Date:   Mon Aug 23 04:43:59 2010 +0000
    
        Removed check that rafts are all fully filled with CCDs
    

    018ddb66

    commit 018ddb66b6f03ce65ad68454eec733f0f4b06b0b
    Author: Steven Bickerton 
    Date:   Thu Dec 6 19:44:13 2012 -1000
    
        change ccdInfo init to {} instead of None.
    

    c2030ec8

    commit c2030ec804a651351b12307bba45df03a206e6c5
    Merge: b140e9b 3e5bf81
    Author: jbosch 
    Date:   Mon Mar 7 22:19:24 2011 +0000
    
        afw #1556 - sync changes from trunk
    

    77729dfe

    commit 77729dfe5bc7cbc44bbca800fc97a99047f52f9b
    Author: rhl 
    Date:   Fri Apr 9 14:55:15 2010 +0000
    
        Don't search geomPolicy.getArray("Raft") if it's actually a scaler
    

    993791af

    commit 993791aff43a00ff81518138edbf2939ad2a19ea
    Author: rhl 
    Date:   Fri Jan 15 06:36:22 2010 +0000
    
        Misc changes, mostly to do with displaying detectors/mosaics of real data not just synthesized
    

    b3296b1d

    commit b3296b1d682a10a6380ac40055a4f4c39cee9836
    Author: rhl 
    Date:   Fri Sep 16 14:05:28 2011 +0000
    
        pyfits should not be required
    

    82325a24

    commit 82325a2470d1b0d353267846e49b731cff60226e
    Author: rhl 
    Date:   Thu Jan 21 08:13:24 2010 +0000
    
        The result of experience with Subaru data
    

    61a76714

    commit 61a767146003c7e685e721336eb99940dec4baf3
    Author: rhl 
    Date:   Thu Jan 14 04:25:43 2010 +0000
    
        Got showCamera working with SuPrimeCam, misc cleanup
    

    2ebad60d

    commit 2ebad60ddfd2a217aa139655a0e6e7e578da48d2
    Author: rhl 
    Date:   Fri Jan 15 07:57:27 2010 +0000
    
        Started adding Defect support;  make Amp inherit from Detector
    

    d30faf6b

    commit d30faf6b4da3af0340b2535ce9d319ec1470b3f3
    Author: rhl 
    Date:   Sun Jan 17 15:02:36 2010 +0000
    
        Add support for bad columns; some icc cleanup
    

    6c5cc14a

    commit 6c5cc14a7d56134d361f5eaa36dcc3df6ae7985d
    Author: krughoff 
    Date:   Fri Apr 30 20:10:32 2010 +0000
    
        Fixed bug in makeDefects which only created defects for the first chip
    

    8933e1bd

    commit 8933e1bd025687a9fc571d0e4bd52b5b0b901ce9
    Author: Robert Lupton the Good 
    Date:   Thu May 10 09:28:54 2012 -0500
    
        Pass SynthesizeCcdImage's arguments to its baseclass; fix doc string
    

    0b8fe106

    commit 0b8fe1061a787af730e8f404dce7f343feab8164
    Author: Steven Bickerton 
    Date:   Thu Jan 26 17:14:15 2012 -0600
    
        more distortion updates.
    

    912ae9b0

    commit 912ae9b08cf0fb9c165494fa3291f18144a3d770
    Author: krughoff 
    Date:   Wed Oct 5 00:21:17 2011 +0000
    
        More fixes for camera geometry and ccd assembly
    

    426eecd3

    commit 426eecd377549e8e51a31f307096b389bb1c4f46
    Author: Robert Lupton the Good 
    Date:   Thu Feb 21 10:29:10 2013 +0900
    
        Replaced SynthesizeImage by ButlerImage
        
        SynthesizeImage predated the butler, and the ButlerImage
        object creates blank images if the dataId is invalid.
        
        We could probably get rid of the GetCcdImage baseclass
        too, but that's a gratuitous change to some APIs that
        currently accept filenames and that might conceivably
        still be in use somewhere
    

    df438a72

    commit df438a724651ee2a107de2df8b27094d34d050b8
    Author: Robert Lupton the Good 
    Date:   Wed Feb 1 12:29:57 2012 -0500
    
        Use Angle for cameraGeom::Orientation; #1879
    

    0f6071dc

    commit 0f6071dc9bd2e9d72f539043f29026d89fb699f7
    Author: rhl 
    Date:   Fri Apr 9 01:58:55 2010 +0000
    
        Added findAmp for the Butler
    

    83689a40

    commit 83689a402f5eb3e42eb8eb17b18dd8ea5dd6ae53
    Author: krughoff 
    Date:   Thu Sep 29 20:52:34 2011 +0000
    
        changes for ticket #1767
    

    64a9e1e1

    commit 64a9e1e1a047c9b9ce6b4a06e2d8bf150635a8f8
    Author: rhl 
    Date:   Thu Feb 24 11:38:24 2011 +0000
    
        Added way to trim an Exposure
    

    fd901390

    commit fd901390b961fa520c44c396d01382c606eef9d9
    Author: rhl 
    Date:   Thu Jan 14 08:27:40 2010 +0000
    
        Use SynthesizeCcdImage to cleanup interface to reading or synthesizing CCD images
    

    ee28a753

    commit ee28a753fb7c71ea1ae3e02838b14ff59c498778
    Author: Steven Bickerton 
    Date:   Fri Dec 7 14:09:38 2012 +0900
    
        added offsetUnit to cameraGeom policy.  cleaned-up some tabs.
    

    e193729a

    commit e193729ad24e2b0d48b1abcd0ddb2aaad6ba4188
    Author: rhl 
    Date:   Wed Feb 23 12:27:29 2011 +0000
    
        Worked on cameraGeom; all pixel positions are now floating (to permit transfer of centroids to boresight coordinates)
    

    Commits in /Users/nate/repos_lsst/afw/

    c856a32c

    commit c856a32c3ccde92fb10084e436529ecb2401192c
    Author: Simon Krughoff 
    Date:   Wed Mar 5 19:04:01 2014 -0600
    
        Cleaned up cameraGeom.utils and added getNQuarters to Orientation
    

    9d2d359a

    commit 9d2d359a48763dd970c7d5ba6c2d6382b9110511
    Author: Simon Krughoff 
    Date:   Thu Apr 3 14:20:54 2014 -0500
    
        response to review added handling of isTrimmed in prepareWcsData
    

    b6ce1d15

    commit b6ce1d159abe2be15138b9f88ccc6971c2543eaa
    Author: Simon Krughoff 
    Date:   Mon Mar 10 18:44:53 2014 -0500
    
        Added saturation value to AmpInfoTable.
    

    23a9616a

    commit 23a9616af3904401f6d3f5024d8aa031ca7b0e88
    Author: Simon Krughoff 
    Date:   Wed Mar 12 20:00:54 2014 -0500
    
        Fixed Wcs issue in cameraGeom.utils
    

    726f34b1

    commit 726f34b150abc8b1fc4779504ceb34fa9f2ab456
    Author: Simon Krughoff 
    Date:   Thu Sep 18 19:09:00 2014 -0700
    
        Added ds9.Buffering to CCD bounding boxes render
    

    f8333aa0

    commit f8333aa0b312a6d6ecd444c6deebf38f2c9114ef
    Author: Simon Krughoff 
    Date:   Mon Mar 10 18:54:40 2014 -0500
    
        Fixed typo in cameraGeomUtils.prepareWcsData()
    

    e0fa1c0b

    commit e0fa1c0bff0103bd3feca69126484caa71fdd523
    Author: Simon Krughoff 
    Date:   Thu Sep 18 19:05:10 2014 -0700
    
        Scale gain by arbitrary function in amp image
    

    b4f73cbf

    commit b4f73cbf3097165062c02aa04905ab10b06c6bec
    Author: Russell Owen 
    Date:   Mon Sep 8 16:05:52 2014 -0700
    
        First pass at DM-840
        Added UNDEFINED ImageOrigin enum value
        Made UNDEFINED the default for image constructors (which have lots of defaults,
        so I can't just delete the origin default).
        Eliminated the default value for ImageBase.getBBox.
        Modified all code that calls functions that accept an ImageOrigin argument to specify it explicitly.
    

    d1d2fb23

    commit d1d2fb2379e8ca75f6aae8129a9c705f2fb4ae87
    Author: Simon Krughoff 
    Date:   Thu Sep 18 19:07:47 2014 -0700
    
        Fixed up docs to match new API
    

    0f6071dc

    commit 0f6071dc9bd2e9d72f539043f29026d89fb699f7
    Author: rhl 
    Date:   Fri Apr 9 01:58:55 2010 +0000
    
        Added findAmp for the Butler
    

    36730423

    commit 36730423155b5a8ff0bd86f5e5230bb9177f5986
    Author: Simon Krughoff 
    Date:   Thu Sep 18 19:06:05 2014 -0700
    
        Return None instead of exception
        
        When calculating the raw CCD bounding box return None instead of
        raising when the amps do not have raw data.
    

    9372e552

    commit 9372e55278b23ff8990145914b5807675b26d769
    Author: Simon Krughoff 
    Date:   Tue Mar 4 18:29:47 2014 -0600
    
        More work on cameraGeom.utils and the camera geom unit test
    

    8b4a97d8

    commit 8b4a97d87cace3df7e96fbbb3861891d4d326c79
    Author: Simon Krughoff 
    Date:   Thu Sep 18 19:03:06 2014 -0700
    
        Add division from __future__
        
        Now importing division from __future__ this is more in line with
        the rest of the stack.  There are some limitations with this outlined
        in DM-83.
    

    1ff73d16

    commit 1ff73d1676c9e157841aeebebc13512fa7e72ddb
    Author: Simon Krughoff 
    Date:   Wed Mar 5 20:23:49 2014 -0600
    
        Added test for Orientation.getNQuarter.  Fixed imports in some of the utils.  Removed out of date comments in testCameraGeom.py
    

    5261ebd8

    commit 5261ebd80b0661984b5f5510800d037e89fef9e0
    Author: Simon Krughoff 
    Date:   Wed Mar 12 18:48:02 2014 -0500
    
        Change mention of amp data to amp information
    

    08da793e

    commit 08da793ef8cb7f9661104d6916f471c1ee895c22
    Author: Robert Lupton the Good 
    Date:   Wed Feb 6 11:46:35 2013 -1000
    
        Rewrote showCamera to put the CCDs in the correct places
        
        Also other cleanup (e.g. imageSource == None works again; we can handle displaying
        the SuprimeCam CCDs which have had the top part (with guider shadows) removed)
    

    ff18f270

    commit ff18f2708856bb8b9851e4a0bc29601b512fa20c
    Author: Simon Krughoff 
    Date:   Thu Sep 18 18:47:07 2014 -0700
    
        Generalized the show* methods
        
        These methods now take an image source that is used to access
        the images.  This makes it easier to load images from disk.
        
        The image source must have the following two methods:
        getCcdImage(Detector, ImageFactory, binSize)
        getAmpImage(AmpInfoTable, ImageFactory)
    

    1f7e505a

    commit 1f7e505a716e222d81146ce6bccce4e4f8db5f46
    Author: rhl 
    Date:   Mon May 24 13:33:01 2010 +0000
    
        Change made in error; the problem was due to an incorrect use of trimmed CCD images as raw CCD images.  The proper fix still needs to be applied
    

    bde0ab27

    commit bde0ab27a9add858f810563213c1424f9e63ddde
    Author: Robert Lupton the Good 
    Date:   Sun Apr 12 16:00:47 2015 -0300
    
        Implement RFC-42
        
        N.b. that you need display_ds9 to use the ds9 backend
        N.b. support frame only in cameraGeom.utils top-level routine, showCamera
    

    d5210db5

    commit d5210db520306e329b276d1ab520cd47c86a129b
    Author: Simon Krughoff 
    Date:   Thu Sep 18 19:09:35 2014 -0700
    
        White space changes and removed unused code
    

    cb8ea286

    commit cb8ea2860388cf7f9e6a83f3feadabc2f8fa565f
    Author: Simon Krughoff 
    Date:   Wed Oct 1 17:03:20 2014 -0700
    
        Changed binSize to be in binned pixels
        
        This makes it easier to deal with binned images and makes
        it more obvious what to expect from the border in the image
        displayed in ds9
    

    439c701f

    commit 439c701fb2f9a53eecb3e5485566ad59dd30057d
    Author: krughoff 
    Date:   Thu Apr 29 00:22:16 2010 +0000
    
        small changes to utils to utilize defects
    

    82325a24

    commit 82325a2470d1b0d353267846e49b731cff60226e
    Author: rhl 
    Date:   Thu Jan 21 08:13:24 2010 +0000
    
        The result of experience with Subaru data
    

    61a76714

    commit 61a767146003c7e685e721336eb99940dec4baf3
    Author: rhl 
    Date:   Thu Jan 14 04:25:43 2010 +0000
    
        Got showCamera working with SuPrimeCam, misc cleanup
    

    545f4dc9

    commit 545f4dc9108633ab9207c63391287bf46e819278
    Author: Russell Owen 
    Date:   Wed Jan 14 16:35:27 2015 -0800
    
        Updated all cameraGeom doc strings to work better with Doxygen
        Also removed one unused import and one no-op semicolon from a return statement
    

    d00b5062

    commit d00b5062544c14213f0c78490a3d4d53cb502bf5
    Author: Simon Krughoff 
    Date:   Mon Sep 15 10:42:56 2014 -0700
    
        Fixed method documentation
        
        Added [in] and [out] to @param for each method.  Added some missing
        parameter documentation.
    

    39ce81bb

    commit 39ce81bb1108dd6435e49baae5db3003625b93fe
    Author: Simon Krughoff 
    Date:   Mon Oct 20 17:53:27 2014 -0700
    
        Documentation improvements from review of DM-766
        
        Adds documentation about examples scripts to doxygen
        of CameraGeom.  Also clarified some of the assumptions
        in the utils docstrings.
    

    d21f3141

    commit d21f31412c45938442cc8d43e5cfc79b2e85f05f
    Author: Simon Krughoff 
    Date:   Wed Feb 26 18:26:28 2014 -0600
    
        First start on porting utils
    

    f6e303b1

    commit f6e303b125a3f1d2a8184b0ebe408254dd5c2402
    Author: Simon Krughoff 
    Date:   Wed Mar 12 18:37:25 2014 -0500
    
        Changes to address code review from Jim
    

    20d15f9f

    commit 20d15f9f585f90d2205b058c94f9356645dc137d
    Author: Simon Krughoff 
    Date:   Fri Mar 7 18:05:53 2014 -0600
    
        Added bounding boxes to showCamera
    

    297a2be9

    commit 297a2be96cb3105f7ebad0da7c947e80cc510065
    Author: Simon Krughoff 
    Date:   Thu Mar 27 18:10:51 2014 -0500
    
        fixed bug in prepareWcs
    

    Return to list

    include/lsst/afw/coord/Coord.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #if !defined(LSST_AFW_COORD_COORD_H)
                    #define LSST_AFW_COORD_COORD_H
                    /**
                     * @file
                     * @brief Functions to handle coordinates
                     * @ingroup afw
                     * @author Steve Bickerton
                     *
                     * @todo add FK4 ... as needed
                     */ 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/shared_ptr.hpp"
                    
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/geom/Angle.h"
    
    43 c55f7877 - #include "lsst/afw/coord/Utils.h"
    #include "lsst/afw/coord/Observatory.h" #include "lsst/daf/base.h" namespace lsst { namespace afw { namespace coord { /* * Information about the coordinate system we support */ enum CoordSystem { FK5, ICRS, GALACTIC, ECLIPTIC, TOPOCENTRIC }; CoordSystem makeCoordEnum(std::string const system); class IcrsCoord; class Fk5Coord; class GalacticCoord; class EclipticCoord; class TopocentricCoord; /** * @class Coord * * This is the base class for spherical coordinates. */ class Coord { public: typedef boost::shared_ptr Ptr; typedef boost::shared_ptr ConstPtr; Coord(lsst::afw::geom::Point2D const &p2d, lsst::afw::geom::AngleUnit unit = lsst::afw::geom::degrees, double const epoch = 2000.0); Coord(lsst::afw::geom::Point3D const &p3d, double const epoch = 2000.0, bool normalize=true, lsst::afw::geom::Angle const defaultLongitude = lsst::afw::geom::Angle(0.)); Coord(lsst::afw::geom::Angle const ra, lsst::afw::geom::Angle const dec, double const epoch = 2000.0); Coord(std::string const ra, std::string const dec, double const epoch = 2000.0); Coord(); virtual ~Coord() {} virtual Coord::Ptr clone() const { return Coord::Ptr(new Coord(*this)); } virtual void reset(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude) { double const epoch = 2000.0; reset(longitude, latitude, epoch); } virtual void reset(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude, double const epoch); double getEpoch() const { return _epoch; } lsst::afw::geom::Point2D getPosition(lsst::afw::geom::AngleUnit unit = lsst::afw::geom::degrees) const; lsst::afw::geom::Point3D getVector() const; virtual std::pair getCoordNames() const { return std::pair("RA", "Dec"); }
    100 0d696ad1 +
    101 4d62652f + virtual std::string getClassName() const { return "Coord"; }
    // These are inline functions and are defined at the end of this header file lsst::afw::geom::Angle operator[](int const index) const; bool operator==(Coord const &rhs) const; /** * @brief The main access method for the longitudinal coordinate * * All systems store their longitudinal coordinate in _longitude, * be it RA, l, lambda, or azimuth. This is how they're accessed. * */ inline lsst::afw::geom::Angle getLongitude() const { return _longitude; }; /** * @brief The main access method for the latitudinal coordinate * * All systems store their latitudinal coordinate in _latitude, * be it Dec, b, beta, or altitude. This is how they're accessed. */ inline lsst::afw::geom::Angle getLatitude() const { return _latitude; }; inline std::string getLongitudeStr(lsst::afw::geom::AngleUnit unit) const; inline std::string getLatitudeStr() const; Coord transform(Coord const &poleFrom, Coord const &poleTo) const; lsst::afw::geom::Angle angularSeparation(Coord const &c) const; std::pair getOffsetFrom(Coord const &c) const; std::pair getTangentPlaneOffset(Coord const &c) const; void rotate(Coord const &axis, lsst::afw::geom::Angle const theta); lsst::afw::geom::Angle offset(lsst::afw::geom::Angle const phi, lsst::afw::geom::Angle const arcLen); Coord::Ptr convert(CoordSystem system) const; virtual Fk5Coord toFk5(double const epoch) const; virtual Fk5Coord toFk5() const; virtual IcrsCoord toIcrs() const; virtual GalacticCoord toGalactic() const; virtual EclipticCoord toEcliptic(double const epoch) const; virtual EclipticCoord toEcliptic() const; virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &obsDate) const; private: lsst::afw::geom::Angle _longitude; lsst::afw::geom::Angle _latitude; double _epoch; void _verifyValues() const; }; /** * @class IcrsCoord * @brief A class to handle Icrs coordinates (inherits from Coord) */ class IcrsCoord : public Coord { public: typedef boost::shared_ptr Ptr; IcrsCoord(lsst::afw::geom::Point2D const &p2d, lsst::afw::geom::AngleUnit unit = lsst::afw::geom::degrees) : Coord(p2d, unit, 2000.0) {} IcrsCoord(lsst::afw::geom::Point3D const &p3d, bool normalize=true, lsst::afw::geom::Angle const defaultLongitude = lsst::afw::geom::Angle(0.)) : Coord(p3d, 2000.0, normalize, defaultLongitude) {} IcrsCoord(lsst::afw::geom::Angle const ra, lsst::afw::geom::Angle const dec) : Coord(ra, dec, 2000.0) {} IcrsCoord(std::string const ra, std::string const dec) : Coord(ra, dec, 2000.0) {} IcrsCoord() : Coord() {} virtual Coord::Ptr clone() const { return IcrsCoord::Ptr(new IcrsCoord(*this)); }
    169 4d62652f +
    170 4d62652f + virtual std::string getClassName() const { return "IcrsCoord"; }
    virtual void reset(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude); lsst::afw::geom::Angle getRa() const { return getLongitude(); } lsst::afw::geom::Angle getDec() const { return getLatitude(); } std::string getRaStr(lsst::afw::geom::AngleUnit unit) const { return getLongitudeStr(unit); } std::string getDecStr() const { return getLatitudeStr(); } virtual Fk5Coord toFk5(double const epoch) const; virtual Fk5Coord toFk5() const; virtual IcrsCoord toIcrs() const; private: }; /** * @class Fk5Coord * @brief A class to handle Fk5 coordinates (inherits from Coord) */ class Fk5Coord : public Coord { public: typedef boost::shared_ptr Ptr; Fk5Coord(lsst::afw::geom::Point2D const &p2d, lsst::afw::geom::AngleUnit unit = lsst::afw::geom::degrees, double const epoch = 2000.0) : Coord(p2d, unit, epoch) {} Fk5Coord(lsst::afw::geom::Point3D const &p3d, double const epoch = 2000.0, bool normalize=true, lsst::afw::geom::Angle const defaultLongitude= lsst::afw::geom::Angle(0.)) : Coord(p3d, epoch, normalize, defaultLongitude) {} Fk5Coord(lsst::afw::geom::Angle const ra, lsst::afw::geom::Angle const dec, double const epoch = 2000.0) : Coord(ra, dec, epoch) {} Fk5Coord(std::string const ra, std::string const dec, double const epoch = 2000.0) : Coord(ra, dec, epoch) {} Fk5Coord() : Coord() {} virtual Coord::Ptr clone() const { return Fk5Coord::Ptr(new Fk5Coord(*this)); }
    210 4d62652f + virtual std::string getClassName() const { return "Fk5Coord"; }
    211 4d62652f +
    Fk5Coord precess(double const epochTo) const; lsst::afw::geom::Angle getRa() const { return getLongitude(); } lsst::afw::geom::Angle getDec() const { return getLatitude(); } std::string getRaStr(lsst::afw::geom::AngleUnit unit) const { return getLongitudeStr(unit); } std::string getDecStr() const { return getLatitudeStr(); } virtual Fk5Coord toFk5(double const epoch) const; virtual Fk5Coord toFk5() const; virtual IcrsCoord toIcrs() const; virtual GalacticCoord toGalactic() const; virtual EclipticCoord toEcliptic(double const epoch) const; virtual EclipticCoord toEcliptic() const; virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &obsDate) const; private: }; /** * @class GalacticCoord * @brief A class to handle Galactic coordinates (inherits from Coord) */ class GalacticCoord : public Coord { public: typedef boost::shared_ptr Ptr; GalacticCoord(lsst::afw::geom::Point2D const &p2d, lsst::afw::geom::AngleUnit unit = lsst::afw::geom::degrees) : Coord(p2d, unit) {} GalacticCoord(lsst::afw::geom::Point3D const &p3d, bool normalize=true, lsst::afw::geom::Angle const defaultLongitude= lsst::afw::geom::Angle(0.)) : Coord(p3d, normalize, defaultLongitude) {} GalacticCoord(lsst::afw::geom::Angle const l, lsst::afw::geom::Angle const b) : Coord(l, b) {} GalacticCoord(std::string const l, std::string const b) : Coord(l, b) {} GalacticCoord() : Coord() {} virtual Coord::Ptr clone() const { return GalacticCoord::Ptr(new GalacticCoord(*this)); }
    252 4d62652f + virtual std::string getClassName() const { return "GalacticCoord"; }
    253 4d62652f +
    virtual void reset(lsst::afw::geom::Angle const longitude, lsst::afw::geom::Angle const latitude); virtual std::pair getCoordNames() const { return std::pair("L", "B"); } lsst::afw::geom::Angle getL() const { return getLongitude(); } lsst::afw::geom::Angle getB() const { return getLatitude(); } std::string getLStr(lsst::afw::geom::AngleUnit unit) const { return getLongitudeStr(unit); } std::string getBStr() const { return getLatitudeStr(); } virtual Fk5Coord toFk5(double const epoch) const; virtual Fk5Coord toFk5() const ; virtual GalacticCoord toGalactic() const; private: }; /** * @class EclipticCoord * @brief A class to handle Ecliptic coordinates (inherits from Coord) */ class EclipticCoord : public Coord { public: typedef boost::shared_ptr Ptr; EclipticCoord(lsst::afw::geom::Point2D const &p2d, lsst::afw::geom::AngleUnit unit = lsst::afw::geom::degrees, double const epoch = 2000.0) : Coord(p2d, unit, epoch) {} EclipticCoord(lsst::afw::geom::Point3D const &p3d, double const epoch = 2000.0, bool normalize=true, lsst::afw::geom::Angle const defaultLongitude= lsst::afw::geom::Angle(0.)) : Coord(p3d, epoch, normalize, defaultLongitude) {} // note the abbreviation of lambda -> lamd to avoid swig warnings for python keyword 'lambda' EclipticCoord(lsst::afw::geom::Angle const lamb, lsst::afw::geom::Angle const beta, double const epoch = 2000.0) : Coord(lamb, beta, epoch) {} EclipticCoord(std::string const lamb, std::string const beta, double const epoch = 2000.0) : Coord(lamb, beta, epoch) {} EclipticCoord() : Coord() {} virtual Coord::Ptr clone() const { return EclipticCoord::Ptr(new EclipticCoord(*this)); }
    302 723062e1 +
    303 4d62652f + virtual std::string getClassName() const { return "EclipticCoord"; }
    virtual std::pair getCoordNames() const { return std::pair("Lambda", "Beta"); } lsst::afw::geom::Angle getLambda() const { return getLongitude(); } lsst::afw::geom::Angle getBeta() const { return getLatitude(); } std::string getLambdaStr(lsst::afw::geom::AngleUnit unit) const { return getLongitudeStr(unit); } std::string getBetaStr() const { return getLatitudeStr(); } virtual Fk5Coord toFk5(double const epoch) const; virtual Fk5Coord toFk5() const; virtual EclipticCoord toEcliptic(double const epoch) const; virtual EclipticCoord toEcliptic() const; EclipticCoord precess(double const epochTo) const; private: }; /** * @class TopocentricCoord * @brief A class to handle topocentric (AltAz) coordinates (inherits from Coord) */ class TopocentricCoord : public Coord { public: typedef boost::shared_ptr Ptr; TopocentricCoord(lsst::afw::geom::Point2D const &p2d, lsst::afw::geom::AngleUnit unit, double const epoch, Observatory const &obs) : Coord(p2d, unit, epoch), _obs(obs) {} TopocentricCoord(lsst::afw::geom::Point3D const &p3d, double const epoch, Observatory const &obs, bool normalize=true, lsst::afw::geom::Angle const defaultLongitude= lsst::afw::geom::Angle(0.)) : Coord(p3d, epoch, normalize, defaultLongitude), _obs(obs) {} TopocentricCoord(lsst::afw::geom::Angle const az, lsst::afw::geom::Angle const alt, double const epoch, Observatory const &obs) : Coord(az, alt, epoch), _obs(obs) {} TopocentricCoord(std::string const az, std::string const alt, double const epoch, Observatory const &obs) : Coord(az, alt, epoch), _obs(obs) {} virtual Coord::Ptr clone() const { return TopocentricCoord::Ptr(new TopocentricCoord(*this)); }
    347 4d62652f + virtual std::string getClassName() const { return "TopocentricCoord"; }
    348 4d62652f +
    349 4d62652f + Observatory getObservatory() const { return _obs; }
    350 4d62652f +
    virtual std::pair getCoordNames() const { return std::pair("Az", "Alt"); } lsst::afw::geom::Angle getAzimuth() const { return getLongitude(); } lsst::afw::geom::Angle getAltitude() const { return getLatitude(); } std::string getAzimuthStr(lsst::afw::geom::AngleUnit unit) const { return getLongitudeStr(unit); } std::string getAltitudeStr() const { return getLatitudeStr(); } virtual Fk5Coord toFk5(double const epoch) const; virtual Fk5Coord toFk5() const; virtual TopocentricCoord toTopocentric(Observatory const &obs, lsst::daf::base::DateTime const &date) const; virtual TopocentricCoord toTopocentric() const; private: Observatory _obs; }; /* * Factory Functions * */ Coord::Ptr makeCoord(CoordSystem const system, lsst::afw::geom::Angle const ra, lsst::afw::geom::Angle const dec, double const epoch); Coord::Ptr makeCoord(CoordSystem const system, std::string const ra, std::string const dec, double const epoch); Coord::Ptr makeCoord(CoordSystem const system, lsst::afw::geom::Point2D const &p2d, lsst::afw::geom::AngleUnit unit, double const epoch); Coord::Ptr makeCoord(CoordSystem const system, lsst::afw::geom::Point3D const &p3d, double const epoch, bool normalize=true, lsst::afw::geom::Angle const defaultLongitude=lsst::afw::geom::Angle(0.)); Coord::Ptr makeCoord(CoordSystem const system); Coord::Ptr makeCoord(CoordSystem const system, lsst::afw::geom::Angle const ra, lsst::afw::geom::Angle const dec); Coord::Ptr makeCoord(CoordSystem const system, std::string const ra, std::string const dec); Coord::Ptr makeCoord(CoordSystem const system, lsst::afw::geom::Point2D const &p2d, lsst::afw::geom::AngleUnit unit); Coord::Ptr makeCoord(CoordSystem const system, lsst::afw::geom::Point3D const &p3d, bool normalize=true, lsst::afw::geom::Angle const defaultLongitude=lsst::afw::geom::Angle(0.)); /* * Utility functions * */ lsst::afw::geom::Angle eclipticPoleInclination(double const epoch); lsst::afw::geom::Angle dmsStringToAngle(std::string const dms); lsst::afw::geom::Angle hmsStringToAngle(std::string const hms); std::string angleToDmsString(lsst::afw::geom::Angle const deg); std::string angleToHmsString(lsst::afw::geom::Angle const deg); std::ostream & operator<<(std::ostream & os, Coord const & coord); }}} /* ============================================================== * * Definitions of inline functions * * ============================================================== */ /** * @brief Provide access to our contents via an index * */ inline lsst::afw::geom::Angle lsst::afw::coord::Coord::operator[](int const index) const { switch (index) { case 0: return _longitude; break; case 1: return _latitude; break; default:
    415 29df7008 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    428 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Index must be 0 or 1."); break; } } /** * @brief Allow quick access to the longitudinal coordinate as a string * * @note There's no reason to want a longitude in radians, so that unit will cause * an exception to be thrown * @note There's no clear winner for a default, so the unit must always be * explicitly provided. * */ inline std::string lsst::afw::coord::Coord::getLongitudeStr(lsst::afw::geom::AngleUnit unit) const { if (unit == lsst::afw::geom::hours) { return angleToHmsString(getLongitude()); } else if (unit == lsst::afw::geom::degrees) { return angleToDmsString(getLongitude()); } else {
    436 29df7008 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    449 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Units must be 'degrees' or 'hours'"); } } /** * @brief Allow quick access to the longitude coordinate as a string * * @note There's no reason to want a latitude in radians or hours, so * the units can not be explicitly requested. * */ inline std::string lsst::afw::coord::Coord::getLatitudeStr() const { return angleToDmsString(getLatitude()); } /** * @brief Equality operator, compares each element directly */ inline bool lsst::afw::coord::Coord::operator==(lsst::afw::coord::Coord const &rhs) const { return (_longitude == rhs._longitude) && (_latitude == rhs._latitude) && (_epoch == rhs._epoch); }
    473 89acbf3a + /**
    474 89acbf3a + * @brief Inequality; the complement of equality
    475 89acbf3a + */
    476 89acbf3a + inline bool operator!=(lsst::afw::coord::Coord const &lhs, lsst::afw::coord::Coord const &rhs) {
    477 89acbf3a + return !(lhs == rhs);
    478 89acbf3a + }
    479 89acbf3a +
    #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    29df7008

    commit 29df7008c846afeffa2dea8c96e9923903ed8c86
    Author: bick 
    Date:   Thu Mar 25 22:48:33 2010 +0000
    
        #1188 Inlined some accessors.  Added exception for makeCoordEnum.
    

    c55f7877

    commit c55f7877791c670dbadd0abfa9e9696a17cfb924
    Author: dstn 
    Date:   Wed May 4 16:27:43 2011 +0000
    
        plug Angle into Coord, doing massive violence in the process
    

    Commits in /Users/nate/repos_lsst/afw/

    723062e1

    commit 723062e13485c54a881ca0976b4627b872b931c1
    Author: bick 
    Date:   Fri Jul 30 21:21:34 2010 +0000
    
        #1397 Made rotate()/offset() methods in-situ.  Added clone().
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    4d62652f

    commit 4d62652fa86a1c53d99c71ca845d3ea3af63565f
    Author: Russell Owen 
    Date:   Wed Apr 22 16:57:18 2015 -0700
    
        Improved string representations of Coords
        
        Improved os << Coord (in C++) and Coord.__str__ and __repr__ in Python
        for Coord and all subclasses, as follows:
        - The coordinate system is shown, even for clones (without the need to cast)
        - Positions are in degrees, instead of radians
        - IcrsCoord and GalacticCoord do not show the epoch
        - TopocentricCoord now has string representations, and the data includes Observatory
        - Coord.__str__ now uses C++ os << Coord, for simplicity and uniformity
        - Coord.__repr__ shows numbers (except observatory to full precision
          (except for observatory data for TopocentricCoord, since it didn't seem worth the extra clutter).
        - Coord.__repr__ omits the leading "afwCoord."
        
        Note: I would prefer to make Coord.__repr__ the same as __str__
        but it was more detailed so I left that feature.
        
        Make Coord.__str__ use << and add observatory information for topo
    

    0d696ad1

    commit 0d696ad1f31c46bb66dd93863415f3378ef7b8b0
    Author: bick 
    Date:   Sat Mar 13 23:46:40 2010 +0000
    
        #1188 changee accessor names for point2d and 3d.
    

    89acbf3a

    commit 89acbf3a5ab0708c97a4f0e4cadb66a1709170d4
    Author: John Swinbank 
    Date:   Mon Mar 23 08:32:59 2015 -0400
    
        Implement != for Coord.
    

    Return to list

    include/lsst/afw/image/Image.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief Support for 2-D images
                     *
                     * This file contains the basic 2-d image support for LSST
                     */
                    #ifndef LSST_AFW_IMAGE_IMAGE_H
                    #define LSST_AFW_IMAGE_IMAGE_H
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/mpl/bool.hpp"
                    #include "boost/shared_ptr.hpp"
                    
                    #include "lsst/afw/geom/Extent.h"
                    #include "lsst/afw/geom/Box.h"
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/image/lsstGil.h"
                    #include "lsst/afw/image/Utils.h"
                    #include "lsst/afw/image/ImageUtils.h"
                    #include "lsst/afw/math/Function.h"
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/pex/exceptions.h"
                    #include "ndarray.h"
                    
                    namespace lsst { namespace afw {
                    
                    namespace formatters {
                        template  class ImageFormatter;
                        template  class DecoratedImageFormatter;
                    }
                    
                    namespace fits {
                    class Fits;
                    class MemFileManager;
                    }
                    
                    namespace image {
                        namespace detail {
                            //
                            // Traits for image types
                            //
                            /// Base %image tag
                            struct basic_tag { };
                            /// tag for an Image
                            struct Image_tag : public basic_tag { };
                            /// traits class for image categories
                            template
                            struct image_traits {
                                typedef typename ImageT::image_category image_category;
                            };
                            //
                            std::string const wcsNameForXY0 = "A"; // the name of the WCS to use to save (X0, Y0) to FITS files; e.g. "A"
                        }
                    
                        /*********************************************************************************************************/
                        /// A class used to request that array accesses be checked
                        class CheckIndices {
                        public:
                            explicit CheckIndices(bool check=true) : _check(check) {}
                            operator bool() const { return _check; }
                        private:
                            bool _check;
                        };
                    
                        /*********************************************************************************************************/
                        /// \brief metafunction to extract reference type from PixelT
                        template
                        struct Reference {
                            typedef typename boost::gil::channel_traits::reference type; ///< reference type
                        };
                        /// \brief metafunction to extract const reference type from PixelT    
                        template
                        struct ConstReference {
                            typedef typename boost::gil::channel_traits::const_reference type; ///< const reference type
                        };
                        
                        enum ImageOrigin {PARENT, LOCAL};
                    
                        /// \brief The base class for all %image classed (Image, Mask, MaskedImage, ...)
                        //
                        // You are not expected to use this class directly in your own code; use one of the
                        // specialised subclasses
                        //
                        template
                        class ImageBase : public lsst::daf::base::Persistable,
                                          public lsst::daf::base::Citizen {
                        private:
                            typedef typename lsst::afw::image::detail::types_traits::view_t _view_t;
                            typedef typename lsst::afw::image::detail::types_traits::const_view_t _const_view_t;
                    
                    
                            typedef ndarray::Manager Manager;
                        public:        
                    
                            typedef boost::shared_ptr > Ptr; ///< A shared_ptr to an ImageBase
                            typedef boost::shared_ptr > ConstPtr; ///< A shared_ptr to a const ImageBase
                    
                            typedef detail::basic_tag image_category; ///< trait class to identify type of %image
                    
                            /// A single Pixel of the same type as those in the ImageBase
                            typedef PixelT SinglePixel;
                            /// A pixel in this ImageBase
                            typedef PixelT Pixel;
                            /// A Reference to a PixelT
                            typedef typename Reference::type PixelReference;
                            /// A ConstReference to a PixelT
                            typedef typename ConstReference::type PixelConstReference;
                            /// An xy_locator
                            typedef typename _view_t::xy_locator xy_locator;
                            /// A const_xy_locator
                            typedef typename _view_t::xy_locator::const_t const_xy_locator;
                            /// An STL compliant iterator
                            typedef typename _view_t::iterator iterator;
                            /// An STL compliant const iterator
                            typedef typename _const_view_t::iterator const_iterator;
                            /// An STL compliant reverse iterator
                            typedef typename _view_t::reverse_iterator reverse_iterator;
                            /// An STL compliant const reverse iterator
                            typedef typename _const_view_t::reverse_iterator const_reverse_iterator;
                            /// An iterator for traversing the pixels in a row
                            typedef typename _view_t::x_iterator x_iterator;
                            /// A fast STL compliant iterator for contiguous images
                            /// N.b. The order of pixel access is undefined
                            typedef x_iterator fast_iterator;
                            /// An iterator for traversing the pixels in a row, created from an xy_locator
                            typedef typename _view_t::x_iterator xy_x_iterator;
                            /// A const iterator for traversing the pixels in a row
                            typedef typename _const_view_t::x_iterator const_x_iterator;
                            /// An iterator for traversing the pixels in a column
                            typedef typename _view_t::y_iterator y_iterator;
                            /// An iterator for traversing the pixels in a row, created from an xy_locator
                            typedef typename _view_t::y_iterator xy_y_iterator;
                            /// A const iterator for traversing the pixels in a column
                            typedef typename _const_view_t::y_iterator const_y_iterator;
                            /// A mutable ndarray representation of the image
                            typedef typename ndarray::Array Array;
                            /// An immutable ndarray representation of the image
                            typedef typename ndarray::Array ConstArray;
                    
                            template friend class ImageBase; // needed by generalised copy constructors
                            //
                            /// \brief Convert a type to our SinglePixel type
                            //
                            template
                            static SinglePixel PixelCast(SinglePixelT rhs) {
                                return SinglePixel(rhs);
                            }
                            //
                            // DecoratedImage needs enough access to ImageBase to read data from disk; we might be able to design around this
                            //
                            template friend class DecoratedImage;
                            template friend class MaskedImage;
                            explicit ImageBase(const geom::Extent2I  & dimensions=geom::Extent2I());
                            explicit ImageBase(const geom::Box2I &bbox);
                            ImageBase(const ImageBase& src, const bool deep=false);
                            explicit ImageBase(const ImageBase& src, const geom::Box2I& bbox,
    
    187 2035d06f - const ImageOrigin origin=LOCAL, const bool deep=false);
    ? ^^^ ^
    187 93994d54 + const ImageOrigin origin=PARENT, const bool deep=false);
    ? ^ ^^^^ /// generalised copy constructor /// /// defined here in the header so that the compiler can instantiate N(N-1) conversions between N /// ImageBase types. template ImageBase(const ImageBase& rhs, const bool deep) : lsst::daf::base::Citizen(typeid(this)) { if (!deep) {
    196 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    196 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Only deep copies are permitted for ImageBases with different pixel types"); }
    200 3263f939 - ImageBase tmp(rhs.getBBox(PARENT));
    ? ------
    200 93994d54 + ImageBase tmp(rhs.getBBox());
    copy_and_convert_pixels(rhs._gilView, tmp._gilView); // from boost::gil using std::swap; // See Meyers, Effective C++, Item 25 ImageBase::swap(tmp); // See Meyers, Effective C++, Items 11 and 43 } explicit ImageBase( Array const & array, bool deep = false, geom::Point2I const & xy0 = geom::Point2I() ); virtual ~ImageBase() { } ImageBase& operator=(const ImageBase& rhs); ImageBase& operator=(const PixelT rhs); void operator<<=(const ImageBase& rhs); // // Operators etc. // PixelReference operator()(int x, int y); PixelReference operator()(int x, int y, CheckIndices const&); PixelConstReference operator()(int x, int y) const; PixelConstReference operator()(int x, int y, CheckIndices const&) const; PixelConstReference get0(int x, int y) const { return operator()(x-getX0(), y-getY0()); } PixelConstReference get0(int x, int y, CheckIndices const& check) const { return operator()(x-getX0(), y-getY0(), check); } void set0(int x, int y, const PixelT v) { operator()(x-getX0(), y-getY0()) = v; } void set0(int x, int y, const PixelT v, CheckIndices const& check) { operator()(x-getX0(), y-getY0(), check) = v; } /// Return the number of columns in the %image int getWidth() const { return _gilView.width(); } /// Return the number of rows in the %image int getHeight() const { return _gilView.height(); } /** * Return the %image's column-origin * * This will usually be 0 except for images created using the * ImageBase(fileName, hdu, BBox, mode) ctor or ImageBase(ImageBase, BBox) cctor * The origin can be reset with \c setXY0 */ int getX0() const { return _origin.getX(); } /** * Return the %image's row-origin * * This will usually be 0 except for images created using the * ImageBase(fileName, hdu, BBox, mode) ctor or ImageBase(ImageBase, BBox) cctor * The origin can be reset with \c setXY0 */ int getY0() const { return _origin.getY(); } /** * Return the %image's origin * * This will usually be (0, 0) except for images created using the * ImageBase(fileName, hdu, BBox, mode) ctor or ImageBase(ImageBase, BBox) cctor * The origin can be reset with \c setXY0 */ geom::Point2I getXY0() const { return _origin; } /** * @brief Convert image position to index (nearest integer and fractional parts) * * @return std::pair(nearest integer index, fractional part) */ std::pair positionToIndex( double const pos, ///< image position lsst::afw::image::xOrY const xy ///< Is this a column or row coordinate? ) const { double const fullIndex = pos - PixelZeroPos - (xy == X ? getX0() : getY0()); int const roundedIndex = static_cast(fullIndex + 0.5); double const residual = fullIndex - roundedIndex; return std::pair(roundedIndex, residual); } /** * @brief Convert image index to image position * * The LSST indexing convention is: * * the index of the bottom left pixel is 0,0 * * the position of the center of the bottom left pixel is PixelZeroPos, PixelZeroPos * * @return image position */ inline double indexToPosition( double ind, ///< image index lsst::afw::image::xOrY const xy ///< Is this a column or row coordinate? ) const { return ind + PixelZeroPos + (xy == X ? getX0() : getY0()); } /// Return the %image's size; useful for passing to constructors geom::Extent2I getDimensions() const { return geom::Extent2I(getWidth(), getHeight()); } void swap(ImageBase &rhs); Array getArray(); ConstArray getArray() const; // // Iterators and Locators // iterator begin() const; iterator end() const; reverse_iterator rbegin() const; reverse_iterator rend() const; iterator at(int x, int y) const; fast_iterator begin(bool) const; fast_iterator end(bool) const; /// Return an \c x_iterator to the start of the \c y'th row /// /// Incrementing an \c x_iterator moves it across the row x_iterator row_begin(int y) const { return _gilView.row_begin(y); } /// Return an \c x_iterator to the end of the \c y'th row x_iterator row_end(int y) const { return _gilView.row_end(y); } /// Return an \c x_iterator to the point (x, y) in the %image x_iterator x_at(int x, int y) const { return _gilView.x_at(x, y); } /// Return an \c y_iterator to the start of the \c y'th row /// /// Incrementing an \c y_iterator moves it up the column y_iterator col_begin(int x) const { return _gilView.col_begin(x); } /// Return an \c y_iterator to the end of the \c y'th row y_iterator col_end(int x) const { return _gilView.col_end(x); } /// Return an \c y_iterator to the point (x, y) in the %image y_iterator y_at(int x, int y) const { return _gilView.y_at(x, y); } /// Return an \c xy_locator at the point (x, y) in the %image /// /// Locators may be used to access a patch in an image xy_locator xy_at(int x, int y) const { return xy_locator(_gilView.xy_at(x, y)); } /** * Set the ImageBase's origin * * The origin is usually set by the constructor, so you shouldn't need this function * * \note There are use cases (e.g. memory overlays) that may want to set these values, but * don't do so unless you are an Expert. */ void setXY0(geom::Point2I const origin) { _origin=origin; } /** * Set the ImageBase's origin * * The origin is usually set by the constructor, so you shouldn't need this function * * \note There are use cases (e.g. memory overlays) that may want to set these values, but * don't do so unless you are an Expert. */ void setXY0(int const x0, int const y0) { setXY0(geom::Point2I(x0,y0)); }
    377 5673d2fa - geom::Box2I getBBox(ImageOrigin origin=LOCAL) const {
    ? ^^^ ^
    377 93994d54 + geom::Box2I getBBox(ImageOrigin origin=PARENT) const {
    ? ^ ^^^^ if (origin == PARENT) { return geom::Box2I(_origin, getDimensions()); } else return geom::Box2I(geom::Point2I(0,0), getDimensions()); } private: geom::Point2I _origin; Manager::Ptr _manager; _view_t _gilView; //oring of ImageBase in some larger image as returned to and manipulated //by the user protected: #if !defined(SWIG) static _view_t _allocateView(geom::Extent2I const & dimensions, Manager::Ptr & manager); static _view_t _makeSubView( geom::Extent2I const & dimensions, geom::Extent2I const & offset, const _view_t & view ); _view_t _getRawView() const { return _gilView; } #endif inline bool isContiguous() const { return begin()+getWidth()*getHeight() == end(); } }; template void swap(ImageBase& a, ImageBase& b); /************************************************************************************************************/ /// A class to represent a 2-dimensional array of pixels template class Image : public ImageBase { public: template friend class MaskedImage; typedef boost::shared_ptr > Ptr; typedef boost::shared_ptr > ConstPtr; typedef detail::Image_tag image_category; #if !defined(SWIG) /// A templated class to return this classes' type (present in Image/Mask/MaskedImage) template struct ImageTypeFactory { /// Return the desired type typedef Image type; }; #endif template friend class Image; // needed by generalised copy constructors explicit Image(unsigned int width, unsigned int height, PixelT initialValue=0); explicit Image(geom::Extent2I const & dimensions=geom::Extent2I(), PixelT initialValue=0); explicit Image(geom::Box2I const & bbox, PixelT initialValue=0);
    437 2035d06f - explicit Image(Image const & rhs, geom::Box2I const & bbox, ImageOrigin const origin=LOCAL,
    ? ^^^ ^
    437 93994d54 + explicit Image(Image const & rhs, geom::Box2I const & bbox, ImageOrigin const origin=PARENT,
    ? ^ ^^^^ const bool deep=false); Image(const Image& rhs, const bool deep=false); /** * @brief Construct an Image by reading a regular FITS file. * * @param[in] fileName File to read. * @param[in] hdu HDU to read, 1-indexed (i.e. 1=Primary HDU). The special value * of 0 reads the Primary HDU unless it is empty, in which case it * reads the first extension HDU. * @param[in,out] metadata Metadata read from the header (may be null). * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. */ explicit Image( std::string const & fileName, int hdu=0, PTR(lsst::daf::base::PropertySet) metadata=PTR(lsst::daf::base::PropertySet)(), geom::Box2I const & bbox=geom::Box2I(),
    457 271e8097 - ImageOrigin origin=LOCAL
    ? ^^^ ^
    457 93994d54 + ImageOrigin origin=PARENT
    ? ^ ^^^^ ); /** * @brief Construct an Image by reading a FITS image in memory. * * @param[in] manager An object that manages the memory buffer to read. * @param[in] hdu HDU to read, 1-indexed (i.e. 1=Primary HDU). The special value * of 0 reads the Primary HDU unless it is empty, in which case it * reads the first extension HDU. * @param[in,out] metadata Metadata read from the header (may be null). * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. */ explicit Image( fits::MemFileManager & manager, int hdu=0, PTR(lsst::daf::base::PropertySet) metadata=PTR(lsst::daf::base::PropertySet)(), geom::Box2I const & bbox=geom::Box2I(),
    476 271e8097 - ImageOrigin origin=LOCAL
    ? ^^^ ^
    476 93994d54 + ImageOrigin origin=PARENT
    ? ^ ^^^^ ); /** * @brief Construct an Image from an already-open FITS object. * * @param[in] fitsfile A FITS object to read from, already at the desired HDU. * @param[in,out] metadata Metadata read from the header (may be null). * @param[in] bbox If non-empty, read only the pixels within the bounding box. * @param[in] origin Coordinate system of the bounding box; if PARENT, the bounding box * should take into account the xy0 saved with the image. */ explicit Image( fits::Fits & fitsfile, PTR(lsst::daf::base::PropertySet) metadata=PTR(lsst::daf::base::PropertySet)(), geom::Box2I const & bbox=geom::Box2I(),
    492 271e8097 - ImageOrigin origin=LOCAL
    ? ^^^ ^
    492 93994d54 + ImageOrigin origin=PARENT
    ? ^ ^^^^ ); // generalised copy constructor template Image(Image const& rhs, const bool deep) : image::ImageBase(rhs, deep) {} explicit Image(ndarray::Array const & array, bool deep = false, geom::Point2I const & xy0 = geom::Point2I()) : image::ImageBase(array, deep, xy0) {} virtual ~Image() { } // // Assignment operators are not inherited // Image& operator=(const PixelT rhs); Image& operator=(const Image& rhs); /** * @brief Write an image to a regular FITS file. * * @param[in] fileName Name of the file to write. * @param[in] metadata Additional values to write to the header (may be null). * @param[in] mode "w"=Create a new file; "a"=Append a new HDU. */ void writeFits( std::string const& fileName, CONST_PTR(lsst::daf::base::PropertySet) metadata = CONST_PTR(lsst::daf::base::PropertySet)(), std::string const& mode="w" ) const; /** * @brief Write an image to a FITS RAM file. * * @param[in] manager Manager object for the memory block to write to. * @param[in] metadata Additional values to write to the header (may be null). * @param[in] mode "w"=Create a new file; "a"=Append a new HDU. */ void writeFits( fits::MemFileManager & manager, CONST_PTR(lsst::daf::base::PropertySet) metadata = CONST_PTR(lsst::daf::base::PropertySet)(), std::string const& mode="w" ) const; /** * @brief Write an image to an open FITS file object. * * @param[in] fitsfile A FITS file already open to the desired HDU. * @param[in] metadata Additional values to write to the header (may be null). */ void writeFits( fits::Fits & fitsfile, CONST_PTR(lsst::daf::base::PropertySet) metadata = CONST_PTR(lsst::daf::base::PropertySet)() ) const; /** * @brief Read an Image from a regular FITS file. * * @param[in] filename Name of the file to read. * @param[in] hdu Number of the "header-data unit" to read (where 1 is the Primary HDU). * The default value of 0 is interpreted as "the first HDU with NAXIS != 0". */ static Image readFits(std::string const & filename, int hdu=0) { return Image(filename, hdu); } /** * @brief Read an Image from a FITS RAM file. * * @param[in] manager Object that manages the memory to be read. * @param[in] hdu Number of the "header-data unit" to read (where 1 is the Primary HDU). * The default value of 0 is interpreted as "the first HDU with NAXIS != 0". */ static Image readFits(fits::MemFileManager & manager, int hdu=0) { return Image(manager, hdu); } void swap(Image &rhs); // // Operators etc. // void operator+=(PixelT const rhs); virtual void operator+=(Imageconst & rhs); void operator+=(lsst::afw::math::Function2 const& function); void scaledPlus(double const c, Imageconst & rhs); void operator-=(PixelT const rhs); void operator-=(Image const& rhs); void operator-=(lsst::afw::math::Function2 const& function); void scaledMinus(double const c, Imageconst & rhs); void operator*=(PixelT const rhs); void operator*=(Image const& rhs); void scaledMultiplies(double const c, Imageconst & rhs); void operator/=(PixelT const rhs); void operator/=(Image const& rhs); void scaledDivides(double const c, Imageconst & rhs); // In-place per-pixel sqrt(). Useful when handling variance planes. void sqrt(); protected: using ImageBase::_getRawView; private: LSST_PERSIST_FORMATTER(lsst::afw::formatters::ImageFormatter) }; template void operator+=(Image &lhs, Image const& rhs); template void operator-=(Image &lhs, Image const& rhs); template void operator*=(Image &lhs, Image const& rhs); template void operator/=(Image &lhs, Image const& rhs); template void swap(Image& a, Image& b); /************************************************************************************************************/ /** * \brief A container for an Image and its associated metadata */ template class DecoratedImage : public lsst::daf::base::Persistable, public lsst::daf::base::Citizen { public: /// shared_ptr to a DecoratedImage typedef boost::shared_ptr Ptr; /// shared_ptr to a const DecoratedImage typedef boost::shared_ptr ConstPtr; /// shared_ptr to the Image typedef PTR(Image) ImagePtr; /// shared_ptr to the Image as const typedef CONST_PTR(Image) ImageConstPtr; explicit DecoratedImage(const geom::Extent2I & dimensions=geom::Extent2I()); explicit DecoratedImage(const geom::Box2I & bbox); explicit DecoratedImage(PTR(Image) rhs); DecoratedImage(DecoratedImage const& rhs, const bool deep=false); explicit DecoratedImage( std::string const& fileName, const int hdu=0, geom::Box2I const& bbox=geom::Box2I(),
    634 3263f939 - ImageOrigin const origin = LOCAL
    ? ^^^ ^
    634 93994d54 + ImageOrigin const origin = PARENT
    ? ^ ^^^^ ); DecoratedImage& operator=(const DecoratedImage& image); PTR(lsst::daf::base::PropertySet) getMetadata() const { return _metadata; } void setMetadata(PTR(lsst::daf::base::PropertySet) metadata) { _metadata = metadata; } /// Return the number of columns in the %image int getWidth() const { return _image->getWidth(); } /// Return the number of rows in the %image int getHeight() const { return _image->getHeight(); } /// Return the %image's column-origin int getX0() const { return _image->getX0(); } /// Return the %image's row-origin int getY0() const { return _image->getY0(); } /// Return the %image's size; useful for passing to constructors const geom::Extent2I getDimensions() const { return _image->getDimensions(); } void swap(DecoratedImage &rhs); void writeFits( std::string const& fileName, CONST_PTR(lsst::daf::base::PropertySet) metadata = CONST_PTR(lsst::daf::base::PropertySet)(), std::string const& mode="w" ) const; /// Return a shared_ptr to the DecoratedImage's Image ImagePtr getImage() { return _image; } /// Return a shared_ptr to the DecoratedImage's Image as const ImageConstPtr getImage() const { return _image; } /** * Return the DecoratedImage's gain * \note This is mostly just a place holder for other properties that we might * want to associate with a DecoratedImage */ double getGain() const { return _gain; } /// Set the DecoratedImage's gain void setGain(double gain) { _gain = gain; } private: LSST_PERSIST_FORMATTER(lsst::afw::formatters::DecoratedImageFormatter) PTR(Image) _image; PTR(lsst::daf::base::PropertySet) _metadata; double _gain; void init(); }; template void swap(DecoratedImage& a, DecoratedImage& b); }}} // lsst::afw::image #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    5673d2fa

    commit 5673d2fa593579e624f1a8d1bc54a75264b0ac12
    Author: Robert Lupton the Good 
    Date:   Wed Dec 21 16:16:59 2011 -0500
    
        Added a missing default LOCAL ImageOrigin
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    2035d06f

    commit 2035d06f093eae708fc33e59f8733d7ed9303872
    Author: rhl 
    Date:   Mon Aug 22 19:16:06 2011 +0000
    
        Provided default of LOCAL for ImageOrigin in cctors
    

    271e8097

    commit 271e8097c7ebbadd88d2d43588a80148fdce619a
    Author: Jim Bosch 
    Date:   Mon Nov 19 12:50:21 2012 -0500
    
        Fix up and relocate doxygen for FITS-reading ctors.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    examples/timeWarpExposure.py

    Diff:

                    #!/usr/bin/env python
                    
                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    
                    import math
                    import sys
                    import os
                    import time
                    
    
    30 7cbb2bb9 + import lsst.utils
    30 59a197d3 - import eups
    31 59a197d3 -
    import lsst.daf.base as dafBase import lsst.afw.geom as afwGeom import lsst.afw.image as afwImage import lsst.afw.math as afwMath MaxIter = 20 MaxTime = 1.0 # seconds SaveImages = False DegPerRad = 180.0 / math.pi DegreesFlag = afwGeom.degrees def setDegreesFlag(newValue): """Set global DegreesFlag; avoids a syntax warning in makeWcs """ global DegreesFlag DegreesFlag = newValue
    50 7cbb2bb9 + afwdataDir = lsst.utils.getPackageDir("afwdata")
    51 59a197d3 - dataDir = eups.productDir("afwdata")
    52 59a197d3 - if not dataDir:
    53 59a197d3 - raise RuntimeError("Must set up afwdata")
    55 59a197d3 - InputExposurePath = os.path.join(dataDir, "ImSim/calexp/v85408556-fr/R23/S11.fits")
    52 7cbb2bb9 + InputExposurePath = os.path.join(afwdataDir, "ImSim/calexp/v85408556-fr/R23/S11.fits")
    ? +++ def timeWarp(destExposure, srcExposure, warpingControl): """Time warpExposure int warpExposure( DestExposureT &destExposure, SrcExposureT const &srcExposure, SeparableKernel &warpingKernel, int const interpLength=0); @param destExposure: output exposure (including a WCS) @param srcExposure: input exposure (including a WCS) @param warpingKernel: warping kernel @param interpLength: interpolation length (0 for no interpolation) @return (elapsed time in seconds, number of iterations) """ startTime = time.time(); for nIter in range(1, MaxIter + 1): goodPix = afwMath.warpExposure(destExposure, srcExposure, warpingControl) endTime = time.time() if endTime - startTime > MaxTime: break return (endTime - startTime, nIter, goodPix) def makeWcs(projName, destCtrInd, skyOffset, rotAng, scaleFac, srcWcs, srcCtrInd): """Make an RA/Dec WCS from another RA/Dec WCS @param projName: projection, e,g, "TAN" @param destCtrInd: pixel index of center of WCS; used to compute CRPIX; typically the center of the destination exposure @param skyOffset: offset in sky coords (axis 1, axis 2 degrees): dest sky pos at destCtrInd = src sky pos at destCtrInd + skyOffset @param rotAng: change of orientation with respect to srcWcs, in degrees @param scaleFac: output resolution / input resolution @param srcWcs: reference WCS @param srcCtrInd: index of source pixel whose sky matches destCtrInd on new WCS typically the center of the source exposure """ ps = dafBase.PropertySet() destCtrFitsPix = afwGeom.Point2D(*[ind + 1.0 for ind in destCtrInd]) srcCtrFitsPix = afwGeom.Point2D(*[ind + 1.0 for ind in srcCtrInd]) srcOffFitsPix = srcCtrFitsPix + afwGeom.Extent2D(1.0, 0.0) # offset 1 pixel in x to compute orient & scale try: srcCtrSkyPos = srcWcs.pixelToSky(srcCtrFitsPix).getPosition(DegreesFlag) except Exception: import lsst.afw.coord as afwCoord setDegreesFlag(afwCoord.DEGREES) srcCtrSkyPos = srcWcs.pixelToSky(srcCtrFitsPix).getPosition(DegreesFlag) srcOffSkyPos = srcWcs.pixelToSky(srcOffFitsPix).getPosition(DegreesFlag) srcSkyOff = srcOffSkyPos - srcCtrSkyPos srcAngleRad = math.atan2(srcSkyOff[1], srcSkyOff[0]) destAngleRad = srcAngleRad + (rotAng / DegPerRad) srcScale = math.sqrt(srcSkyOff[0]**2 + srcSkyOff[1]**2) # in degrees/pixel destScale = srcScale / scaleFac for i in range(2): ip1 = i + 1 ctypeStr = ("%-5s%3s" % (("RA", "DEC")[i], projName)).replace(" ", "-") ps.add("CTYPE%1d" % (ip1,), ctypeStr) ps.add("CRPIX%1d" % (ip1,), destCtrFitsPix[i]) ps.add("CRVAL%1d" % (ip1,), srcCtrSkyPos[i] + skyOffset[i]) ps.add("RADECSYS", "ICRS") ps.add("EQUINOX", 2000) ps.add("CD1_1", -destScale * math.cos(destAngleRad)) ps.add("CD2_1", destScale * math.sin(destAngleRad)) ps.add("CD1_2", destScale * math.sin(destAngleRad)) ps.add("CD2_2", destScale * math.cos(destAngleRad)) return afwImage.makeWcs(ps) def run(): if len(sys.argv) < 2: srcExposure = afwImage.ExposureF(InputExposurePath) if True: bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(2000, 2000)) srcExposure = afwImage.ExposureF(srcExposure, bbox, afwImage.LOCAL, False) else: srcExposure = afwImage.ExposureF(sys.argv[1]) srcWcs = srcExposure.getWcs() srcDim = srcExposure.getDimensions() srcCtrInd = [int(d / 2) for d in srcDim] # make the destination exposure small enough that even after rotation and offset # (by reasonable amounts) there are no edge pixels destDim = afwGeom.Extent2I(*[int(sd * 0.5) for sd in srcDim]) destExposure = afwImage.ExposureF(destDim) destCtrInd = [int(d / 2) for d in destDim] maskKernelName = "" cacheSize = 0 print "Warping", InputExposurePath print "Source (sub)image size:", srcDim print "Destination image size:", destDim print print "test# interp scaleFac skyOffset rotAng kernel goodPix time/iter" print ' (pix) (RA, Dec ") (deg) (sec)' testNum = 1 for interpLength in (0, 1, 5, 10): for scaleFac in (1.2,): # (1.0, 1.5): for skyOffsetArcSec in ((0.0, 0.0),): # ((0.0, 0.0), (10.5, -5.5)): skyOffset = [so / 3600.0 for so in skyOffsetArcSec] for rotAng, kernelName in ( (0.0, "bilinear"), (0.0, "lanczos2"), (0.0, "lanczos3"), (45.0, "lanczos3"), ): warpingControl = afwMath.WarpingControl( kernelName, maskKernelName, cacheSize, interpLength, ) destWcs = makeWcs( projName = "TAN", destCtrInd = destCtrInd, skyOffset = skyOffset, rotAng = rotAng, scaleFac = scaleFac, srcWcs = srcWcs, srcCtrInd = srcCtrInd, ) destExposure.setWcs(destWcs) dTime, nIter, goodPix = timeWarp(destExposure, srcExposure, warpingControl) print "%4d %5d %8.1f %6.1f, %6.1f %7.1f %10s %8d %6.2f" % ( testNum, interpLength, scaleFac, skyOffsetArcSec[0], skyOffsetArcSec[1], rotAng, kernelName, goodPix, dTime/float(nIter)) if SaveImages: destExposure.writeFits("warpedExposure%03d.fits" % (testNum,)) testNum += 1 if __name__ == "__main__": run()

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    59a197d3

    commit 59a197d30f304172f8e3a84a92ad25decada2009
    Author: rowen 
    Date:   Wed May 18 02:54:52 2011 +0000
    
        Speed up warpExposure a bit and add a timing example
        (which needs a minor tweak to run older versions of afw).
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/geom/CoordinateExpr.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include "lsst/afw/geom/CoordinateBase.h"
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/geom/Extent.h"
                    
                    namespace geom = lsst::afw::geom;
                    
                    template 
                    geom::CoordinateExpr geom::CoordinateExpr::and_(CoordinateExpr const & other) const {
                        CoordinateExpr r(*this);
    
    32 7ccf406e - for (register int n=0; n ? ---------
    32 51a67dff + for (int n=0; n if (!other[n]) r[n] = false; } return r; } template geom::CoordinateExpr geom::CoordinateExpr::or_(CoordinateExpr const & other) const { CoordinateExpr r(*this);
    41 7ccf406e - for (register int n=0; n ? ---------
    41 51a67dff + for (int n=0; n if (other[n]) r[n] = true; } return r; } template geom::CoordinateExpr geom::CoordinateExpr::not_() const { CoordinateExpr r;
    50 7ccf406e - for (register int n=0; n ? ---------
    50 51a67dff + for (int n=0; n if (!this->operator[](n)) r[n] = true; } return r; } template class geom::CoordinateExpr<2>; template class geom::CoordinateExpr<3>;

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7ccf406e

    commit 7ccf406eabf8ad8f018a7d66cf517ddeaa94d9e1
    Author: jbosch 
    Date:   Mon Dec 14 19:43:59 2009 +0000
    
        afw/892:
         - implementations for geom (all but Box now done)
         - fixed compilation errors in ellipses and tests for ellipses
         - merged updates from trunk in (fixed an obvious typo introduced in math::offsetImage by the merge)
    

    Commits in /Users/nate/repos_lsst/afw/

    51a67dff

    commit 51a67dff1f2d5067d66ad025fe1efee37aeca339
    Author: Russell Owen 
    Date:   Tue Oct 14 12:50:44 2014 -0700
    
        Remove use of deprecated C++ keyword "register"
    

    Return to list

    include/lsst/afw/gpu/GpuExceptions.h

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008 - 2012 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #ifndef LSST_AFW_MATH_DETAIL_GPU_EXCEPTIONS_H
                    #define LSST_AFW_MATH_DETAIL_GPU_EXCEPTIONS_H
                    /**
                     * @file
                     *
                     * @brief additional GPU exceptions
                     *
                     * @author Kresimir Cosic
                     *
                     * @ingroup afw
                     */
                    
                    #include "lsst/pex/exceptions.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace gpu {
                    
    
    43 af8f5ebe - LSST_EXCEPTION_TYPE(GpuMemoryException, lsst::pex::exceptions::RuntimeErrorException, lsst::afw::gpu::GpuMemoryException)
    ? ^^^^^^ ^ --------- ^^^^^^ ^
    43 21597d88 + LSST_EXCEPTION_TYPE(GpuMemoryError, lsst::pex::exceptions::RuntimeError, lsst::afw::gpu::GpuMemoryError)
    ? ^^ ^ ^^ ^
    44 af8f5ebe - LSST_EXCEPTION_TYPE(GpuRuntimeErrorException, lsst::pex::exceptions::RuntimeErrorException, lsst::afw::gpu::GpuRuntimeErrorException)
    ? --------- --------- ---------
    44 21597d88 + LSST_EXCEPTION_TYPE(GpuRuntimeError, lsst::pex::exceptions::RuntimeError, lsst::afw::gpu::GpuRuntimeError)
    } } } #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    af8f5ebe

    commit af8f5ebef4f524d96fa4c824d3c8eb1cf11a6869
    Author: Kresimir Cosic 
    Date:   Mon Feb 27 03:39:36 2012 +0100
    
        Added afw::gpu namespace, reorganized files and interfaces to use this namespace
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/table/Catalog.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_Catalog_h_INCLUDED
                    #define AFW_TABLE_Catalog_h_INCLUDED
                    
                    #include 
                    
                    #include "boost/iterator/iterator_adaptor.hpp"
                    #include "boost/iterator/transform_iterator.hpp"
                    
                    #include "lsst/base.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/table/fwd.h"
                    #include "lsst/afw/table/io/FitsWriter.h"
                    #include "lsst/afw/table/io/FitsReader.h"
                    #include "lsst/afw/table/SchemaMapper.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    /**
                     *  @brief Iterator class for CatalogT.
                     *
                     *  Iterators dereference to record references or const references, even though the CatalogT container
                     *  is based on a vector of shared_ptr internally.  This is usually very convenient (and is one of
                     *  the reasons for having a custom container class in the first place).
                     *
                     *  Sometimes, however, we'd like to get a shared_ptr from an iterator (especially because records
                     *  are noncopyable).  With that in mind, CatalogIterator is implicitly convertible to the shared_ptr
                     *  type it holds internally, and can also be assigned a shared_ptr to set the pointer in the 
                     *  underlying container.  This conversion makes sense from the perspective that both iterators
                     *  and smart pointers mimic the interface of pointers and provide the same interface to get at
                     *  the underlying record.
                     */
                    template 
                    class CatalogIterator
                        : public boost::iterator_adaptor,BaseT,typename BaseT::value_type::element_type>
                    {
                    public:
                    
                        CatalogIterator() {}
                    
                        template 
                        CatalogIterator(CatalogIterator const & other) :
                            CatalogIterator::iterator_adaptor_(other.base())
                        {}
                    
                        explicit CatalogIterator(BaseT const & base) : CatalogIterator::iterator_adaptor_(base) {}
                    
                        template 
                        operator PTR(RecordT) () const { return *this->base(); }
                    
                        template 
                        CatalogIterator & operator=(PTR(RecordT) const & other) const {
                            *this->base() = other;
                            return *this;
                        }
                    
                    private:
                        friend class boost::iterator_core_access;
                        typename BaseT::value_type::element_type & dereference() const { return **this->base(); }
                    };
                    
                    /**
                     *  @brief A custom container class for records, based on std::vector.
                     *
                     *  CatalogT wraps a std::vector in an interface that looks more
                     *  like a std::vector; its iterators and accessors return references
                     *  or const references, rather than pointers, making them easier to use.  It
                     *  also holds a table, which is used to allocate new records and determine the
                     *  schema, but no checking is done to ensure that records added to the catalog
                     *  use the same table or indeed have the same schema.
                     *
                     *  Because a CatalogT is holds shared_ptrs internally, many of its operations
                     *  can be either shallow or deep, with new deep copies allocated by the
                     *  catalog's table object.  New records can be also be inserted by pointer
                     *  (shallow) or by value (deep).
                     *
                     *  The constness of records is determined by the constness of the first
                     *  template parameter to CatalogT; a container instance is always either const
                     *  or non-const in that respect (like smart pointers).  Also like smart
                     *  pointers, const member functions (and by extension, const_iterators) do not
                     *  allow the underlying pointers to be changed, while non-const member
                     *  functions and iterators do.
                     *
                     *  CatalogT does not permit empty (null) pointers as elements.  As a result,
                     *  CatalogT has no resize member function.
                     *
                     *  CatalogT has a very different interface in Python; it mimics Python's list
                     *  instead of C++'s std::vector.  It is also considerably simpler, because it
                     *  doesn't need to deal with iterator ranges or the distinction between
                     *  references and shared_ptrs to records.  See the Python docstring for more
                     *  information.
                     */
                    template 
                    class CatalogT {
                        typedef std::vector Internal;
                    public:
                    
                        typedef RecordT Record;
                        typedef typename Record::Table Table;
                        typedef typename Record::ColumnView ColumnView;
                    
                        typedef RecordT value_type;
                        typedef RecordT & reference;
                        typedef PTR(RecordT) pointer;
                        typedef typename Internal::size_type size_type;
                        typedef typename Internal::difference_type difference_type;
                        typedef CatalogIterator iterator;
                        typedef CatalogIterator const_iterator;
                    
                        /// @brief Return the table associated with the catalog.
                        PTR(Table) getTable() const { return _table; }
                    
                        /// @brief Return the schema associated with the catalog's table.
                        Schema getSchema() const { return _table->getSchema(); }
                    
                        /**
                         *  @brief Construct a catalog from a table (or nothing).
                         *
                         *  A catalog with no table is considered invalid; a valid table must be assigned to it
                         *  before it can be used.
                         */
                        explicit CatalogT(PTR(Table) const & table = PTR(Table)()) : _table(table), _internal() {}
                    
                        /// @brief Construct a catalog from a schema, creating a table with Table::make(schema).
                        explicit CatalogT(Schema const & schema) : _table(Table::make(schema)), _internal() {}
                    
                        /**
                         *  @brief Construct a catalog from a table and an iterator range.
                         *
                         *  If deep is true, new records will be created using table->copyRecord before being inserted.
                         *  If deep is false, records will be not be copied, but they must already be associated with
                         *  the given table.  The table itself is never deep-copied.
                         *
                         *  The iterator must dereference to a record reference or const reference rather than a pointer,
                         *  but should be implicitly convertible to a record pointer as well (see CatalogIterator).
                         */
                        template 
                        CatalogT(PTR(Table) const & table, InputIterator first, InputIterator last, bool deep=false) :
                            _table(table), _internal()
                        {
                            insert(end(), first, last, deep);
                        }
                    
                        /// Shallow copy constructor.
                        CatalogT(CatalogT const & other) : _table(other._table), _internal(other._internal) {}
                    
                        /**
                         *  @brief Shallow copy constructor from a container containing a related record type.
                         *
                         *  This conversion only succeeds if OtherRecordT is convertible to RecordT and OtherTable is
                         *  convertible to Table.
                         */
                        template 
                        CatalogT(CatalogT const & other) :
                            _table(other.getTable()), _internal(other.begin().base(), other.end().base())
                        {}
                    
                        /// Shallow assigment.
                        CatalogT & operator=(CatalogT const & other) {
                            if (&other != this) {
                                _table = other._table;
                                _internal = other._internal;
                            }
                            return *this;
                        }
                    
                        /**
                         *  @brief Return the subset of a catalog corresponding to the True values of the given mask array.
                         *
                         *  The returned array's records are shallow copies, and hence will not in general be contiguous.
                         */
                        CatalogT subset(ndarray::Array const & mask) const {
                            if (size_type(mask.size()) != size()) {
                                throw LSST_EXCEPT(
    
    175 9e1f03f1 - pex::exceptions::LengthErrorException,
    ? ---------
    175 21597d88 + pex::exceptions::LengthError,
    (boost::format("Mask array with %d elements applied to catalog with %d elements") % mask.size() % size()).str() ); } CatalogT result(getTable()); ndarray::Array::Iterator maskIter = mask.begin(); const_iterator catIter = begin(); for (; maskIter != mask.end(); ++maskIter, ++catIter) { if (*maskIter) result.push_back(catIter); } return result; } /** * @brief Returns a shallow copy of a subset of this Catalog. The arguments * correspond to python's slice() syntax. */ CatalogT subset(std::ptrdiff_t startd, std::ptrdiff_t stopd, std::ptrdiff_t step) const { /* Python's slicing syntax is weird and wonderful. Both the "start" and "stop" indices can be negative, which means the abs() of the index less than the size; [-1] means the last item. Moreover, it's possible to have a negative index less than -len(); it will get clipped. That is in fact one way to slice *backward* through the array *and* include element 0; >>> range(10)[5:-20:-1] [5, 4, 3, 2, 1, 0] The clipping tests in this function look more complicated than they need to be, but that is partly because there are some weird edge cases. Also, ptrdiff_t vs size_t introduces some annoying complexity. Note that the args are "startd"/"stopd" (not "start"/"stop"). There is a fairly complete set of tests in tests/ticket2026.py; if you try to simplify this function, be sure they continue to pass. */ size_type S = size(); size_type start, stop = 0; // Python doesn't allow step == 0 if (step == 0) { throw LSST_EXCEPT(
    219 5819ddee - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    219 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Step cannot be zero" ); } // Basic negative indexing rule: first add size if (startd < 0) { startd += S; } if (stopd < 0) { stopd += S; } // Start gets clipped to zero; stop does not (yet). if (startd < 0) { startd = 0; } // Now start is non-negative, so can cast to size_t. start = (size_type)startd; if (start > S) { start = S; } if (step > 0) { // When stepping forward, stop gets clipped at zero, // so is non-negative and can get cast to size_t. if (stopd < 0) { stopd = 0; } stop = (size_type)stopd; if (stop > S) { stop = S; } } else if (step < 0) { // When stepping backward, stop gets clipped at -1 so that slices // including 0 are possible. if (stopd < 0) { stopd = -1; } } if (((step > 0) && (start >= stop)) || ((step < 0) && ((std::ptrdiff_t)start <= stopd))) { // Empty range return CatalogT(getTable(), begin(), begin()); } if (step == 1) { // Use the iterator-based constructor for this simple case assert(start >= 0); assert(stop > 0); assert(start < S); assert(stop <= S); return CatalogT(getTable(), begin()+start, begin()+stop); } // Build a new CatalogT and copy records into it. CatalogT cat(getTable()); size_type N = 0; if (step >= 0) { N = (stop - start) / step + (((stop - start) % step) ? 1 : 0); } else { N = (size_t)((stopd - (std::ptrdiff_t)start) / step + (((stopd - (std::ptrdiff_t)start) % step) ? 1 : 0)); } cat.reserve(N); if (step >= 0) { for (size_type i=start; istopd; i+=step) { cat.push_back(get(i)); } } return cat; } /** * @brief Write a FITS binary table to a regular file. * * @param[in] filename Name of the file to write. * @param[in] mode "a" to append a new HDU, "w" to overwrite any existing file. * @param[in] flags Table-subclass-dependent bitflags that control the details of how to * read the catalogs. See e.g. SourceFitsFlags. */ void writeFits(std::string const & filename, std::string const & mode="w", int flags=0) const { io::FitsWriter::apply(filename, mode, *this, flags); } /** * @brief Write a FITS binary table to a RAM file. * * @param[in,out] manager Object that manages the memory to write to. * @param[in] mode "a" to append a new HDU, "w" to overwrite any existing file. * @param[in] flags Table-subclass-dependent bitflags that control the details of how to * read the catalogs. See e.g. SourceFitsFlags. */ void writeFits(fits::MemFileManager & manager, std::string const & mode="w", int flags=0) const { io::FitsWriter::apply(manager, mode, *this, flags); } /** * @brief Write a FITS binary table to an open file object. * * @param[in,out] fitsfile Fits file object to write to. * @param[in] flags Table-subclass-dependent bitflags that control the details of how to * read the catalogs. See e.g. SourceFitsFlags. */ void writeFits(fits::Fits & fitsfile, int flags=0) const { io::FitsWriter::apply(fitsfile, *this, flags); } /** * @brief Read a FITS binary table from a regular file. * * @param[in] filename Name of the file to read. * @param[in] hdu Number of the "header-data unit" to read (where 1 is the Primary HDU). * The default value of 0 is interpreted as "the first HDU with NAXIS != 0". * @param[in] flags Table-subclass-dependent bitflags that control the details of how to read * the catalog. See e.g. SourceFitsFlags. */ static CatalogT readFits(std::string const & filename, int hdu=0, int flags=0) { return io::FitsReader::apply(filename, hdu, flags); } /** * @brief Read a FITS binary table from a RAM file. * * @param[in] manager Object that manages the memory to be read. * @param[in] hdu Number of the "header-data unit" to read (where 1 is the Primary HDU). * The default value of 0 is interpreted as "the first HDU with NAXIS != 0". * @param[in] flags Table-subclass-dependent bitflags that control the details of how to read * the catalog. See e.g. SourceFitsFlags. */ static CatalogT readFits(fits::MemFileManager & manager, int hdu=0, int flags=0) { return io::FitsReader::apply(manager, hdu, flags); } /** * @brief Read a FITS binary table from a file object already at the correct extension. * * @param[in] fitsfile Fits file object to read from. * @param[in] flags Table-subclass-dependent bitflags that control the details of how to read * the catalog. See e.g. SourceFitsFlags. */ static CatalogT readFits(fits::Fits & fitsfile, int flags=0) { return io::FitsReader::apply(fitsfile, flags); } /** * @brief Return a ColumnView of this catalog's records. *
    369 159b2bee - * Will throw RuntimeErrorException if records are not contiguous.
    ? ---------
    369 21597d88 + * Will throw RuntimeError if records are not contiguous.
    */ ColumnView getColumnView() const { if (boost::is_const::value) { throw LSST_EXCEPT(
    374 fee6a99b - pex::exceptions::LogicErrorException,
    ? ---------
    374 21597d88 + pex::exceptions::LogicError,
    "Cannot get a column view from a CatalogT (as column views are always " "non-const views)." ); } return ColumnView::make(_table, begin(), end()); } /// @brief Return true if all records are contiguous. bool isContiguous() const { return ColumnView::isRangeContiguous(_table, begin(), end()); } //@{ /** * Iterator access. * * @sa CatalogIterator */ iterator begin() { return iterator(_internal.begin()); } iterator end() { return iterator(_internal.end()); } const_iterator begin() const { return const_iterator(_internal.begin()); } const_iterator end() const { return const_iterator(_internal.end()); } //@} /// Return true if the catalog has no records. bool empty() const { return _internal.empty(); } /// Return the number of elements in the catalog. size_type size() const { return _internal.size(); } /// Return the maximum number of elements allowed in a catalog. size_type max_size() const { return _internal.max_size(); } /** * @brief Return the capacity of the catalog. * * This is computed as the sum of the current size and the unallocated space in the table. It * does not reflect the size of the internal vector, and hence cannot be used to judge when * iterators may be invalidated. */ size_type capacity() const { return _internal.size() + _table->getBufferSize(); } /** * @brief Increase the capacity of the catalog to the given size. * * This can be used to guarantee that the catalog will be contiguous, but it only affects * records constructed after reserve(). */ void reserve(size_type n) { if (n <= _internal.size()) return; _table->preallocate(n - _internal.size()); } /// Return the record at index i. reference operator[](size_type i) const { return *_internal[i]; } /// Return the record at index i (throws std::out_of_range). reference at(size_type i) const { return *_internal.at(i); } /// Return the first record. reference front() const { return *_internal.front(); } /// Return the last record. reference back() const { return *_internal.back(); } /// Return a pointer to the record at index i. PTR(RecordT) const get(size_type i) const { return _internal[i]; } /// Set the record at index i to a pointer. void set(size_type i, PTR(RecordT) const & p) { _internal[i] = p; } /** * @brief Replace the contents of the table with an iterator range. * * Delegates to insert(); look there for more information. */ template void assign(InputIterator first, InputIterator last, bool deep=false) { clear(); insert(end(), first, last, deep); } /// @brief Add a copy of the given record to the end of the catalog. void push_back(Record const & r) { PTR(RecordT) p = _table->copyRecord(r); _internal.push_back(p); } /// @brief Add the given record to the end of the catalog without copying. void push_back(PTR(RecordT) const & p) { _internal.push_back(p); } /// @brief Create a new record, add it to the end of the catalog, and return a pointer to it. PTR(RecordT) addNew() { PTR(RecordT) r = _table->makeRecord(); _internal.push_back(r); return r; } /// @brief Remove the last record in the catalog void pop_back() { _internal.pop_back(); } /// @brief Deep-copy the catalog using a cloned table. CatalogT copy() const { return CatalogT(getTable()->clone(), begin(), end(), true); } /** * @brief Insert an iterator range into the table. * * InputIterator must dereference to a record reference that is convertible to the record type * held by the catalog, and must be implicitly convertible to a shared_ptr to a record. * * If deep is true, new records will be created by calling copyRecord on the catalog's table. * If deep is false, the new records will not be copied, but they must have been created * with the catalog's table (note that a table may be shared by multiple catalogs). * * If InputIterator models RandomAccessIterator (according to std::iterator_traits) and deep * is true, table->preallocate will be used to ensure that the resulting records are * contiguous in memory and can be used with ColumnView. To ensure this is the case for * other iterator types, the user must preallocate the table manually. */ template void insert(iterator pos, InputIterator first, InputIterator last, bool deep=false) { _maybeReserve( pos, first, last, deep, (typename std::iterator_traits::iterator_category*)0 ); if (deep) { while (first != last) { pos = insert(pos, *first); ++pos; ++first; } } else { while (first != last) { pos = insert(pos, first); assert(pos != end()); ++pos; ++first; } } } /// @brief Insert a range of records into the catalog by copying them with a SchemaMapper. template void insert(SchemaMapper const & mapper, iterator pos, InputIterator first, InputIterator last) { if (!_table->getSchema().contains(mapper.getOutputSchema())) { throw LSST_EXCEPT(
    522 f67d8b24 - pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    522 21597d88 + pex::exceptions::InvalidParameterError,
    ? ^^ ^ "SchemaMapper's output schema does not match catalog's schema" ); } _maybeReserve( pos, first, last, true, (typename std::iterator_traits::iterator_category*)0 ); while (first != last) { pos = insert(pos, _table->copyRecord(*first, mapper)); ++pos; ++first; } } /// Insert a copy of the given record at the given position. iterator insert(iterator pos, Record const & r) { PTR(RecordT) p = _table->copyRecord(r); return iterator(_internal.insert(pos.base(), p)); } /// Insert the given record at the given position without copying. iterator insert(iterator pos, PTR(RecordT) const & p) { return iterator(_internal.insert(pos.base(), p)); } /// Erase the record pointed to by pos, and return an iterator the next record. iterator erase(iterator pos) { return iterator(_internal.erase(pos.base())); } /// Erase the records in the range [first, last). iterator erase(iterator first, iterator last) { return iterator(_internal.erase(first.base(), last.base())); } /// Shallow swap of two catalogs. void swap(CatalogT & other) { _table.swap(other._table); _internal.swap(other._internal); } /// Remove all records from the catalog. void clear() { _internal.clear(); } /// @brief Return true if the catalog is in ascending order according to the given key. template bool isSorted(Key const & key) const; /** * @brief Return true if the catalog is in ascending order according to the given predicate. * * cmp(a, b) should return true if record a is less than record b, and false otherwise. */ template bool isSorted(Compare cmp) const; /// @brief Sort the catalog in-place by the field with the given key. template void sort(Key const & key); /** * @brief Sort the catalog in-place by the field with the given predicate. * * cmp(a, b) should return true if record a is less than record b, and false otherwise. */ template void sort(Compare cmp); //@{ /** * @brief Return an iterator to the record with the given value. * * When the field being searched is not unique, which matching record will be returned * is not defined. In these cases, lower_bound, upper_bound, or equal_range should be * used instead. * * In Python, this method returns a Record, not an iterator. * * @note The catalog must be sorted in ascending order according to the given key * before calling find (i.e. isSorted(key) must be true). * * Returns end() if the Record cannot be found. */ template iterator find(typename Field::Value const & value, Key const & key); template const_iterator find(typename Field::Value const & value, Key const & key) const; //@} //@{ /** * @brief Performed binary searches on sorted fields. * * These methods perform binary searches analogous to the STL algorithms of the same * name; they simply create a comparison functor using the given value and Key. * * In Python, the lower_bound and upper_bound methods return the position of the * result record in the catalog, and equal_range returns a Python slice object * that defines the range. * * @note The catalog must be sorted in ascending order according to the given key * before calling any of the search methods (i.e. isSorted(key) must be true). */ template iterator lower_bound(typename Field::Value const & value, Key const & key); template const_iterator lower_bound(typename Field::Value const & value, Key const & key) const; template iterator upper_bound(typename Field::Value const & value, Key const & key); template const_iterator upper_bound(typename Field::Value const & value, Key const & key) const; template std::pair equal_range(typename Field::Value const & value, Key const & key); template std::pair equal_range(typename Field::Value const & value, Key const & key) const; //@} //@{ /** * @brief Return a reference to the internal vector-of-shared_ptr * * While in most cases it is more convenient to use the Catalog's iterators, which dereference * directly to Record objects (and hence allow iter->method() rather than (**iter).method()), * direct access to the underlying vector-of-shared_ptr is provided here to allow complete use * of the C++ STL. In particular, in order to use a mutating STL algorithm on a Catalog in * such a way that Records are shallow-copied (i.e. shared_ptr::operator= is invoked instead * of Record::operator=), those algorithms should be called on the iterators of these internal * containers. When an algorithm should be called in such a way that records are deep-copied, * the regular Catalog iterators should be used. */ Internal & getInternal() { return _internal; } Internal const & getInternal() const { return _internal; } //@} private: template void _maybeReserve( iterator & pos, InputIterator first, InputIterator last, bool deep, std::random_access_iterator_tag * ) { if (deep) _table->preallocate(last - first); } template void _maybeReserve( iterator pos, InputIterator first, InputIterator last, bool deep, std::input_iterator_tag * ) {} PTR(Table) _table; Internal _internal; }; namespace detail { template struct KeyComparisonFunctor { bool operator()(RecordT const & a, RecordT const & b) const { return a.get(key) < b.get(key); } Key key; }; template struct ComparisonAdaptor { bool operator()(PTR(RecordT) const & a, PTR(RecordT) const & b) const { return adaptee(*a, *b); } Adaptee adaptee; }; template struct KeyExtractionFunctor { typedef typename Field::Value result_type; result_type operator()(RecordT const & r) const { return r.get(key); } Key key; }; } // namespace detail template template bool CatalogT::isSorted(Compare cmp) const { /// TODO: C++11 has an is_sorted function we should use when available. detail::ComparisonAdaptor f = { cmp }; if (empty()) return true; const_iterator last = this->begin(); const_iterator i = last; ++i; for (; i != this->end(); ++i) { if (f(i, last)) return false; last = i; } return true; } template template void CatalogT::sort(Compare cmp) { detail::ComparisonAdaptor f = { cmp }; std::stable_sort(_internal.begin(), _internal.end(), f); } template template bool CatalogT::isSorted(Key const & key) const { detail::KeyComparisonFunctor f = { key }; return isSorted(f); } template template void CatalogT::sort(Key const & key) { detail::KeyComparisonFunctor f = { key }; return sort(f); } template template typename CatalogT::iterator CatalogT::find(typename Field::Value const & value, Key const & key) { detail::KeyExtractionFunctor f = { key }; // Iterator adaptor that makes a CatalogT iterator work like an iterator over field values. typedef boost::transform_iterator,iterator> SearchIter; // Use binary search for log n search; requires sorted table. SearchIter i = std::lower_bound(SearchIter(begin(), f), SearchIter(end(), f), value); if (i.base() == end() || *i != value) return end(); return i.base(); } template template typename CatalogT::const_iterator CatalogT::find(typename Field::Value const & value, Key const & key) const { detail::KeyExtractionFunctor f = { key }; // Iterator adaptor that makes a CatalogT iterator work like an iterator over field values. typedef boost::transform_iterator,const_iterator> SearchIter; // Use binary search for log n search; requires sorted table. SearchIter i = std::lower_bound(SearchIter(begin(), f), SearchIter(end(), f), value); if (i.base() == end() || *i != value) return end(); return i.base(); } template template typename CatalogT::iterator CatalogT::lower_bound(typename Field::Value const & value, Key const & key) { detail::KeyExtractionFunctor f = { key }; // Iterator adaptor that makes a CatalogT iterator work like an iterator over field values. typedef boost::transform_iterator,iterator> SearchIter; SearchIter i = std::lower_bound(SearchIter(begin(), f), SearchIter(end(), f), value); return i.base(); } template template typename CatalogT::const_iterator CatalogT::lower_bound(typename Field::Value const & value, Key const & key) const { detail::KeyExtractionFunctor f = { key }; // Iterator adaptor that makes a CatalogT iterator work like an iterator over field values. typedef boost::transform_iterator,const_iterator> SearchIter; SearchIter i = std::lower_bound(SearchIter(begin(), f), SearchIter(end(), f), value); return i.base(); } template template typename CatalogT::iterator CatalogT::upper_bound(typename Field::Value const & value, Key const & key) { detail::KeyExtractionFunctor f = { key }; // Iterator adaptor that makes a CatalogT iterator work like an iterator over field values. typedef boost::transform_iterator,iterator> SearchIter; SearchIter i = std::upper_bound(SearchIter(begin(), f), SearchIter(end(), f), value); return i.base(); } template template typename CatalogT::const_iterator CatalogT::upper_bound(typename Field::Value const & value, Key const & key) const { detail::KeyExtractionFunctor f = { key }; // Iterator adaptor that makes a CatalogT iterator work like an iterator over field values. typedef boost::transform_iterator,const_iterator> SearchIter; SearchIter i = std::upper_bound(SearchIter(begin(), f), SearchIter(end(), f), value); return i.base(); } template template std::pair::iterator,typename CatalogT::iterator> CatalogT::equal_range(typename Field::Value const & value, Key const & key) { detail::KeyExtractionFunctor f = { key }; // Iterator adaptor that makes a CatalogT iterator work like an iterator over field values. typedef boost::transform_iterator,iterator> SearchIter; std::pair i = std::equal_range(SearchIter(begin(), f), SearchIter(end(), f), value); return std::make_pair(i.first.base(), i.second.base()); } template template std::pair::const_iterator,typename CatalogT::const_iterator> CatalogT::equal_range(typename Field::Value const & value, Key const & key) const { detail::KeyExtractionFunctor f = { key }; // Iterator adaptor that makes a CatalogT iterator work like an iterator over field values. typedef boost::transform_iterator,const_iterator> SearchIter; std::pair i = std::equal_range(SearchIter(begin(), f), SearchIter(end(), f), value); return std::make_pair(i.first.base(), i.second.base()); } //@{ /** * @internal * * This block is just a big, ugly workaround for a Swig deficiency: apparently we can't add * templated methods to an %extend block (or at least we can't do that if the class is also templated), * which we'd need to do to wrap these because they return iterators in C++ and other things in * Python. Instead we'll add doubly-templated free functions, and call them from a %pythoncode * block in an %extend block in the .i file. * * And we can't put these in an %inline block in the .i file because then the definitions * wouldn't be available to downstream instantiations with catalog/record types defined in * other packages. * * But here's the best part: try putting these in 'namespace detail', and detectionLib_wrap.cc * fails to build, because it causes Swig to starts putting "lsst::afw::table::lsst::afw::detection" * in front of Footprint-related things! I have no idea what unholy combination of chewing gum * and rubber bands is holding this together, but I don't want to touch it. * * Oh, how I hate Swig. */ template PTR(RecordT) _Catalog_find(Catalog const & catalog, T const & value, Key const & key) { typename Catalog::const_iterator iter = catalog.find(value, key); if (iter == catalog.end()) { return PTR(RecordT)(); } return iter; // n.b. CatalogIterator is explicitly convertible to shared_ptr } template int _Catalog_lower_bound(Catalog const & catalog, T const & value, Key const & key) { return catalog.lower_bound(value, key) - catalog.begin(); } template int _Catalog_upper_bound(Catalog const & catalog, T const & value, Key const & key) { return catalog.upper_bound(value, key) - catalog.begin(); } template std::pair _Catalog_equal_range(Catalog const & catalog, T const & value, Key const & key) { std::pair p = catalog.equal_range(value, key); return std::pair(p.first - catalog.begin(), p.second - catalog.begin()); } //@} }}} // namespace lsst::afw::table #endif // !AFW_TABLE_Catalog_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    159b2bee

    commit 159b2bee80df4649198123be599cf181731fe646
    Author: Jim Bosch 
    Date:   Mon Feb 6 00:31:10 2012 -0500
    
        documentation for VectorT
    

    5819ddee

    commit 5819ddee5933850bbfd5b663464f0f397d0d5fd6
    Author: Jim Bosch 
    Date:   Wed Jun 13 23:55:04 2012 -0400
    
        Throw an exception instead of asserting when user passes step=0 in slice indexing.
    

    f67d8b24

    commit f67d8b24a5d25e5bc642f1cafd80e58993835a8e
    Author: Jim Bosch 
    Date:   Wed Jun 13 23:56:42 2012 -0400
    
        Add Catalog::insert overload that uses a SchemaMapper.
    

    fee6a99b

    commit fee6a99b99ccc93550a8046f55134402af184883
    Author: Jim Bosch 
    Date:   Wed Aug 29 17:31:54 2012 -0400
    
        prevent access to ColumnView from const Catalogs, and add some documentation
    

    9e1f03f1

    commit 9e1f03f11af1a841920c1f8c9b56d72e7b685b39
    Author: Jim Bosch 
    Date:   Thu May 23 12:29:22 2013 -0400
    
        Add boolean array indexing to afw::table Catalog objects (#2894)
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/geom/Angle.h

    Diff:

    1 35153a16 - #if !defined(ANGLE_H)
    1 d683c19b + #if !defined(LSST_AFW_GEOM_ANGLE_H)
    ? ++++++++++++++
    2 35153a16 - #define ANGLE_H
    2 d683c19b + #define LSST_AFW_GEOM_ANGLE_H
    #include #include #include #include #include namespace lsst { namespace afw { namespace geom { /************************************************************************************************************/ /* * None of C99, C++98, and C++0x define M_PI, so we'll do it ourselves */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-variable" double const PI = boost::math::constants::pi(); ///< The ratio of a circle's circumference to diameter double const TWOPI = boost::math::constants::pi() * 2.0; double const HALFPI = boost::math::constants::pi() * 0.5; double const ONE_OVER_PI = 1.0 / boost::math::constants::pi(); double const SQRTPI = sqrt(boost::math::constants::pi()); double const INVSQRTPI = 1.0/sqrt(boost::math::constants::pi()); double const ROOT2 = boost::math::constants::root_two(); // sqrt(2) #pragma clang diagnostic pop // These shouldn't be necessary if the Angle class is used, but sometimes you just need // them. Better to define them once here than have *180/PI throughout the code... inline double degToRad(double x) { return x * PI / 180.; } inline double radToDeg(double x) { return x * 180. / PI; } inline double radToArcsec(double x) { return x * 3600. * 180. / PI; } inline double radToMas(double x) { return x * 1000. * 3600. * 180. / PI; } inline double arcsecToRad(double x) { return (x / 3600.) * PI / 180.; } inline double masToRad(double x) { return (x / (1000. * 3600.)) * PI / 180.; } // NOTE, if you add things here, you must also add them to // python/lsst/afw/geom/__init__.py // (if you want them to accessible from python) #if 0 && !defined(M_PI) // a good idea, but with ramifications # define M_PI ::lsst::afw::geom::PI #endif /************************************************************************************************************/ class Angle; /** * \brief A class used to convert scalar POD types such as double to Angle * * For example: * \code * Angle pi = 180*degrees; * \endcode * is equivalent to * \code * Angle pi(180, degrees); * \endcode */ class AngleUnit { friend class Angle; template friend const Angle operator *(T lhs, AngleUnit const rhs); public: explicit AngleUnit(double val) : _val(val) {} bool operator==(AngleUnit const &rhs) const; private: double _val; }; inline bool lsst::afw::geom::AngleUnit::operator==(lsst::afw::geom::AngleUnit const &rhs) const { return (_val == rhs._val); } // NOTE, if you add things here, remember to also add them to // python/lsst/afw/geom/__init__.py // swig likes this way of initialising the constant, so don't mess with it; // N.b. swig 1.3 doesn't like PI/(60*180) AngleUnit const radians = AngleUnit(1.0); ///< constant with units of radians AngleUnit const degrees = AngleUnit(PI/180.0); // constant with units of degrees AngleUnit const hours = AngleUnit(PI*15.0/180.0); // constant with units of hours AngleUnit const arcminutes = AngleUnit(PI/60/180.0); // constant with units of arcminutes AngleUnit const arcseconds = AngleUnit(PI/180.0/3600.0); // constant with units of arcseconds /************************************************************************************************************/ /** * A class representing an Angle * * Angles may be manipulated like doubles, and automatically converted to doubles, but they may not be * constructed from doubles without calling a constructor or multiplying by an AngleUnit */ class Angle { friend class AngleUnit; public: /** Construct an Angle with the specified value (interpreted in the given units) */ explicit Angle(double val, AngleUnit units=radians) : _val(val*units._val) {} Angle() : _val(0) {} /** Copy constructor. */ Angle(Angle const& other) : _val(other._val) {} /** Convert an Angle to a double in radians*/ operator double() const { return _val; } /** Convert an Angle to a float in radians*/ //operator float() const { return _val; } /** Return an Angle's value as a double in the specified units (i.e. afwGeom::degrees) */ double asAngularUnits(AngleUnit const& units) const { return _val/units._val; } /** Return an Angle's value as a double in radians */ double asRadians() const { return asAngularUnits(radians); } /** Return an Angle's value as a double in degrees */ double asDegrees() const { return asAngularUnits(degrees); } /** Return an Angle's value as a double in hours */ double asHours() const { return asAngularUnits(hours); } /** Return an Angle's value as a double in arcminutes */ double asArcminutes() const { return asAngularUnits(arcminutes); } /** Return an Angle's value as a double in arcseconds */ double asArcseconds() const { return asAngularUnits(arcseconds); } double toUnitSphereDistanceSquared() const { return 2. * (1. - std::cos(asRadians())); } // == 4.0 * pow(std::sin(0.5 * asRadians()), 2.0) static Angle fromUnitSphereDistanceSquared(double d2) { return (std::acos(1. - d2/2.)) * radians; // == 2.0 * asin(0.5 * sqrt(d2)) } /** Wraps this angle to the range [0, 2 pi) @warning The upper limit is only guaranteed for radians; the upper limit may be slightly squishy for other units, due to roundoff errors. Whether there are any violations is unknown; please update this comment if you can prove that the limits are or are not valid for all supported units. */ void wrap() { _val = std::fmod(_val, TWOPI); // _val is now in the range (-TWOPI, TWOPI) if (_val < 0.0) _val += TWOPI; // if _val is small enough, adding 2 pi gives 2 pi if (_val >= TWOPI) _val = 0.0; } /** Wrap this angle to the range [-pi, pi) @warning Exact limits are only guaranteed for radians; limits for other units may be slightly squishy, due to roundoff errors. Whether there are any violations is unknown; please update this comment if you can prove that the limits are or are not valid for all supported units. */ void wrapCtr() { _val = std::fmod(_val, TWOPI); // _val is now in the range [-TWOPI, TWOPI] if (_val < -PI) { _val += TWOPI; if (_val >= PI) { // handle roundoff error, however unlikely _val = -PI; } } else if (_val >= PI) { _val -= TWOPI; if (_val < -PI) { // handle roundoff error, however unlikely _val = -PI; } } } /** Wrap this angle such that pi <= this - refAng < pi @warning Exact limits are only guaranteed for radians; limits for other units may be slightly squishy due to roundoff errors. There are known violations that are demonstrated in testWrap in tests/angle.py. */ void wrapNear( Angle const & refAng ///< reference angle to match ) { // compute this = (this - refAng).wrapCtr() + refAng // which is correct except for roundoff error at the edges double refAngRad = refAng.asRadians(); *this -= refAng; wrapCtr(); _val += refAngRad; // roundoff can cause slightly out-of-range values; fix those if (_val - refAngRad >= PI) { _val -= TWOPI; } // maximum relative roundoff error for subtraction is 2 epsilon if (_val - refAngRad < -PI) { _val -= _val * 2.0 * std::numeric_limits::epsilon(); } } #define ANGLE_OPUP_TYPE(OP, TYPE) \ Angle& operator OP(TYPE const& d) { \ _val OP d; \ return *this; \ } ANGLE_OPUP_TYPE(*=, double) ANGLE_OPUP_TYPE(*=, int) ANGLE_OPUP_TYPE(+=, double) ANGLE_OPUP_TYPE(+=, int) ANGLE_OPUP_TYPE(-=, double) ANGLE_OPUP_TYPE(-=, int) #undef ANGLE_OPUP_TYPE #define ANGLE_COMP(OP) \ bool operator OP ( const Angle& rhs ) { \ return _val OP rhs._val; \ } ANGLE_COMP(==) ANGLE_COMP(!=) ANGLE_COMP(<=) ANGLE_COMP(>=) ANGLE_COMP(<) ANGLE_COMP(>) #undef ANGLE_COMP private: double _val; }; Angle const NullAngle = Angle(-1000000., degrees); /************************************************************************************************************/ /* * Operators for Angles. * * N.b. We need both int and double versions to avoid ambiguous overloading due to implicit conversion of * Angle to double */ #define ANGLE_OP(OP) \ inline const Angle operator OP(Angle const a, Angle const d) { \ return Angle(static_cast(a) OP static_cast(d)); \ } #define ANGLE_OP_TYPE(OP, TYPE) \ inline const Angle operator OP(Angle const a, TYPE d) { \ return Angle(static_cast(a) OP d); \ } \ \ inline const Angle operator OP(TYPE d, Angle const a) { \ return Angle(d OP static_cast(a)); \ } ANGLE_OP(+) ANGLE_OP(-) ANGLE_OP(*) ANGLE_OP_TYPE(*, double) ANGLE_OP_TYPE(*, int) #undef ANGLE_OP #undef ANGLE_OP_TYPE // Division is different. Don't allow division by an Angle inline const Angle operator /(Angle const a, int d) { return Angle(static_cast(a)/d); } inline const Angle operator /(Angle const a, double d) { return Angle(static_cast(a)/d); } template double operator /(T const lhs, Angle const rhs); /************************************************************************************************************/ /** * \brief Allow a user to check if they have an angle (yes; they could do this themselves via trivial TMP) */ template inline bool isAngle(T) { return false; }; inline bool isAngle(Angle const&) { return true; }; /************************************************************************************************************/ /** * \brief Use AngleUnit to convert a POD (e.g. int, double) to an Angle; e.g. 180*afwGeom::degrees */ template inline const Angle operator *(T lhs, ///< the value to convert AngleUnit const rhs ///< the conversion coefficient ) { BOOST_STATIC_ASSERT_MSG(std::numeric_limits::is_specialized, "Only numeric types may be converted to Angles using degrees/radians!"); return Angle(lhs*rhs._val); } /** * Output operator for an Angle */ std::ostream& operator<<(std::ostream &s, ///< The output stream Angle const a ///< The angle ); }}}
    319 35153a16 - #endif
    319 d683c19b + #endif // if !defined(LSST_AFW_GEOM_ANGLE_H)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    35153a16

    commit 35153a16adf59642b70caa1eba565dca9eb9e4a6
    Author: rhl 
    Date:   Tue May 3 16:43:30 2011 +0000
    
        Added Angle class from hg; #1663
    

    Commits in /Users/nate/repos_lsst/afw/

    d683c19b

    commit d683c19b2e7fc9004ab9c5c25f9cbbfa802cb85b
    Author: Paul Price 
    Date:   Thu Oct 23 14:21:15 2014 +0900
    
        Angle: fully qualify include guard
        
        Coding standard 4-9 says that the entire namespace and filename should
        be used in the guard; otherwise, we can conflict with other packages.
        This particular one conflicts with GalSim (at least).
    

    Return to list

    tests/sourceMatch.py

    Diff:

    1 e43e1b47 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for matching SourceSets Run with: python SourceMatch.py or python >>> import SourceMatch; SourceMatch.run() """
    34 e43e1b47 - import os, re, sys
    35 7cbb2bb9 + import os
    36 7cbb2bb9 + import re
    import numpy import unittest
    38 e43e1b47 - import eups
    39 3b092a84 - from math import radians
    import pickle
    42 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests
    43 a7aa0c91 - import lsst.afw.detection as afwDetect
    import lsst.afw.table as afwTable import lsst.afw.geom as afwGeom #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class SourceMatchTestCase(unittest.TestCase): """A test case for matching SourceSets""" def setUp(self): schema = afwTable.SourceTable.makeMinimalSchema()
    54 8d70f429 - fluxKey = schema.addField("flux", type=float)
    54 a25b9eb2 + fluxKey = schema.addField("flux_flux", type=float)
    ? +++++
    55 8d70f429 - fluxErrKey = schema.addField("flux.err", type=float)
    ? ^^^^
    55 a25b9eb2 + fluxErrKey = schema.addField("flux_fluxSigma", type=float)
    ? ^^^^^^^^^^
    56 8d70f429 - fluxFlagKey = schema.addField("flux.flags", type="Flag")
    ? ^ -
    56 a25b9eb2 + fluxFlagKey = schema.addField("flux_flag", type="Flag")
    ? ^ self.table = afwTable.SourceTable.make(schema) self.table.definePsfFlux("flux") self.ss1 = afwTable.SourceCatalog(self.table) self.ss2 = afwTable.SourceCatalog(self.table) def tearDown(self): del self.table del self.ss1 del self.ss2 def testIdentity(self): nobj = 1000 for i in range(nobj): s = self.ss1.addNew() s.setId(i) s.set(afwTable.SourceTable.getCoordKey().getRa(), (10 + 0.001*i) * afwGeom.degrees) s.set(afwTable.SourceTable.getCoordKey().getDec(), (10 + 0.001*i) * afwGeom.degrees) s = self.ss2.addNew() s.setId(2*nobj + i) s.set(afwTable.SourceTable.getCoordKey().getRa(), (10 + 0.001*i) * afwGeom.degrees) s.set(afwTable.SourceTable.getCoordKey().getDec(), (10 + 0.001*i) * afwGeom.degrees)
    79 3252a40a - # Old API (pre DM-855)
    79 e43e1b47 +
    mat = afwTable.matchRaDec(self.ss1, self.ss2, 1.0 * afwGeom.arcseconds, False)
    81 e43e1b47 +
    81 3252a40a - self.assertEqual(len(mat), nobj)
    82 3252a40a - # New API
    83 3252a40a - mc = afwTable.MatchControl()
    84 3252a40a - mc.findOnlyClosest = False
    85 3252a40a - mat = afwTable.matchRaDec(self.ss1, self.ss2, 1.0*afwGeom.arcseconds, mc)
    self.assertEqual(len(mat), nobj) cat = afwTable.packMatches(mat) mat2 = afwTable.unpackMatches(cat, self.ss1, self.ss2) for m1, m2, c in zip(mat, mat2, cat): self.assertEqual(m1.first, m2.first) self.assertEqual(m1.second, m2.second) self.assertEqual(m1.distance, m2.distance) self.assertEqual(m1.first.getId(), c["first"]) self.assertEqual(m1.second.getId(), c["second"]) self.assertEqual(m1.distance, c["distance"]) self.checkPickle(mat, checkSlots=False) self.checkPickle(mat2, checkSlots=False) if False: s0 = mat[0][0] s1 = mat[0][1] print s0.getRa(), s1.getRa(), s0.getId(), s1.getId() def testNaNPositions(self): ss1 = afwTable.SourceCatalog(self.table) ss2 = afwTable.SourceCatalog(self.table) for ss in (ss1, ss2): ss.addNew().set(afwTable.SourceTable.getCoordKey().getRa(), float('nan') * afwGeom.radians) ss.addNew().set(afwTable.SourceTable.getCoordKey().getDec(), float('nan') * afwGeom.radians) s = ss.addNew() s.set(afwTable.SourceTable.getCoordKey().getRa(), 0.0 * afwGeom.radians) s.set(afwTable.SourceTable.getCoordKey().getDec(), 0.0 * afwGeom.radians) s = ss.addNew() s.set(afwTable.SourceTable.getCoordKey().getRa(), float('nan') * afwGeom.radians) s.set(afwTable.SourceTable.getCoordKey().getDec(), float('nan') * afwGeom.radians)
    124 3252a40a - mc = afwTable.MatchControl()
    125 3252a40a - mc.findOnlyClosest = False
    126 3252a40a - mat = afwTable.matchRaDec(ss1, ss2, 1.0*afwGeom.arcseconds, mc)
    ? ^^
    120 9a8f8dd1 + mat = afwTable.matchRaDec(ss1, ss2, 1.0 * afwGeom.arcseconds, False)
    ? + + ^^^^^ self.assertEqual(len(mat), 1) self.checkPickle(mat) def testPhotometricCalib(self): """Test matching the CFHT catalogue (as generated using LSST code) to the SDSS catalogue"""
    133 e43e1b47 - if not eups.productDir("afwdata"):
    134 e43e1b47 - print >> sys.stderr, "Failed to open sdss catalogue"
    135 e43e1b47 - return
    136 e43e1b47 -
    band = 2 # SDSS r # # Read SDSS catalogue #
    142 e43e1b47 - ifd = open(os.path.join(eups.productDir("afwdata"), "CFHT", "D2", "sdss.dat"), "r")
    ? ^ ^ ^^^^^ ^
    132 7cbb2bb9 + ifd = open(os.path.join(lsst.utils.getPackageDir("afwdata"), "CFHT", "D2", "sdss.dat"), "r")
    ? ^^^^^ ^^^ ^^^^^ ^^^^ sdss = afwTable.SourceCatalog(self.table) sdssSecondary = afwTable.SourceCatalog(self.table) PRIMARY, SECONDARY = 1, 2 # values of mode id = 0 for line in ifd.readlines(): if re.search(r"^\s*#", line): continue fields = line.split() objId = int(fields[0]) name = fields[1] mode = int(fields[2]) ra, dec = [float(f) for f in fields[3:5]] psfMags = [float(f) for f in fields[5:]] if mode == PRIMARY: s = sdss.addNew() elif SECONDARY: s = sdssSecondary.addNew() s.setId(objId) s.setRa(ra * afwGeom.degrees) s.setDec(dec * afwGeom.degrees) s.set(self.table.getPsfFluxKey(), psfMags[band]) del ifd # # Read catalalogue built from the template image # # # Read SDSS catalogue #
    178 e43e1b47 - ifd = open(os.path.join(eups.productDir("afwdata"), "CFHT", "D2", "template.dat"), "r")
    ? ^ ^ ^^^^^ ^
    168 7cbb2bb9 + ifd = open(os.path.join(lsst.utils.getPackageDir("afwdata"), "CFHT", "D2", "template.dat"), "r")
    ? ^^^^^ ^^^ ^^^^^ ^^^^ template = afwTable.SourceCatalog(self.table) id = 0 for line in ifd.readlines(): if re.search(r"^\s*#", line): continue fields = line.split() id, flags = [int(f) for f in fields[0:2]] ra, dec = [float(f) for f in fields[2:4]] flux = [float(f) for f in fields[4:]] if flags & 0x1: # EDGE continue s = template.addNew() s.setId(id) id += 1 s.set(afwTable.SourceTable.getCoordKey().getRa(), ra * afwGeom.degrees) s.set(afwTable.SourceTable.getCoordKey().getDec(), dec * afwGeom.degrees) s.set(self.table.getPsfFluxKey(), flux[0]) del ifd # # Actually do the match #
    206 3252a40a - mc = afwTable.MatchControl()
    207 3252a40a - mc.findOnlyClosest = False
    208 3252a40a -
    209 3252a40a - matches = afwTable.matchRaDec(sdss, template, 1.0*afwGeom.arcseconds, mc)
    ? ^^
    196 9a8f8dd1 + matches = afwTable.matchRaDec(sdss, template, 1.0 * afwGeom.arcseconds, False)
    ? + + ^^^^^ self.assertEqual(len(matches), 901) self.checkPickle(matches) if False: for mat in matches: s0 = mat[0] s1 = mat[1] d = mat[2] print s0.getRa(), s0.getDec(), s1.getRa(), s1.getDec(), s0.getPsfFlux(), s1.getPsfFlux() # # Actually do the match # for s in sdssSecondary: sdss.append(s)
    226 3252a40a - mc = afwTable.MatchControl()
    227 3252a40a - mc.symmetricMatch = False
    228 3252a40a - matches = afwTable.matchRaDec(sdss, 1.0*afwGeom.arcseconds, mc)
    ? ^^
    213 9a8f8dd1 + matches = afwTable.matchRaDec(sdss, 1.0 * afwGeom.arcseconds, False)
    ? + + ^^^^^ nmiss = 1 # one object doesn't match self.assertEqual(len(matches), len(sdssSecondary) - nmiss) self.checkPickle(matches) # # Find the one that didn't match # if False: matchIds = set() for s0, s1, d in matches: matchIds.add(s0.getId()) matchIds.add(s1.getId()) for s in sdssSecondary: if s.getId() not in matchIds: print "RHL", s.getId()
    245 3252a40a - matches = afwTable.matchRaDec(sdss, 1.0*afwGeom.arcseconds)
    230 9a8f8dd1 + matches = afwTable.matchRaDec(sdss, 1.0 * afwGeom.arcseconds, True)
    ? + + ++++++ self.assertEqual(len(matches), 2*(len(sdssSecondary) - nmiss)) self.checkPickle(matches) if False: for mat in matches: s0 = mat[0] s1 = mat[1] d = mat[2] print s0.getId(), s1.getId(), s0.getRa(), s0.getDec(), print s1.getRa(), s1.getDec(), s0.getPsfFlux(), s1.getPsfFlux()
    257 81c6063a - def testMismatches(self):
    258 81c6063a - """ Chech that matchRaDec works as expected when using
    259 81c6063a - the includeMismatches option
    260 81c6063a - """
    261 81c6063a - cat1 = afwTable.SourceCatalog(self.table)
    262 81c6063a - cat2 = afwTable.SourceCatalog(self.table)
    263 81c6063a - nobj = 100
    264 81c6063a - for i in range(nobj):
    265 81c6063a - s1 = cat1.addNew()
    266 81c6063a - s2 = cat2.addNew()
    267 81c6063a - s1.setId(i)
    268 81c6063a - s2.setId(i)
    269 81c6063a - s1.set(afwTable.SourceTable.getCoordKey().getRa(), (10 + 0.0001*i) * afwGeom.degrees)
    270 81c6063a - s2.set(afwTable.SourceTable.getCoordKey().getRa(), (10.005 + 0.0001*i) * afwGeom.degrees)
    271 81c6063a - s1.set(afwTable.SourceTable.getCoordKey().getDec(), (10 + 0.0001*i) * afwGeom.degrees)
    272 81c6063a - s2.set(afwTable.SourceTable.getCoordKey().getDec(), (10.005 + 0.0001*i) * afwGeom.degrees)
    273 81c6063a -
    274 81c6063a - for closest in (True, False):
    275 81c6063a - mc = afwTable.MatchControl()
    276 81c6063a - mc.findOnlyClosest = closest
    277 81c6063a - mc.includeMismatches = False
    278 81c6063a - matches = afwTable.matchRaDec(cat1, cat2, 1.0*afwGeom.arcseconds, mc)
    279 81c6063a - mc.includeMismatches = True
    280 81c6063a - matchesMismatches = afwTable.matchRaDec(cat1, cat2, 1.0*afwGeom.arcseconds, mc)
    281 81c6063a -
    282 81c6063a - catMatches = afwTable.SourceCatalog(self.table)
    283 81c6063a - catMismatches = afwTable.SourceCatalog(self.table)
    284 81c6063a - for m in matchesMismatches:
    285 81c6063a - if m[1] != None:
    286 81c6063a - if not any(x == m[0] for x in catMatches):
    287 81c6063a - catMatches.append(m[0])
    288 81c6063a - else:
    289 81c6063a - catMismatches.append(m[0])
    290 81c6063a - if closest:
    291 81c6063a - self.assertEquals(len(catMatches), len(matches))
    292 81c6063a - matches2 = afwTable.matchRaDec(catMatches, cat2, 1.0*afwGeom.arcseconds, mc)
    293 81c6063a - self.assertEquals(len(matches), len(matches2))
    294 81c6063a - mc.includeMismatches = False
    295 81c6063a - noMatches = afwTable.matchRaDec(catMismatches, cat2, 1.0*afwGeom.arcseconds, mc)
    296 81c6063a - self.assertEquals(len(noMatches), 0)
    297 81c6063a -
    def checkPickle(self, matches, checkSlots=True): """Check that a match list pickles Also checks that the slots survive pickling, if checkSlots is True. """ orig = afwTable.SourceMatchVector(matches) unpickled = pickle.loads(pickle.dumps(orig)) self.assertEqual(len(orig), len(unpickled)) for m1, m2 in zip(orig, unpickled): self.assertEqual(m1.first.getId(), m2.first.getId()) self.assertEqual(m1.first.getRa(), m2.first.getRa()) self.assertEqual(m1.first.getDec(), m2.first.getDec()) self.assertEqual(m1.second.getId(), m2.second.getId()) self.assertEqual(m1.second.getRa(), m2.second.getRa()) self.assertEqual(m1.second.getDec(), m2.second.getDec()) self.assertEqual(m1.distance, m2.distance) if checkSlots: self.assertEqualFloat(m1.first.getPsfFlux(), m2.first.getPsfFlux()) self.assertEqualFloat(m1.second.getPsfFlux(), m2.second.getPsfFlux()) def assertEqualFloat(self, value1, value2): """Compare floating point values, allowing for NAN""" self.assertTrue(value1 == value2 or (numpy.isnan(value1) and numpy.isnan(value2))) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(SourceMatchTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    8d70f429

    commit 8d70f429f96be073739bc1cf495bf46305c008fe
    Author: Jim Bosch 
    Date:   Thu Feb 9 14:43:13 2012 -0500
    
        source matching (but not persistence) converted to afw/table
    

    e43e1b47

    commit e43e1b47770d277a9f474978c1f20a0080cdd597
    Author: rhl 
    Date:   Wed Apr 22 20:04:29 2009 +0000
    
        Added some python tests.  The real catalogue matches require afwdata r9256
    

    3252a40a

    commit 3252a40ad55222b882acf14d2f7cf0f3fe80f585
    Author: Robert Lupton the Good 
    Date:   Tue Jun 10 15:00:58 2014 -0400
    
        Added MatchControl and implemented it for matchXY and MatchRaDec
        
        N.b. added some missing tests on matchXY, although it is unchanged by this
        changeset
    

    3b092a84

    commit 3b092a84df3aec4231324ad17bf7e7024da32eb5
    Author: dstn 
    Date:   Wed Apr 20 14:19:15 2011 +0000
    
        fix Point2D and radians bugs
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    81c6063a

    commit 81c6063a32883b748f3770b7124d74ced7b480f5
    Author: Jose Garmilla 
    Date:   Thu Jun 12 16:14:39 2014 -0400
    
        Implement and test includeMismatches option in MatchControl object
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    a25b9eb2

    commit a25b9eb2df1c00b862411068c0447f4391bb12f4
    Author: pgee 
    Date:   Wed Mar 4 17:06:38 2015 -0800
    
        DM-1076, remove need of unit tests to setVersion(0), and move tests to default version.
        
        Note that there are several version tests in the unit tests which should not be changed.
        Also needed to change Schema::getNames to use the '_' separator for version > 0.
        Also included responses to review comments
    

    e43e1b47

    commit e43e1b47770d277a9f474978c1f20a0080cdd597
    Author: rhl 
    Date:   Wed Apr 22 20:04:29 2009 +0000
    
        Added some python tests.  The real catalogue matches require afwdata r9256
    

    9a8f8dd1

    commit 9a8f8dd109cfa6d9b29ce2d9cfd378c3c019cf8e
    Author: Jim Bosch 
    Date:   Thu Feb 9 17:11:28 2012 -0500
    
        removed old source match persistence in favor of conversion to a match table; moved match code from afw/detection to afw/table
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    tests/SConscript

    Diff:

                    # -*- python -*-
                    import os
                    
                    import lsst.daf.persistence
    
    5 ed95653a + import lsst.utils
    from lsst.sconsUtils import scripts, env, targets
    7 eaf3b304 - dataDir = env.ProductDir("afwdata")
    8 b10ab54c - if not dataDir:
    8 ed95653a + try:
    9 ed95653a + afwdataDir = lsst.utils.getPackageDir("afwdata")
    10 ed95653a + except Exception:
    print "Warning: afwdata is not set up; not running the tests!"
    10 eae9ad17 - else:
    ? ----
    12 ed95653a + else:
    # copy AFWDATA_DIR to the test's environment
    12 2dea9575 - env["ENV"]["AFWDATA_DIR"] = os.environ["AFWDATA_DIR"]
    14 ed95653a + env["ENV"]["AFWDATA_DIR"] = afwdataDir
    if not lsst.daf.persistence.DbAuth.available("lsst10.ncsa.uiuc.edu", "3306"): print "WARNING: No database authenticator seen" print "Database tests may be skipped or may fail" # set up arguments for C++ tests
    19 5b522953 - inFile = os.path.join(dataDir, "data", "871034p_1_MI.fits")
    21 ed95653a + inFile = os.path.join(afwdataDir, "data", "871034p_1_MI.fits")
    ? +++
    20 2dcc3781 - inFileRamFitsIO1 = os.path.join(dataDir, "data", "fpC-002570-r6-0199_sub.fits")
    22 ed95653a + inFileRamFitsIO1 = os.path.join(afwdataDir, "data", "fpC-002570-r6-0199_sub.fits")
    ? +++
    21 2dcc3781 - inFileRamFitsIO2 = os.path.join(dataDir, "data", "fpC-005902-r6-0677_sub.fits")
    23 ed95653a + inFileRamFitsIO2 = os.path.join(afwdataDir, "data", "fpC-005902-r6-0677_sub.fits")
    ? +++ testArgs = dict( maskedImage1 = "%s %s file:maskedImage1_output_1.fits file:maskedImage1_output_2.fits" % \ (inFile, inFile), ramFitsIO = "%s %s" % (inFileRamFitsIO1, inFileRamFitsIO2), ) scripts.BasicSConscript.tests(args=testArgs) env.Depends("tests/PsfIo.py", "tests/testTableArchivesLib.py") env.Clean(targets["tests"], "#testTable.fits")

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b10ab54c

    commit b10ab54c802578e3cc4158bc33aa212a5cba5bc4
    Author: rallsman 
    Date:   Sun Apr 6 01:43:41 2008 +0000
    
        Mostly replacing the files which were inexplicably zero length on last commit.
    

    2dcc3781

    commit 2dcc37810a125dfa79f96647f0d7784c8c7ee582
    Author: Robert Lupton the Good 
    Date:   Tue Nov 22 14:17:03 2011 -0500
    
        fpC files moved to a subdirectory ./data
    

    eae9ad17

    commit eae9ad175a79abc17b9939be5beb520d5e90dc1f
    Author: rowen 
    Date:   Sat Oct 16 00:21:41 2010 +0000
    
        Merge ticket #1469: further convolution speedups
    

    2dea9575

    commit 2dea95754edd136c2095954c2ab31be234222f5c
    Author: rowen 
    Date:   Wed Apr 16 17:32:59 2008 +0000
    
        afw reorg: fix tests/SConscript so wcsMatch test succeeds.
    

    eaf3b304

    commit eaf3b304012319a76db97dfeaf32d0dcc0fb717e
    Author: jbosch 
    Date:   Fri Oct 14 22:11:46 2011 +0000
    
        afw #1780 - now building with new sconsUtils and third-party packages (aside from gsl+interpolation issues and tests currently also failing on trunk).
    

    5b522953

    commit 5b522953c3a80b54c7832793f353c7e00d3b5ea7
    Author: Jim Bosch 
    Date:   Tue Nov 20 14:53:52 2012 -0500
    
        Convert tests to use MEFs (requires afwdata update), remove a worthless one.
    

    Commits in /Users/nate/repos_lsst/afw/

    ed95653a

    commit ed95653aae0db5c64fec82321af822db861c9e9c
    Author: Joshua Hoblitt 
    Date:   Thu May 21 14:38:34 2015 -0700
    
        replace eups.productDir() calls with lsst.utils.getPackageDir()
    

    Return to list

    tests/box.py

    Diff:

    1 a8e2a7e9 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? + # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for geom.Box2I, geom.Box2D Run with: ./Box.py or python >>> import box; box.run() """ import os import sys import unittest import numpy import lsst.utils.tests as utilsTests import lsst.pex.exceptions import lsst.afw.geom as geom
    44 4bae7ca1 + numpy.random.seed(1)
    45 4bae7ca1 +
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class Box2ITestCase(unittest.TestCase): def testEmpty(self): box = geom.Box2I() self.assert_(box.isEmpty()) self.assertEqual(box.getWidth(), 0) self.assertEqual(box.getHeight(), 0) for x in (-1,0,1): for y in (-1,0,1): point = geom.Point2I(x,y) self.assertFalse(box.contains(point)) box.include(point) self.assert_(box.contains(point)) box = geom.Box2I() box.grow(3) self.assert_(box.isEmpty()) def testConstruction(self): for n in range(10): xmin, xmax, ymin, ymax = [int(i) for i in numpy.random.randint(low=-5, high=5, size=4)] if xmin > xmax: xmin, xmax = xmax, xmin if ymin > ymax: ymin, ymax = ymax, ymin pmin = geom.Point2I(xmin,ymin) pmax = geom.Point2I(xmax,ymax) # min/max constructor box = geom.Box2I(pmin,pmax) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getMax(), pmax) box = geom.Box2I(pmax,pmin) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getMax(), pmax) box = geom.Box2I(pmin,pmax,False) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getMax(), pmax) box = geom.Box2I(pmax,pmin,False) self.assert_(box.isEmpty() or pmax == pmin) # min/dim constructor dim = geom.Extent2I(1) + pmax - pmin if any(dim.eq(0)): box = geom.Box2I(pmin,dim) self.assert_(box.isEmpty()) box = geom.Box2I(pmin,dim,False) self.assert_(box.isEmpty()) else: box = geom.Box2I(pmin,dim) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getDimensions(), dim) box = geom.Box2I(pmin,dim,False) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getDimensions(), dim) dim = -dim box = geom.Box2I(pmin,dim) self.assertEqual(box.getMin(), pmin + dim + geom.Extent2I(1)) self.assertEqual(box.getDimensions(), geom.Extent2I(abs(dim.getX()),abs(dim.getY()))) def testOverflowDetection(self): try: box = geom.Box2I(geom.Point2I(2147483645, 149), geom.Extent2I(8,8))
    105 b47297e2 - except lsst.pex.exceptions.LsstCppException as err:
    ? ^^^^^^^ ^^^^^^ ^
    107 6fc1c3d1 + except lsst.pex.exceptions.OverflowError as err:
    ? ^^^^^^^^ ^^ ^
    106 b47297e2 - self.assert_(isinstance(err.args[0], lsst.pex.exceptions.OverflowErrorException))
    108 6fc1c3d1 + pass
    else: # On some platforms, sizeof(int) may be > 4, so this test doesn't overflow. # In that case, we just verify that there was in fact no overflow. # It's hard to construct a more platform-independent test because Python doesn't # provide an easy way to get sizeof(int); note that sys.maxint is usually sizeof(long). self.assert_(box.getWidth() > 0) def testSwap(self): x00, y00, x01, y01 = (0,1,2,3) x10, y10, x11, y11 = (4,5,6,7) box0 = geom.Box2I(geom.PointI(x00, y00), geom.PointI(x01, y01)) box1 = geom.Box2I(geom.PointI(x10, y10), geom.PointI(x11, y11)) box0.swap(box1) self.assertEqual(box0.getMinX(), x10); self.assertEqual(box0.getMinY(), y10); self.assertEqual(box0.getMaxX(), x11); self.assertEqual(box0.getMaxY(), y11); self.assertEqual(box1.getMinX(), x00); self.assertEqual(box1.getMinY(), y00); self.assertEqual(box1.getMaxX(), x01); self.assertEqual(box1.getMaxY(), y01); def testConversion(self): for n in range(10): xmin, xmax, ymin, ymax = numpy.random.uniform(low=-10, high=10, size=4) if xmin > xmax: xmin, xmax = xmax, xmin if ymin > ymax: ymin, ymax = ymax, ymin fpMin = geom.Point2D(xmin,ymin) fpMax = geom.Point2D(xmax,ymax) if any((fpMax-fpMin).lt(3)): continue # avoid empty boxes fpBox = geom.Box2D(fpMin, fpMax) intBoxBig = geom.Box2I(fpBox, geom.Box2I.EXPAND) fpBoxBig = geom.Box2D(intBoxBig) intBoxSmall = geom.Box2I(fpBox, geom.Box2I.SHRINK) fpBoxSmall = geom.Box2D(intBoxSmall) self.assert_(fpBoxBig.contains(fpBox)) self.assert_(fpBox.contains(fpBoxSmall)) self.assert_(intBoxBig.contains(intBoxSmall)) self.assert_(geom.Box2D(intBoxBig)) self.assertEqual(geom.Box2I(fpBoxBig, geom.Box2I.EXPAND), intBoxBig) self.assertEqual(geom.Box2I(fpBoxSmall, geom.Box2I.SHRINK), intBoxSmall) self.assert_(geom.Box2I(geom.Box2D()).isEmpty())
    152 b47297e2 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException, geom.Box2I,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    154 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError, geom.Box2I,
    ? ^^ ^ ^^ ^ geom.Box2D(geom.Point2D(), geom.Point2D(float("inf"), float("inf")))) def testAccessors(self): xmin, xmax, ymin, ymax = [int(i) for i in numpy.random.randint(low=-5, high=5, size=4)] if xmin > xmax: xmin, xmax = xmax, xmin if ymin > ymax: ymin, ymax = ymax, ymin pmin = geom.Point2I(xmin,ymin) pmax = geom.Point2I(xmax,ymax) box = geom.Box2I(pmin, pmax, True) self.assertEqual(pmin, box.getMin()) self.assertEqual(pmax, box.getMax()) self.assertEqual(box.getMinX(), xmin) self.assertEqual(box.getMinY(), ymin) self.assertEqual(box.getMaxX(), xmax) self.assertEqual(box.getMaxY(), ymax) self.assertEqual(box.getBegin(), pmin) self.assertEqual(box.getEnd(), (pmax + geom.Extent2I(1))) self.assertEqual(box.getBeginX(), xmin) self.assertEqual(box.getBeginY(), ymin) self.assertEqual(box.getEndX(), xmax + 1) self.assertEqual(box.getEndY(), ymax + 1) self.assertEqual(box.getDimensions(), (pmax - pmin + geom.Extent2I(1))) self.assertEqual(box.getWidth(), (xmax - xmin + 1)) self.assertEqual(box.getHeight(), (ymax - ymin + 1)) self.assertAlmostEqual(box.getArea(), box.getWidth() * box.getHeight(), places=14) corners = box.getCorners() self.assertEqual(corners[0], box.getMin()) self.assertEqual(corners[1].getX(), box.getMaxX()) self.assertEqual(corners[1].getY(), box.getMinY()) self.assertEqual(corners[2], box.getMax()) self.assertEqual(corners[3].getX(), box.getMinX()) self.assertEqual(corners[3].getY(), box.getMaxY()) def testRelations(self): box = geom.Box2I(geom.Point2I(-2,-3), geom.Point2I(2,1), True) self.assertNotEqual(box, (3,4,5)) # should not throw self.assert_(box.contains(geom.Point2I(0,0))) self.assert_(box.contains(geom.Point2I(-2,-3))) self.assert_(box.contains(geom.Point2I(2,-3))) self.assert_(box.contains(geom.Point2I(2,1))) self.assert_(box.contains(geom.Point2I(-2,1))) self.assertFalse(box.contains(geom.Point2I(-2,-4))) self.assertFalse(box.contains(geom.Point2I(-3,-3))) self.assertFalse(box.contains(geom.Point2I(2,-4))) self.assertFalse(box.contains(geom.Point2I(3,-3))) self.assertFalse(box.contains(geom.Point2I(3,1))) self.assertFalse(box.contains(geom.Point2I(2,2))) self.assertFalse(box.contains(geom.Point2I(-3,1))) self.assertFalse(box.contains(geom.Point2I(-2,2))) self.assert_(box.contains(geom.Box2I(geom.Point2I(-1,-2), geom.Point2I(1,0)))) self.assert_(box.contains(box)) self.assertFalse(box.contains(geom.Box2I(geom.Point2I(-2,-3), geom.Point2I(2,2)))) self.assertFalse(box.contains(geom.Box2I(geom.Point2I(-2,-3), geom.Point2I(3,1)))) self.assertFalse(box.contains(geom.Box2I(geom.Point2I(-3,-3), geom.Point2I(2,1)))) self.assertFalse(box.contains(geom.Box2I(geom.Point2I(-3,-4), geom.Point2I(2,1)))) self.assert_(box.overlaps(geom.Box2I(geom.Point2I(-2,-3), geom.Point2I(2,2)))) self.assert_(box.overlaps(geom.Box2I(geom.Point2I(-2,-3), geom.Point2I(3,1)))) self.assert_(box.overlaps(geom.Box2I(geom.Point2I(-3,-3), geom.Point2I(2,1)))) self.assert_(box.overlaps(geom.Box2I(geom.Point2I(-3,-4), geom.Point2I(2,1)))) self.assert_(box.overlaps(geom.Box2I(geom.Point2I(-1,-2), geom.Point2I(1,0)))) self.assert_(box.overlaps(box)) self.assertFalse(box.overlaps(geom.Box2I(geom.Point2I(-5,-3), geom.Point2I(-3,1)))) self.assertFalse(box.overlaps(geom.Box2I(geom.Point2I(-2,-6), geom.Point2I(2,-4)))) self.assertFalse(box.overlaps(geom.Box2I(geom.Point2I(3,-3), geom.Point2I(4,1)))) self.assertFalse(box.overlaps(geom.Box2I(geom.Point2I(-2,2), geom.Point2I(2,2)))) def testMutators(self): box = geom.Box2I(geom.Point2I(-2,-3), geom.Point2I(2,1), True) box.grow(1) self.assertEqual(box, geom.Box2I(geom.Point2I(-3,-4), geom.Point2I(3,2), True)) box.grow(geom.Extent2I(2,3)) self.assertEqual(box, geom.Box2I(geom.Point2I(-5,-7), geom.Point2I(5,5), True)) box.shift(geom.Extent2I(3,2)) self.assertEqual(box, geom.Box2I(geom.Point2I(-2,-5), geom.Point2I(8,7), True)) box.include(geom.Point2I(-4,2)) self.assertEqual(box, geom.Box2I(geom.Point2I(-4,-5), geom.Point2I(8,7), True)) box.include(geom.Point2I(0,-6)) self.assertEqual(box, geom.Box2I(geom.Point2I(-4,-6), geom.Point2I(8,7), True)) box.include(geom.Box2I(geom.Point2I(0,0), geom.Point2I(10,11), True)) self.assertEqual(box, geom.Box2I(geom.Point2I(-4,-6), geom.Point2I(10,11), True)) box.clip(geom.Box2I(geom.Point2I(0,0), geom.Point2I(11,12), True)) self.assertEqual(box, geom.Box2I(geom.Point2I(0,0), geom.Point2I(10,11), True)) box.clip(geom.Box2I(geom.Point2I(-1,-2), geom.Point2I(5,4), True)) self.assertEqual(box, geom.Box2I(geom.Point2I(0,0), geom.Point2I(5,4), True)) class Box2DTestCase(unittest.TestCase): def testEmpty(self): box = geom.Box2D() self.assert_(box.isEmpty()) self.assertEqual(box.getWidth(), 0.0) self.assertEqual(box.getHeight(), 0.0) for x in (-1,0,1): for y in (-1,0,1): point = geom.Point2D(x,y) self.assertFalse(box.contains(point)) box.include(point) self.assert_(box.contains(point)) box = geom.Box2D() box.grow(3) self.assert_(box.isEmpty()) def testConstruction(self): for n in range(10): xmin, xmax, ymin, ymax = numpy.random.uniform(low=-5, high=5, size=4) if xmin > xmax: xmin, xmax = xmax, xmin if ymin > ymax: ymin, ymax = ymax, ymin pmin = geom.Point2D(xmin,ymin) pmax = geom.Point2D(xmax,ymax) # min/max constructor box = geom.Box2D(pmin,pmax) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getMax(), pmax) box = geom.Box2D(pmax,pmin) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getMax(), pmax) box = geom.Box2D(pmin,pmax,False) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getMax(), pmax) box = geom.Box2D(pmax,pmin,False) self.assert_(box.isEmpty()) # min/dim constructor dim = pmax - pmin if any(dim.eq(0)): box = geom.Box2D(pmin,dim) self.assert_(box.isEmpty()) box = geom.Box2D(pmin,dim,False) self.assert_(box.isEmpty()) else: box = geom.Box2D(pmin,dim) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getDimensions(), dim) box = geom.Box2D(pmin,dim,False) self.assertEqual(box.getMin(), pmin) self.assertEqual(box.getDimensions(), dim) dim = -dim box = geom.Box2D(pmin,dim) self.assertEqual(box.getMin(), pmin + dim) self.assert_(numpy.allclose(box.getDimensions(), geom.Extent2D(abs(dim.getX()),abs(dim.getY())))) def testSwap(self): x00, y00, x01, y01 = (0.,1.,2.,3.) x10, y10, x11, y11 = (4.,5.,6.,7.) box0 = geom.Box2D(geom.PointD(x00, y00), geom.PointD(x01, y01)) box1 = geom.Box2D(geom.PointD(x10, y10), geom.PointD(x11, y11)) box0.swap(box1) self.assertEqual(box0.getMinX(), x10); self.assertEqual(box0.getMinY(), y10); self.assertEqual(box0.getMaxX(), x11); self.assertEqual(box0.getMaxY(), y11); self.assertEqual(box1.getMinX(), x00); self.assertEqual(box1.getMinY(), y00); self.assertEqual(box1.getMaxX(), x01); self.assertEqual(box1.getMaxY(), y01); def testAccessors(self): xmin, xmax, ymin, ymax = numpy.random.uniform(low=-5, high=5, size=4) if xmin > xmax: xmin, xmax = xmax, xmin if ymin > ymax: ymin, ymax = ymax, ymin pmin = geom.Point2D(xmin,ymin) pmax = geom.Point2D(xmax,ymax) box = geom.Box2D(pmin, pmax, True) self.assertEqual(pmin, box.getMin()) self.assertEqual(pmax, box.getMax()) self.assertEqual(box.getMinX(), xmin) self.assertEqual(box.getMinY(), ymin) self.assertEqual(box.getMaxX(), xmax) self.assertEqual(box.getMaxY(), ymax) self.assertEqual(box.getDimensions(), (pmax - pmin)) self.assertEqual(box.getWidth(), (xmax - xmin)) self.assertEqual(box.getHeight(), (ymax - ymin)) self.assertEqual(box.getArea(), box.getWidth() * box.getHeight()) self.assertEqual(box.getCenterX(), 0.5*(pmax.getX() + pmin.getX())) self.assertEqual(box.getCenterY(), 0.5*(pmax.getY() + pmin.getY())) self.assertEqual(box.getCenter().getX(), box.getCenterX()) self.assertEqual(box.getCenter().getY(), box.getCenterY()) corners = box.getCorners() self.assertEqual(corners[0], box.getMin()) self.assertEqual(corners[1].getX(), box.getMaxX()) self.assertEqual(corners[1].getY(), box.getMinY()) self.assertEqual(corners[2], box.getMax()) self.assertEqual(corners[3].getX(), box.getMinX()) self.assertEqual(corners[3].getY(), box.getMaxY()) def testRelations(self): box = geom.Box2D(geom.Point2D(-2,-3), geom.Point2D(2,1), True) self.assert_(box.contains(geom.Point2D(0,0))) self.assert_(box.contains(geom.Point2D(-2,-3))) self.assertFalse(box.contains(geom.Point2D(2,-3))) self.assertFalse(box.contains(geom.Point2D(2,1))) self.assertFalse(box.contains(geom.Point2D(-2,1))) self.assert_(box.contains(geom.Box2D(geom.Point2D(-1,-2), geom.Point2D(1,0)))) self.assert_(box.contains(box)) self.assertFalse(box.contains(geom.Box2D(geom.Point2D(-2,-3), geom.Point2D(2,2)))) self.assertFalse(box.contains(geom.Box2D(geom.Point2D(-2,-3), geom.Point2D(3,1)))) self.assertFalse(box.contains(geom.Box2D(geom.Point2D(-3,-3), geom.Point2D(2,1)))) self.assertFalse(box.contains(geom.Box2D(geom.Point2D(-3,-4), geom.Point2D(2,1)))) self.assert_(box.overlaps(geom.Box2D(geom.Point2D(-2,-3), geom.Point2D(2,2)))) self.assert_(box.overlaps(geom.Box2D(geom.Point2D(-2,-3), geom.Point2D(3,1)))) self.assert_(box.overlaps(geom.Box2D(geom.Point2D(-3,-3), geom.Point2D(2,1)))) self.assert_(box.overlaps(geom.Box2D(geom.Point2D(-3,-4), geom.Point2D(2,1)))) self.assert_(box.overlaps(geom.Box2D(geom.Point2D(-1,-2), geom.Point2D(1,0)))) self.assert_(box.overlaps(box)) self.assertFalse(box.overlaps(geom.Box2D(geom.Point2D(-5,-3), geom.Point2D(-3,1)))) self.assertFalse(box.overlaps(geom.Box2D(geom.Point2D(-2,-6), geom.Point2D(2,-4)))) self.assertFalse(box.overlaps(geom.Box2D(geom.Point2D(3,-3), geom.Point2D(4,1)))) self.assertFalse(box.overlaps(geom.Box2D(geom.Point2D(-2,2), geom.Point2D(2,2)))) self.assertFalse(box.overlaps(geom.Box2D(geom.Point2D(-2,-5), geom.Point2D(2,-3)))) self.assertFalse(box.overlaps(geom.Box2D(geom.Point2D(-4,-3), geom.Point2D(-2,1)))) self.assertFalse(box.contains(geom.Box2D(geom.Point2D(-2,1), geom.Point2D(2,3)))) self.assertFalse(box.contains(geom.Box2D(geom.Point2D(2,-3), geom.Point2D(4,1)))) def testMutators(self): box = geom.Box2D(geom.Point2D(-2,-3), geom.Point2D(2,1), True) box.grow(1) self.assertEqual(box, geom.Box2D(geom.Point2D(-3,-4), geom.Point2D(3,2), True)) box.grow(geom.Extent2D(2,3)) self.assertEqual(box, geom.Box2D(geom.Point2D(-5,-7), geom.Point2D(5,5), True)) box.shift(geom.Extent2D(3,2)) self.assertEqual(box, geom.Box2D(geom.Point2D(-2,-5), geom.Point2D(8,7), True)) box.include(geom.Point2D(-4,2)) self.assertEqual(box, geom.Box2D(geom.Point2D(-4,-5), geom.Point2D(8,7), True)) self.assert_(box.contains(geom.Point2D(-4,2))) box.include(geom.Point2D(0,-6)) self.assertEqual(box, geom.Box2D(geom.Point2D(-4,-6), geom.Point2D(8,7), True)) box.include(geom.Box2D(geom.Point2D(0,0), geom.Point2D(10,11), True)) self.assertEqual(box, geom.Box2D(geom.Point2D(-4,-6), geom.Point2D(10,11), True)) box.clip(geom.Box2D(geom.Point2D(0,0), geom.Point2D(11,12), True)) self.assertEqual(box, geom.Box2D(geom.Point2D(0,0), geom.Point2D(10,11), True)) box.clip(geom.Box2D(geom.Point2D(-1,-2), geom.Point2D(5,4), True)) self.assertEqual(box, geom.Box2D(geom.Point2D(0,0), geom.Point2D(5,4), True)) def testFlipI(self): parentExtent = geom.Extent2I(15,20) x00, y00, x11, y11 = (8,11,13,16) lrx00,lry00,lrx11,lry11 = (1,11,6,16) tbx00,tby00,tbx11,tby11 = (8,3,13,8) box0 = geom.Box2I(geom.Point2I(x00, y00), geom.Point2I(x11, y11)) box1 = geom.Box2I(geom.Point2I(x00, y00), geom.Point2I(x11, y11)) box0.flipLR(parentExtent[0]) box1.flipTB(parentExtent[1]) #test flip RL self.assertEqual(box0.getMinX(), lrx00); self.assertEqual(box0.getMinY(), lry00); self.assertEqual(box0.getMaxX(), lrx11); self.assertEqual(box0.getMaxY(), lry11); #test flip TB self.assertEqual(box1.getMinX(), tbx00); self.assertEqual(box1.getMinY(), tby00); self.assertEqual(box1.getMaxX(), tbx11); self.assertEqual(box1.getMaxY(), tby11); def testFlipD(self): parentExtent = geom.Extent2D(15.1,20.6) x00, y00, x11, y11 = (8.3,11.4,13.2,16.9) lrx00,lry00,lrx11,lry11 = (1.9,11.4,6.8,16.9) tbx00,tby00,tbx11,tby11 = (8.3,3.7,13.2,9.2) box0 = geom.Box2D(geom.Point2D(x00, y00), geom.Point2D(x11, y11)) box1 = geom.Box2D(geom.Point2D(x00, y00), geom.Point2D(x11, y11)) box0.flipLR(parentExtent[0]) box1.flipTB(parentExtent[1]) #test flip RL self.assertAlmostEqual(box0.getMinX(), lrx00, places=6); self.assertAlmostEqual(box0.getMinY(), lry00, places=6); self.assertAlmostEqual(box0.getMaxX(), lrx11, places=6); self.assertAlmostEqual(box0.getMaxY(), lry11, places=6); #test flip TB self.assertAlmostEqual(box1.getMinX(), tbx00, places=6); self.assertAlmostEqual(box1.getMinY(), tby00, places=6); self.assertAlmostEqual(box1.getMaxX(), tbx11, places=6); self.assertAlmostEqual(box1.getMaxY(), tby11, places=6); #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(Box2ITestCase) suites += unittest.makeSuite(Box2DTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(exit=False): """Run the tests""" utilsTests.run(suite(), exit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b47297e2

    commit b47297e251e0a6c5a299e75c23da267d2e4f3406
    Author: Jim Bosch 
    Date:   Sat Mar 30 17:26:05 2013 -0400
    
        Add overflow and finiteness detection to Box2I constructors (#2769).
    

    a8e2a7e9

    commit a8e2a7e9666f30c2384ae6bb3557181f65684db7
    Author: jbosch 
    Date:   Mon Dec 21 23:37:41 2009 +0000
    
        afw/#1095 - swig wrappers, some tests for BoxI and BoxD.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    4bae7ca1

    commit 4bae7ca131d04a3f68e47748b0423617ffd33000
    Author: Paul Price 
    Date:   Wed Aug 6 16:40:49 2014 -0400
    
        tests: seed random number generator to make tests deterministic
    

    Return to list

    python/lsst/afw/display/init.py

    Diff:

                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    
                    """Application Framework code to display images on ds9
                    """
    
    25 7c7e5c6d - from ds9 import *
    25 bde0ab27 + from interface import *
    26 bde0ab27 + from .utils import Mosaic

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7c7e5c6d

    commit 7c7e5c6d5384cc9d5c9c2b316b0f523d21dbcb13
    Author: rowen 
    Date:   Thu Mar 27 17:39:11 2008 +0000
    
        afw reorg:
        - lsst.afw will not import sub-packages; thus you need not import all of afw
        - added "orphans.txt": a list of files that belong elsewhere
    

    Commits in /Users/nate/repos_lsst/afw/

    bde0ab27

    commit bde0ab27a9add858f810563213c1424f9e63ddde
    Author: Robert Lupton the Good 
    Date:   Sun Apr 12 16:00:47 2015 -0300
    
        Implement RFC-42
        
        N.b. that you need display_ds9 to use the ds9 backend
        N.b. support frame only in cameraGeom.utils top-level routine, showCamera
    

    Return to list

    include/lsst/afw/table/Exposure.h

    Diff:

                    // -*- lsst-c++ -*-
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010, 2011 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #ifndef AFW_TABLE_Exposure_h_INCLUDED
                    #define AFW_TABLE_Exposure_h_INCLUDED
                    
                    #include "lsst/afw/geom/Box.h"
                    #include "lsst/afw/table/BaseRecord.h"
                    #include "lsst/afw/table/BaseTable.h"
                    #include "lsst/afw/table/SortedCatalog.h"
                    #include "lsst/afw/table/BaseColumnView.h"
                    #include "lsst/afw/table/io/FitsWriter.h"
                    
                    namespace lsst { namespace afw {
                    
                    namespace image {
                    class Wcs;
                    class Calib;
    
    38 18d4b1ff - class ApCorrMap;
    } // namespace image namespace detection { class Psf; } // namespace detection
    44 ad63680a -
    45 fd15d1dd - namespace geom { namespace polygon {
    46 fd15d1dd - class Polygon;
    47 fd15d1dd - }}
    namespace table { class ExposureRecord; class ExposureTable; template class ExposureCatalogT; namespace io { class OutputArchiveHandle; class InputArchive; } // namespace io /** * @brief Record class used to store exposure metadata. */ class ExposureRecord : public BaseRecord { public: typedef ExposureTable Table; typedef ColumnViewT ColumnView; typedef ExposureCatalogT Catalog; typedef ExposureCatalogT ConstCatalog; CONST_PTR(ExposureTable) getTable() const { return boost::static_pointer_cast(BaseRecord::getTable()); } RecordId getId() const; void setId(RecordId id); geom::Box2I getBBox() const; void setBBox(geom::Box2I const & bbox); /** * @brief Return true if the bounding box contains the given celestial coordinate point, taking
    81 ad63680a + * into account the Wcs of the ExposureRecord.
    86 74a95535 - * into account the Wcs of the ExposureRecord. If includeValidPolygon is true it will also check
    87 74a95535 - * that the point is within the valid validPolygon.
    88 ad63680a - *
    89 ad63680a - * @throw LogicErrorException if the ExposureRecord has no Wcs.
    90 ad63680a - */
    ? -
    82 ad63680a + *
    91 74a95535 - bool contains(Coord const & coord, bool includeValidPolygon = false) const;
    83 21597d88 + * @throw LogicError if the ExposureRecord has no Wcs.
    84 ad63680a + */
    85 ad63680a + bool contains(Coord const & coord) const;
    /** * @brief Return true if the bounding box contains the given point, taking into account its Wcs
    89 ad63680a + * (given) and the Wcs of the ExposureRecord.
    95 74a95535 - * (given) and the Wcs of the ExposureRecord. If includeValidPolygon is true it will also check
    96 74a95535 - * that the point is within the valid validPolygon.
    97 ad63680a - *
    98 ad63680a - * @throw LogicErrorException if the ExposureRecord has no Wcs.
    99 ad63680a - */
    ? -
    90 ad63680a + *
    91 21597d88 + * @throw LogicError if the ExposureRecord has no Wcs.
    92 ad63680a + */
    100 74a95535 - bool contains(geom::Point2D const & point, image::Wcs const & wcs, bool includeValidPolygon = false) const;
    ? ----------------------------------
    93 ad63680a + bool contains(geom::Point2D const & point, image::Wcs const & wcs) const;
    //@{
    103 18d4b1ff - /// Get/Set the the attached Wcs, Psf, Calib, or ApCorrMap. No copies are made.
    ? --------------
    96 ad63680a + /// Get/Set the the attached Wcs, Psf, or Calib. No copies are made.
    ? +++ CONST_PTR(image::Wcs) getWcs() const { return _wcs; } void setWcs(CONST_PTR(image::Wcs) wcs) { _wcs = wcs; } CONST_PTR(detection::Psf) getPsf() const { return _psf; } void setPsf(CONST_PTR(detection::Psf) psf) { _psf = psf; } CONST_PTR(image::Calib) getCalib() const { return _calib; } void setCalib(CONST_PTR(image::Calib) calib) { _calib = calib; }
    112 18d4b1ff -
    113 18d4b1ff - CONST_PTR(image::ApCorrMap) getApCorrMap() const { return _apCorrMap; }
    114 18d4b1ff - void setApCorrMap(CONST_PTR(image::ApCorrMap) apCorrMap) { _apCorrMap = apCorrMap; }
    115 fd15d1dd -
    116 fd15d1dd - CONST_PTR(geom::polygon::Polygon) getValidPolygon() const { return _validPolygon; }
    117 fd15d1dd - void setValidPolygon(CONST_PTR(geom::polygon::Polygon) polygon) { _validPolygon = polygon; }
    //@} protected: ExposureRecord(PTR(ExposureTable) const & table); virtual void _assign(BaseRecord const & other); private: CONST_PTR(image::Wcs) _wcs; CONST_PTR(detection::Psf) _psf; CONST_PTR(image::Calib) _calib;
    130 18d4b1ff - CONST_PTR(image::ApCorrMap) _apCorrMap;
    131 fd15d1dd - CONST_PTR(geom::polygon::Polygon) _validPolygon;
    }; /** * @brief Table class used to store exposure metadata. * * @copydetails ExposureRecord */ class ExposureTable : public BaseTable { public: typedef ExposureRecord Record; typedef ColumnViewT ColumnView; typedef ExposureCatalogT Catalog; typedef ExposureCatalogT ConstCatalog; /** * @brief Construct a new table. * * @param[in] schema Schema that defines the fields, offsets, and record size for the table. */ static PTR(ExposureTable) make(Schema const & schema); /** * @brief Return a minimal schema for Exposure tables and records. * * The returned schema can and generally should be modified further, * but many operations on ExposureRecords will assume that at least the fields * provided by this routine are present. */
    161 ad63680a - static Schema makeMinimalSchema() { return getMinimalSchema().schema; }
    146 af38dfb3 + static Schema makeMinimalSchema() {
    147 af38dfb3 + Schema r = getMinimalSchema().schema;
    148 af38dfb3 + r.disconnectAliases();
    149 af38dfb3 + return r;
    150 af38dfb3 + }
    /** * @brief Return true if the given schema is a valid ExposureTable schema. * * This will always be true if the given schema was originally constructed * using makeMinimalSchema(), and will rarely be true otherwise. */ static bool checkSchema(Schema const & other) { return other.contains(getMinimalSchema().schema); } //@{ /** * Get keys for standard fields shared by all references. * * These keys are used to implement getters and setters on ExposureRecord. */ /// @brief Key for the unique ID. static Key getIdKey() { return getMinimalSchema().id; } /// @brief Key for the minimum point of the bbox. static Key< Point > getBBoxMinKey() { return getMinimalSchema().bboxMin; } /// @brief Key for the maximum point of the bbox. static Key< Point > getBBoxMaxKey() { return getMinimalSchema().bboxMax; } //@} /// @copydoc BaseTable::clone PTR(ExposureTable) clone() const { return boost::static_pointer_cast(_clone()); } /// @copydoc BaseTable::makeRecord PTR(ExposureRecord) makeRecord() { return boost::static_pointer_cast(_makeRecord()); } /// @copydoc BaseTable::copyRecord PTR(ExposureRecord) copyRecord(BaseRecord const & other) { return boost::static_pointer_cast(BaseTable::copyRecord(other)); } /// @copydoc BaseTable::copyRecord PTR(ExposureRecord) copyRecord(BaseRecord const & other, SchemaMapper const & mapper) { return boost::static_pointer_cast(BaseTable::copyRecord(other, mapper)); } protected: ExposureTable(Schema const & schema); ExposureTable(ExposureTable const & other); private: // Struct that holds the minimal schema and the special keys we've added to it. struct MinimalSchema { Schema schema; Key id; Key< Point > bboxMin; Key< Point > bboxMax; MinimalSchema(); }; // Return the singleton minimal schema. static MinimalSchema & getMinimalSchema(); friend class io::FitsWriter; template friend class ExposureCatalogT; // Return a writer object that knows how to save in FITS format. See also FitsWriter. virtual PTR(io::FitsWriter) makeFitsWriter(fits::Fits * fitsfile, int flags) const; PTR(io::FitsWriter) makeFitsWriter( fits::Fits * fitsfile, PTR(io::OutputArchive) archive, int flags ) const; }; #ifndef SWIG /** * @brief Custom catalog class for ExposureRecord/Table. * * We don't expect to subclass ExposureRecord/Table, so unlike other Catalogs we can (and do) define * some ExposureCatalogT member functions in Exposure.cc where the explicit instantiation is done. */ template class ExposureCatalogT : public SortedCatalogT { typedef SortedCatalogT Base; public: typedef RecordT Record; typedef typename Record::Table Table; typedef typename Base::iterator iterator; typedef typename Base::const_iterator const_iterator; /** * @brief Construct a vector from a table (or nothing). * * A vector with no table is considered invalid; a valid table must be assigned to it * before it can be used. */ explicit ExposureCatalogT(PTR(Table) const & table = PTR(Table)()) : Base(table) {} /// @brief Construct a vector from a schema, creating a table with Table::make(schema). explicit ExposureCatalogT(Schema const & schema) : Base(schema) {} /** * @brief Construct a vector from a table and an iterator range. * * If deep is true, new records will be created using table->copyRecord before being inserted. * If deep is false, records will be not be copied, but they must already be associated with * the given table. The table itself is never deep-copied. * * The iterator must dereference to a record reference or const reference rather than a pointer, * but should be implicitly convertible to a record pointer as well (see CatalogIterator). */ template ExposureCatalogT(PTR(Table) const & table, InputIterator first, InputIterator last, bool deep=false) : Base(table, first, last, deep) {} /** * @brief Shallow copy constructor from a container containing a related record type. * * This conversion only succeeds if OtherRecordT is convertible to RecordT and OtherTable is * convertible to Table. */ template ExposureCatalogT(ExposureCatalogT const & other) : Base(other) {} using Base::writeFits; /** * @brief Write a FITS binary table to an open file object. * * Instead of writing nested Persistables to an internal archive and appending it * to the FITS file, this overload inserts nested Persistables into the given * archive and does not save it, leaving it to the user to save it later. */ void writeFits(fits::Fits & fitsfile, PTR(io::OutputArchive) archive, int flags=0) const { PTR(io::FitsWriter) writer = this->getTable()->makeFitsWriter(&fitsfile, archive, flags); writer->write(*this); } /** * @brief Read a FITS binary table from a regular file. * * @param[in] filename Name of the file to read. * @param[in] hdu Number of the "header-data unit" to read (where 1 is the Primary HDU). * The default value of 0 is interpreted as "the first HDU with NAXIS != 0". * @param[in] flags Table-subclass-dependent bitflags that control the details of how to read * the catalog. See e.g. SourceFitsFlags. */ static ExposureCatalogT readFits(std::string const & filename, int hdu=0, int flags=0) { return io::FitsReader::apply(filename, hdu, flags); } /** * @brief Read a FITS binary table from a RAM file. * * @param[in] manager Object that manages the memory to be read. * @param[in] hdu Number of the "header-data unit" to read (where 1 is the Primary HDU). * The default value of 0 is interpreted as "the first HDU with NAXIS != 0". * @param[in] flags Table-subclass-dependent bitflags that control the details of how to read * the catalog. See e.g. SourceFitsFlags. */ static ExposureCatalogT readFits(fits::MemFileManager & manager, int hdu=0, int flags=0) { return io::FitsReader::apply(manager, hdu, flags); } /** * @brief Read a FITS binary table from a file object already at the correct extension. * * @param[in] fitsfile Fits file object to read from. * @param[in] flags Table-subclass-dependent bitflags that control the details of how to read * the catalog. See e.g. SourceFitsFlags. */ static ExposureCatalogT readFits(fits::Fits & fitsfile, int flags=0) { return io::FitsReader::apply(fitsfile, flags); } /** * @brief Read a FITS binary table from a file object already at the correct extension. * * This overload reads nested Persistables from the given archive instead of loading * a new archive from the HDUs following the catalog. */ static ExposureCatalogT readFits(fits::Fits & fitsfile, PTR(io::InputArchive) archive, int flags=0) { return io::FitsReader::apply(fitsfile, archive, flags); } /** * @brief Convenience output function for Persistables that contain an ExposureCatalog. * * Unlike writeFits, this saves main catalog to one of the tables within the archive, * as part of a Persistable's set of catalogs, rather than saving it to a separate HDU * not managed by the archive. */ void writeToArchive(io::OutputArchiveHandle & handle, bool ignoreUnpersistable=true) const; /** * @brief Convenience input function for Persistables that contain an ExposureCatalog. * * Unlike the FITS read methods, this reader is not polymorphically aware - it always * tries to create an ExposureTable rather than infer the type of table from the data. */ static ExposureCatalogT readFromArchive(io::InputArchive const & archive, BaseCatalog const & catalog); /** * @brief Return the subset of a catalog corresponding to the True values of the given mask array. * * The returned array's records are shallow copies, and hence will not in general be contiguous. */ ExposureCatalogT subset(ndarray::Array const & mask) const { return ExposureCatalogT(Base::subset(mask)); } /** * @brief Shallow copy a subset of another ExposureCatalog. Mostly here for * use from python. */ ExposureCatalogT subset(std::ptrdiff_t startd, std::ptrdiff_t stopd, std::ptrdiff_t step) const { return ExposureCatalogT(Base::subset(startd, stopd, step)); } /** * @brief Return a shallow subset of the catalog with only those records that contain the
    375 ad63680a + * given point.
    386 74a95535 - * given point. If includeValidPolygon is true it will also check that the point is within
    387 74a95535 - * the validPolygon.
    * * @sa ExposureRecord::contains */
    391 74a95535 - ExposureCatalogT subsetContaining(Coord const & coord, bool includeValidPolygon = false) const;
    ? ----------------------------------
    379 38ad08ad + ExposureCatalogT subsetContaining(Coord const & coord) const;
    /** * @brief Return a shallow subset of the catalog with only those records that contain the
    383 ad63680a + * given point.
    395 74a95535 - * given point. If includeValidPolygon is true it will also check that the point is within
    396 74a95535 - * the validPolygon.
    * * @sa ExposureRecord::contains */
    400 74a95535 - ExposureCatalogT subsetContaining(geom::Point2D const & point, image::Wcs const & wcs,
    ? ^^
    387 38ad08ad + ExposureCatalogT subsetContaining(geom::Point2D const & point, image::Wcs const & wcs) const;
    ? ^^^^^^^^
    401 74a95535 - bool includeValidPolygon = false) const;
    protected: explicit ExposureCatalogT(Base const & other) : Base(other) {} }; typedef ColumnViewT ExposureColumnView; typedef ExposureCatalogT ExposureCatalog; typedef ExposureCatalogT ConstExposureCatalog; inline RecordId ExposureRecord::getId() const { return get(ExposureTable::getIdKey()); } inline void ExposureRecord::setId(RecordId id) { set(ExposureTable::getIdKey(), id); } #endif // !SWIG }}} // namespace lsst::afw::table #endif // !AFW_TABLE_Exposure_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ad63680a

    commit ad63680a28ce16e98b156f40c8c0e3474ac65410
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:50:27 2013 -0500
    
        Add ExposureTable/Record/Catalog.
    

    74a95535

    commit 74a95535fc9f08c3cc5dc04a9467ddd33428ebb2
    Author: Bob Armstrong 
    Date:   Mon Sep 15 15:09:35 2014 -0400
    
        Exposure: Add includeValidPolygon option to contains function to check in valid region.
    

    18d4b1ff

    commit 18d4b1ff87ba59ac01d68d655548a78c2a04ac9f
    Author: Jim Bosch 
    Date:   Tue Jun 3 18:05:37 2014 -0400
    
        Add ApCorrMap to ExposureRecord
    

    fd15d1dd

    commit fd15d1dd03c8a1d1b06864fe90ad7d962bc7e567
    Author: Bob Armstrong 
    Date:   Mon Sep 15 08:34:26 2014 -0400
    
        Exposure: Add a Polygon object to Exposure.
        
        Polygons will be used to define valid regions for each CCD to
        reject vignetted regions when building the Coadd Psf.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    ad63680a

    commit ad63680a28ce16e98b156f40c8c0e3474ac65410
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:50:27 2013 -0500
    
        Add ExposureTable/Record/Catalog.
    

    af38dfb3

    commit af38dfb301ac07e9a48bfdcaf28140d730eb650c
    Author: Jim Bosch 
    Date:   Fri Nov 21 16:00:24 2014 -0600
    
        Disconnect aliases from minimal schemas
        
        Aliases are shared when Schemas are copied, which is usually desirable,
        but the makeMinimalSchema need to return new Schemas with a fresh set
        of aliases, or we end up with a lot of confusing behavior as one piece
        of code tries to set an alias and affects a completely different one,
        via a shared AliasMap they both got from the minimal schema.
    

    38ad08ad

    commit 38ad08ad2101e9cc2f59a107b39c5baad77c1c82
    Author: Jim Bosch 
    Date:   Thu Feb 28 12:52:12 2013 +0900
    
        Minor fixes to reflect code review for #2467.
        
        Removed trailing whitespace.
        Renamed ExposureCatalog::findContains to subsetContaining.
        Miscellaneous doc fixes.
        Added check on input sizes in SchemaMapper::join.
        OutputArchive::put overloads needed to forward permissive flag when delegating.
    

    Return to list

    include/lsst/afw/detection/FootprintArray.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    /**
                     *  @file FootprintArray.cc
                     *
                     *  @brief Templated source for FootprintArray.h functions.
                     *
                     *  This is an includeable template source file; it should be included whenever
                     *  the functions declared in FootprintArray.h are used.  Note that while
                     *  FootprintArray.h is included by afw/detection.h, FootprintArray.cc is not.
                     *  
                     *  The functions here have too many template parameters for explicit instantiation
                     *  to be attractive (because the number of instantiations is combinatorial).
                     */
                    
                    #include "lsst/afw/detection/FootprintArray.h"
                    #include "lsst/afw/detection/Footprint.h"
                    #include 
                    #include 
                    
                    namespace lsst{
                    namespace afw{
                    namespace detection{
                    
                    namespace {
                        /*
                         * Check that the Footprint is consistent with the src and dest arrays
                         *
                         * \note The names @c src and @c dest are appropriate when checking expandArrays's arguments, but
                         * are switched when checking flattenArray
                         */
                        template 
                        void checkConvertArray(Footprint const & fp,
                                              ndarray::Array const & src,
                                              ndarray::Array const & dest,
                                              geom::Point2I const & xy0
                                             )
                        {
                            geom::Box2I fpBox = fp.getBBox();
                            geom::Box2I imBox(xy0, geom::Extent2I(dest.template getSize<1>(), dest.template getSize<0>()));
                            
                            if (src.template getSize<0>() != fp.getArea()) {
    
    65 285ea506 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    65 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("Array outer size (%d) does not match" " footprint area (%d)." ) % dest.template getSize<0>() % fp.getArea())); } if (!imBox.contains(fpBox)) {
    72 285ea506 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    72 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ str(boost::format("Array bounding box (%d) does not contain footprint " "bounding box (%d)") % imBox % fpBox)); } } } template void flattenArray( Footprint const & fp, ndarray::Array const & src, ndarray::Array const & dest, geom::Point2I const & xy0 ) { typedef ndarray::Array SourceT; typedef ndarray::Array DestT; BOOST_STATIC_ASSERT(!boost::is_const::value); checkConvertArray(fp, dest, src, xy0); typename DestT::Iterator destIter(dest.begin()); for (Footprint::SpanList::const_iterator s = fp.getSpans().begin(); s != fp.getSpans().end(); ++s) { Span const & span = **s; typename SourceT::Reference row(src[span.getY() - xy0.getY()]); std::copy( row.begin() + span.getX0() - xy0.getX(), row.begin() + span.getX1() + 1 - xy0.getX(), destIter ); destIter += span.getWidth(); } } template void flattenArray( Footprint const & fp, ndarray::Array const & src, ndarray::Array const & dest, PixelOpT const& pixelOp, geom::Point2I const & xy0 ) { typedef ndarray::Array SourceT; typedef ndarray::Array DestT; BOOST_STATIC_ASSERT(!boost::is_const::value); checkConvertArray(fp, dest, src, xy0); typename DestT::Iterator destIter(dest.begin()); for (Footprint::SpanList::const_iterator s = fp.getSpans().begin(); s != fp.getSpans().end(); ++s) { Span const & span = **s; typename SourceT::Reference row(src[span.getY() - xy0.getY()]); typename SourceT::Reference::Iterator rowIter = row.begin() + span.getX0() - xy0.getX(); for (typename DestT::Iterator destEnd = destIter + span.getWidth(); destIter != destEnd; ++destIter, ++rowIter) { *destIter = *rowIter; *rowIter = pixelOp(*rowIter); } } } template ndarray::Array::type, N-1, N-1> flattenArray( Footprint const & fp, ndarray::Array const & src, geom::Point2I const & xy0 ) { ndarray::Vector shape = ndarray::concatenate(fp.getArea(), src.getShape().template last()); ndarray::Array::type, N-1,N-1> dest = ndarray::allocate(shape); flattenArray(fp, src, dest, xy0); return dest; } template void expandArray( Footprint const & fp, ndarray::Array const & src, ndarray::Array const & dest, geom::Point2I const & xy0 ) { typedef ndarray::Array SourceT; typedef ndarray::Array DestT; BOOST_STATIC_ASSERT(!boost::is_const::value); checkConvertArray(fp, src, dest, xy0); typename SourceT::Iterator srcIter(src.begin()); for (Footprint::SpanList::const_iterator s = fp.getSpans().begin(); s != fp.getSpans().end(); ++s) { Span const & span = **s; typename DestT::Reference row(dest[span.getY() - xy0.getY()]); std::copy(srcIter, srcIter + span.getWidth(), row.begin() + span.getX0() - xy0.getX()); srcIter += span.getWidth(); } } template void expandArray( Footprint const & fp, ndarray::Array const & src, ndarray::Array const & dest, PixelOpT const& pixelOp, geom::Point2I const & xy0 ) { typedef ndarray::Array SourceT; typedef ndarray::Array DestT; BOOST_STATIC_ASSERT(!boost::is_const::value); checkConvertArray(fp, src, dest, xy0); typename SourceT::Iterator srcIter(src.begin()); for (Footprint::SpanList::const_iterator s = fp.getSpans().begin(); s != fp.getSpans().end(); ++s) { Span const & span = **s; typename DestT::Reference row(dest[span.getY() - xy0.getY()]); typename DestT::Reference::Iterator rowIter = row.begin() + span.getX0() - xy0.getX(); for (typename SourceT::Iterator srcEnd = srcIter + span.getWidth(); srcIter != srcEnd; ++srcIter, ++rowIter) { *rowIter = pixelOp(*srcIter); } } } template ndarray::Array::type, N+1, N+1> expandArray( Footprint const & fp, ndarray::Array const & src, geom::Box2I const & bbox ) { geom::Box2I box(bbox); if (box.isEmpty()) { box = fp.getBBox(); } ndarray::Array::type, N+1, N+1> dest = ndarray::allocate( ndarray::concatenate( ndarray::makeVector(box.getHeight(), box.getWidth()), src.getShape().template last() ) ); dest.deep() = 0.0; expandArray(fp, src, dest, box.getMin()); return dest; } }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    285ea506

    commit 285ea506f9f760af2b5e2609e48f6a429530bf53
    Author: Robert Lupton the Good 
    Date:   Mon Nov 28 11:39:17 2011 -0500
    
        Add a version of expandArray that takes a functor to modify the image; rename origin to xy0
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/math/Kernel.h

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #ifndef LSST_AFW_MATH_KERNEL_H
                    #define LSST_AFW_MATH_KERNEL_H
                    /**
                     * @file
                     *
                     * @brief Declare the Kernel class and subclasses.
                     *
                     * @author Russell Owen
                     *
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    
                    #include "boost/mpl/or.hpp"
                    #include "boost/shared_ptr.hpp"
                    #include "boost/make_shared.hpp"
                    #include "boost/static_assert.hpp"
                    #include "boost/type_traits/is_same.hpp"
                    #include "boost/type_traits/is_base_and_derived.hpp"
                    
                    #include "boost/serialization/shared_ptr.hpp"
                    #include "boost/serialization/vector.hpp"
                    #include "boost/serialization/export.hpp"
                    
                    #include "lsst/daf/base/Persistable.h"
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/image/Utils.h"
                    #include "lsst/afw/math/Function.h"
                    #include "lsst/afw/math/traits.h"
                    
                    #include "lsst/afw/table/io/Persistable.h"
                    
                    namespace lsst {
                    namespace afw {
                    
                    namespace formatters {
                    class KernelFormatter;
                    }
                    
                    namespace math {
                    
                    #ifndef SWIG
                    using boost::serialization::make_nvp;
                    #endif
                    
                        /**
                         * @brief Kernels are used for convolution with MaskedImages and (eventually) Images
                         *
                         * Kernel is a virtual base class; it cannot be instantiated. The following notes apply to
                         * Kernel and to its subclasses.
                         *
                         * The template type should usually be float or double; integer kernels
                         * should be used with caution because they do not normalize well.
                         *
                         * The center pixel of a Kernel is at index: (width-1)/2, (height-1)/2. Thus it is centered along
                         * columns/rows if the kernel has an odd number of columns/rows and shifted 1/2 pixel towards 0 otherwise.
                         * A kernel should have an odd number of columns and rows unless it is intended to shift an image.
                         *
                         * Spatially Varying Kernels
                         *
                         * Kernels may optionally vary spatially (so long as they have any kernel parameters).
                         * To make a spatially varying kernel, specify a spatial function at construction
                         * (you cannot change your mind once the kernel is constructed).
                         * You must also specify a set of spatial parameters, and you may do this at construction
                         * and/or later by calling setSpatialParameters. The spatial parameters are a vector
                         * (one per kernel function parameter) of spatial function parameters. In other words
                         * the spatial parameters are a vector of vectors indexed as [kernel parameter][spatial parameter].
                         * The one spatial function is used to compute the kernel parameters at a given spatial position
                         * by computing each kernel parameter using its associated vector of spatial function parameters.
                         *
                         * The convolve function computes the spatial function at the pixel position (not index) of the image.
                         * See the convolve function for details.
                         *
                         * Note that if a kernel is spatially varying then you may not set the kernel parameters directly;
                         * that is the job of the spatial function! However, you may change the spatial parameters at any time.
                         *
                         * Design Notes
                         *
                         * The basic design is to use the same kernel class for both spatially varying and spatially invariant
                         * kernels. The user either does or does not supply a function describing the spatial variation
                         * at creation time. In addition, analytic kernels are described by a user-supplied function
                         * of the same basic type as the spatial variation function.
                         *
                         * Several other designs were considered, including:
                         * A) Use different classes for spatially varying and spatially invariant versions of each kernel.
                         * Thus instead of three basic kernel classes (FixedKernel, AnalyticKernel and LinearCombinationKernel)
                         * we would have five (since FixedKernel cannot be spatially varying). Robert Lupton argued that
                         * was a needless expansion of the class hiearchy and I agreed.
                         * B) Construct analytic kernels by defining a subclass of AnalyticKernel that is specific to the
                         * desired functional (e.g. GaussianAnalyticKernel). If spatial models are handled the same way
                         * then this creates a serious proliferation of kernel classes (even if we only have two different
                         * spatial models, e.g. polynomial and Chebyshev polynomial). I felt it made more sense to define
                         * the spatial model by some kind of function class (often called a "functor"), and since we needed
                         * such a class, I chose to use it for the analytic kernel as well.
                         *
                         * However, having a separate function class does introduce some potential inefficiencies.
                         * If a function is part of the class it can potentially be evaluated more quickly than calling
                         * a function for each pixel or spatial position.
                         *
                         * A possible variant on the current design is to define the spatial model and analytic kernel
                         * by specifying the functions as template parameters. This has the potential to regain some efficiency
                         * in evaluating the functions. However, it would be difficult or impossible to pre-instantiate
                         * the desired template classes, a requirement of the LSST coding standards.
                         *
                         * @ingroup afw
                         */
                        class Kernel : public lsst::daf::base::Citizen, public lsst::daf::base::Persistable,
                                       public afw::table::io::PersistableFacade,
                                       public afw::table::io::Persistable
                        {
                    
                        public:
                            typedef double Pixel;
                            typedef PTR(Kernel) Ptr;
                            typedef CONST_PTR(Kernel) ConstPtr;
                            typedef PTR(lsst::afw::math::Function2) SpatialFunctionPtr;
                            typedef lsst::afw::math::Function2 SpatialFunction;
                            typedef lsst::afw::math::NullFunction2 NullSpatialFunction;
                    
                            // Traits values for this class of Kernel
                            typedef generic_kernel_tag kernel_fill_factor;
                    
                            /**
                             * @brief Construct a null Kernel of size 0,0.
                             *
                             * A null constructor is primarily intended for persistence.
                             */
                            explicit Kernel();
                    
                            /**
                             * @brief Construct a spatially invariant Kernel or a spatially varying Kernel with one spatial function
                             * that is duplicated as needed.
                             *
    
    161 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if a spatial function is specified
    ? ^^^^^^ ^
    161 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if a spatial function is specified
    ? ^^ ^ * and the kernel has no parameters.
    163 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if a width or height < 1
    ? ^^^^^^ ^
    163 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if a width or height < 1
    ? ^^ ^ */ explicit Kernel( int width, ///< number of columns int height, ///< number of height unsigned int nKernelParams, ///< number of kernel parameters SpatialFunction const &spatialFunction=NullSpatialFunction() ///< spatial function, or NullSpatialFunction() if none specified ); /** * @brief Construct a spatially varying Kernel with a list of spatial functions (one per kernel parameter) * * Note: if the list of spatial functions is empty then the kernel is not spatially varying. *
    178 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if a width or height < 1
    ? ^^^^^^ ^
    178 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if a width or height < 1
    ? ^^ ^ */ explicit Kernel( int width, ///< number of columns int height, ///< number of height const std::vector spatialFunctionList ///< list of spatial function, one per kernel parameter ); virtual ~Kernel() {} /** * @brief Return a pointer to a deep copy of this kernel * * This kernel exists instead of a copy constructor * so one can obtain a copy of an actual kernel * instead of a useless copy of the base class. * * Every kernel subclass must override this method. * * @return a pointer to a deep copy of the kernel */ virtual PTR(Kernel) clone() const = 0; /** * @brief Compute an image (pixellized representation of the kernel) in place * * x, y are ignored if there is no spatial function. * * @return The kernel sum * * @note computeNewImage has been retired; it doesn't need to be a member *
    211 3771b5eb - * @throw lsst::pex::exceptions::InvalidParameterException if the image is the wrong size
    ? ^^^^^^ ^
    211 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the image is the wrong size
    ? ^^ ^
    212 b79a02a2 - * @throw lsst::pex::exceptions::OverflowErrorException if doNormalize is true and the kernel sum is
    ? ---------
    212 21597d88 + * @throw lsst::pex::exceptions::OverflowError if doNormalize is true and the kernel sum is
    * exactly 0 */ double computeImage( lsst::afw::image::Image &image, ///< image whose pixels are to be set (output); ///< xy0 of the image will be set to -kernel.getCtr() bool doNormalize, ///< normalize the image (so sum is 1)? double x = 0.0, ///< x (column position) at which to compute spatial function double y = 0.0 ///< y (row position) at which to compute spatial function ) const; /** * @brief Return the Kernel's dimensions (width, height) */ geom::Extent2I const getDimensions() const { return geom::Extent2I(_width, _height); } void setDimensions(geom::Extent2I dims) { _width = dims.getX(); _height = dims.getY(); } inline void setWidth(int width) { _width = width; } inline void setHeight(int height) { _height = height; } /** * @brief Return the Kernel's width */ inline int getWidth() const { return _width; } /** * @brief Return the Kernel's height */ inline int getHeight() const { return _height; } /** * @brief Return index of kernel's center */ inline lsst::afw::geom::Point2I getCtr() const { return lsst::afw::geom::Point2I(_ctrX, _ctrY); } /** * @brief Return x index of kernel's center * * @deprecated Use getCtr instead */ inline int getCtrX() const { return _ctrX; } /** * @brief Return y index of kernel's center * * @deprecated Use getCtr instead */ inline int getCtrY() const { return _ctrY; } /** * @brief return parent bounding box, with XY0 = -center */ inline lsst::afw::geom::Box2I getBBox() const { return lsst::afw::geom::Box2I( lsst::afw::geom::Point2I(-_ctrX, -_ctrY), lsst::afw::geom::Extent2I(_width, _height) ); } /** * @brief Return the number of kernel parameters (0 if none) */ inline unsigned int getNKernelParameters() const { return _nKernelParams; } /** * @brief Return the number of spatial parameters (0 if not spatially varying) */ inline int getNSpatialParameters() const { return this->isSpatiallyVarying() ? _spatialFunctionList[0]->getNParameters() : 0; } /** * @brief Return a clone of the specified spatial function (one component of the spatial model) * * @return a shared pointer to a spatial function. The function is a deep copy, so setting its parameters * has no effect on the kernel. *
    306 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if kernel not spatially varying
    ? ^^^^^^ ^
    306 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel not spatially varying
    ? ^^ ^
    307 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if index out of range
    ? ^^^^^^ ^
    307 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if index out of range
    ? ^^ ^ */ SpatialFunctionPtr getSpatialFunction( unsigned int index ///< index of desired spatial function; ///< must be in range [0, number spatial parameters - 1] ) const; /** * @brief Return a list of clones of the spatial functions. * * @return a list of shared pointers to spatial functions. The functions are deep copies, * so setting their parameters has no effect on the kernel. */ std::vector getSpatialFunctionList() const; /// Return a particular Kernel Parameter (no bounds checking). This version is slow, /// but specialisations may be faster virtual double getKernelParameter(unsigned int i) const { return getKernelParameters()[i]; } /** * @brief Return the current kernel parameters * * If the kernel is spatially varying then the parameters are those last computed. * See also computeKernelParametersFromSpatialModel. * If there are no kernel parameters then returns an empty vector. */ virtual std::vector getKernelParameters() const; /** * Given a bounding box for pixels one wishes to compute by convolving an image with this kernel, * return the bounding box of pixels that must be accessed on the image to be convolved. * Thus the box shifted by -kernel.getCtr() and its size is expanded by kernel.getDimensions()-1. * * @return the bbox expanded by the kernel. */ lsst::afw::geom::Box2I growBBox(lsst::afw::geom::Box2I const &bbox) const; /** * Given a bounding box for an image one wishes to convolve with this kernel, * return the bounding box for the region of pixels that can be computed. * Thus the box shifted by kernel.getCtr() and its size is reduced by kernel.getDimensions()-1. * * @return the bbox shrunk by the kernel. *
    353 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if the resulting box would have
    ? ^^^^^^ ^
    353 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the resulting box would have
    ? ^^ ^ * dimension < 1 in either axis */ lsst::afw::geom::Box2I shrinkBBox(lsst::afw::geom::Box2I const &bbox) const; /** * @brief Set index of kernel's center */ inline void setCtr(lsst::afw::geom::Point2I ctr) { _ctrX = ctr.getX(); _ctrY = ctr.getY(); _setKernelXY(); } /** * @brief Set x index of kernel's center * * @deprecated Use setCtr instead */ inline void setCtrX(int ctrX) { _ctrX = ctrX; _setKernelXY(); } /** * @brief Set y index of kernel's center * * @deprecated Use setCtr instead */ inline void setCtrY(int ctrY) { _ctrY = ctrY; _setKernelXY(); } /** * @brief Return the spatial parameters parameters (an empty vector if not spatially varying) */ inline std::vector > getSpatialParameters() const { std::vector > spatialParams; std::vector::const_iterator spFuncIter = _spatialFunctionList.begin(); for ( ; spFuncIter != _spatialFunctionList.end(); ++spFuncIter) { spatialParams.push_back((*spFuncIter)->getParameters()); } return spatialParams; } /** * @brief Return true iff the kernel is spatially varying (has a spatial function) */ inline bool isSpatiallyVarying() const { return _spatialFunctionList.size() != 0; } /** * @brief Set the kernel parameters of a spatially invariant kernel. *
    409 3771b5eb - * @throw lsst::pex::exceptions::RuntimeErrorException if the kernel has a spatial function
    ? ---------
    409 21597d88 + * @throw lsst::pex::exceptions::RuntimeError if the kernel has a spatial function
    410 3771b5eb - * @throw lsst::pex::exceptions::InvalidParameterException if the params vector is the wrong length
    ? ^^^^^^ ^
    410 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the params vector is the wrong length
    ? ^^ ^ */ inline void setKernelParameters(std::vector const ¶ms) { if (this->isSpatiallyVarying()) {
    414 068759b9 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    414 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Kernel is spatially varying"); } const unsigned int nParams = this->getNKernelParameters(); if (nParams != params.size()) {
    419 74a931c5 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    419 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Number of parameters is wrong, saw %d expected %d") % nParams % params.size()).str()); } for (unsigned int ii = 0; ii < nParams; ++ii) { this->setKernelParameter(ii, params[ii]); } } /** * @brief Set the kernel parameters of a 2-component spatially invariant kernel. * * @warning This is a low-level method intended for maximum efficiency when using warping kernels. * No error checking is performed. Use the std::vector form if you want safety. */ inline void setKernelParameters(std::pair const& params) { this->setKernelParameter(0, params.first); this->setKernelParameter(1, params.second); } /** * @brief Set the parameters of all spatial functions * * Params is indexed as [kernel parameter][spatial parameter] *
    444 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if params is the wrong shape
    ? ^^^^^^ ^
    444 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if params is the wrong shape
    ? ^^ ^ * (if this exception is thrown then no parameters are changed) */ void setSpatialParameters(const std::vector > params); /** * @brief Compute the kernel parameters at a specified point * * Warning: this is a low-level function that assumes kernelParams is the right length. * It will fail in unpredictable ways if that condition is not met. */ void computeKernelParametersFromSpatialModel( std::vector &kernelParams, double x, double y) const; /** * @brief Return a string representation of the kernel */ virtual std::string toString(std::string const& prefix="") const; /** * @brief Compute a cache of Kernel values, if desired * * @warning: few kernel classes actually support this, * in which case this is a no-op and getCacheSize always returns 0. */ virtual void computeCache( int const ///< desired cache size ) {} /** * @brief Get the current size of the kernel cache (0 if none or if caches not supported) */ virtual int getCacheSize() const { return 0; }; #if 0 // fails to compile with icc; is it actually used? virtual void toFile(std::string fileName) const; #endif struct PersistenceHelper; protected: virtual std::string getPythonModule() const; /** * @brief Set one kernel parameter * * Classes that have kernel parameters must subclass this function. * * This function is marked "const", despite modifying unimportant internals, * so that computeImage can be const. *
    496 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException always (unless subclassed)
    ? ^^^^^^ ^
    496 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError always (unless subclassed)
    ? ^^ ^ */ virtual void setKernelParameter(unsigned int ind, double value) const; /** * @brief Set the kernel parameters from the spatial model (if any). * * This function has no effect if there is no spatial model. * * This function is marked "const", despite modifying unimportant internals, * so that computeImage can be const. */ void setKernelParametersFromSpatialModel(double x, double y) const; /** * @brief Low-level version of computeImage * * Before this is called the image dimensions are checked, the image's xy0 is set * and the kernel's parameters are set. * This routine sets the pixels, including normalization if requested. * * @return The kernel sum */ virtual double doComputeImage( lsst::afw::image::Image &image, ///< image whose pixels are to be set (output) bool doNormalize ///< normalize the image (so sum is 1)? ) const = 0; std::vector _spatialFunctionList; private: LSST_PERSIST_FORMATTER(lsst::afw::formatters::KernelFormatter) int _width; int _height; int _ctrX; int _ctrY; unsigned int _nKernelParams; // prevent copying and assignment (to avoid problems from type slicing) Kernel(const Kernel&); Kernel& operator=(const Kernel&); // Set the Kernel's ideas about the x- and y- coordinates virtual void _setKernelXY() {} }; typedef std::vector KernelList; /** * @brief A kernel created from an Image * * It has no adjustable parameters and so cannot be spatially varying. * * @ingroup afw */ class FixedKernel : public afw::table::io::PersistableFacade, public Kernel { public: typedef PTR(FixedKernel) Ptr; typedef CONST_PTR(FixedKernel) ConstPtr; /** * @brief Construct an empty FixedKernel of size 0x0 */ explicit FixedKernel(); /** * @brief Construct a FixedKernel from an image */ explicit FixedKernel( lsst::afw::image::Image const &image ///< image for kernel ); /** * @brief Construct a FixedKernel from a generic Kernel */ explicit FixedKernel( lsst::afw::math::Kernel const& kernel, ///< Kernel to convert to Fixed lsst::afw::geom::Point2D const& pos ///< desired position ); virtual ~FixedKernel() {} virtual PTR(Kernel) clone() const; virtual std::string toString(std::string const& prefix = "") const; virtual Pixel getSum() const { return _sum; } virtual bool isPersistable() const { return true; } class Factory; protected: double doComputeImage( lsst::afw::image::Image &image, bool doNormalize ) const; virtual std::string getPersistenceName() const; virtual void write(OutputArchiveHandle & handle) const; private: lsst::afw::image::Image _image; Pixel _sum; friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("k", boost::serialization::base_object(*this)); ar & make_nvp("img", _image); ar & make_nvp("sum", _sum); } }; /** * @brief A kernel described by a function. * * The function's x, y arguments are as follows: * * -getCtr() for the lower left corner pixel * * 0, 0 for the center pixel * * (getDimensions() - 1) - getCtr() for the upper right pixel * * Note: each pixel is set to the value of the kernel function at the center of the pixel * (rather than averaging the function over the area of the pixel). * * @ingroup afw */ class AnalyticKernel : public afw::table::io::PersistableFacade, public Kernel { public: typedef PTR(AnalyticKernel) Ptr; typedef CONST_PTR(AnalyticKernel) ConstPtr; typedef lsst::afw::math::Function2 KernelFunction; typedef PTR(lsst::afw::math::Function2) KernelFunctionPtr; /** * @brief Construct an empty spatially invariant AnalyticKernel of size 0x0 */ explicit AnalyticKernel(); /** * @brief Construct a spatially invariant AnalyticKernel, * or a spatially varying AnalyticKernel where the spatial model * is described by one function (that is cloned to give one per analytic function parameter). */ explicit AnalyticKernel( int width, ///< width of kernel int height, ///< height of kernel KernelFunction const &kernelFunction, ///< kernel function; a deep copy is made Kernel::SpatialFunction const &spatialFunction=NullSpatialFunction() ///< spatial function; ///< one deep copy is made for each kernel function parameter; ///< if omitted or set to Kernel::NullSpatialFunction() then the kernel is spatially invariant ); /** * @brief Construct a spatially varying AnalyticKernel, where the spatial model * is described by a list of functions (one per analytic function parameter). *
    658 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    658 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * if the length of spatialFunctionList != # kernel function parameters. */ explicit AnalyticKernel( int width, ///< width of kernel int height, ///< height of kernel KernelFunction const &kernelFunction, ///< kernel function; a deep copy is made std::vector const &spatialFunctionList ///< list of spatial functions, ///< one per kernel function parameter; a deep copy is made of each function ); virtual ~AnalyticKernel() {} virtual PTR(Kernel) clone() const; /** * @brief Compute an image (pixellized representation of the kernel) in place * * This special version accepts any size image (though you can get in trouble * if the image is large enough that the image is evaluated outside its domain). * * x, y are ignored if there is no spatial function. * * @return The kernel sum * * @note computeNewImage has been retired; it doesn't need to be a member *
    686 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if the image is the wrong size
    ? ^^^^^^ ^
    686 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the image is the wrong size
    ? ^^ ^
    687 92570c02 - * @throw lsst::pex::exceptions::OverflowErrorException if doNormalize is true and the kernel sum is
    ? ---------
    687 21597d88 + * @throw lsst::pex::exceptions::OverflowError if doNormalize is true and the kernel sum is
    * exactly 0 */ double computeImage( lsst::afw::image::Image &image, ///< image whose pixels are to be set (output) ///< xy0 of the image will be set to -kernel.getCtr() - border, ///< where border = (image.getDimensions() - kernel.getDimensions()) / 2 bool doNormalize, ///< normalize the image (so sum is 1)? double x = 0.0, ///< x (column position) at which to compute spatial function double y = 0.0 ///< y (row position) at which to compute spatial function ) const; virtual std::vector getKernelParameters() const; /** * @brief Get a deep copy of the kernel function */ virtual KernelFunctionPtr getKernelFunction() const; virtual std::string toString(std::string const& prefix="") const; virtual bool isPersistable() const { return true; } class Factory; protected: virtual double doComputeImage( lsst::afw::image::Image &image, bool doNormalize ) const; virtual std::string getPersistenceName() const; virtual void write(OutputArchiveHandle & handle) const; protected: virtual void setKernelParameter(unsigned int ind, double value) const; KernelFunctionPtr _kernelFunctionPtr; friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("k", boost::serialization::base_object(*this)); ar & make_nvp("fn", _kernelFunctionPtr); } }; /** * @brief A kernel that has only one non-zero pixel (of value 1) * * It has no adjustable parameters and so cannot be spatially varying. * * @ingroup afw */ class DeltaFunctionKernel : public afw::table::io::PersistableFacade, public Kernel { public: typedef PTR(DeltaFunctionKernel) Ptr; typedef CONST_PTR(DeltaFunctionKernel) ConstPtr; // Traits values for this class of Kernel typedef deltafunction_kernel_tag kernel_fill_factor; /** * @brief Construct a spatially invariant DeltaFunctionKernel *
    756 92570c02 - * @throw pexExcept::InvalidParameterException if active pixel is off the kernel
    ? ^^^^^^ ^
    756 21597d88 + * @throw pexExcept::InvalidParameterError if active pixel is off the kernel
    ? ^^ ^ */ explicit DeltaFunctionKernel( int width, ///< kernel size (columns) int height, ///< kernel size (rows) lsst::afw::geom::Point2I const &point ///< index of active pixel (where 0,0 is the lower left corner) ); virtual ~DeltaFunctionKernel() {} virtual PTR(Kernel) clone() const; lsst::afw::geom::Point2I getPixel() const { return _pixel; } virtual std::string toString(std::string const& prefix="") const; virtual bool isPersistable() const { return true; } class Factory; protected: virtual double doComputeImage( lsst::afw::image::Image &image, bool doNormalize ) const; virtual std::string getPersistenceName() const; virtual void write(OutputArchiveHandle & handle) const; private: lsst::afw::geom::Point2I _pixel; friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { boost::serialization::void_cast_register< DeltaFunctionKernel, Kernel>( static_cast(0), static_cast(0)); } }; /** * @brief A kernel that is a linear combination of fixed basis kernels. * * Convolution may be performed by first convolving the image * with each fixed kernel, then adding the resulting images using the (possibly * spatially varying) kernel coefficients. * * The basis kernels are cloned (deep copied) so you may safely modify your own copies. * * Warnings: * - This class does not normalize the individual basis kernels; they are used "as is". * * @ingroup afw */ class LinearCombinationKernel : public afw::table::io::PersistableFacade, public Kernel { public: typedef PTR(LinearCombinationKernel) Ptr; typedef CONST_PTR(LinearCombinationKernel) ConstPtr; /** * @brief Construct an empty LinearCombinationKernel of size 0x0 */ explicit LinearCombinationKernel(); /** * @brief Construct a spatially invariant LinearCombinationKernel */ explicit LinearCombinationKernel( KernelList const &kernelList, ///< list of (shared pointers to const) basis kernels std::vector const &kernelParameters ///< kernel coefficients ); /** * @brief Construct a spatially varying LinearCombinationKernel, where the spatial model * is described by one function (that is cloned to give one per basis kernel). */ explicit LinearCombinationKernel( KernelList const &kernelList, ///< list of (shared pointers to const) basis kernels Kernel::SpatialFunction const &spatialFunction ///< spatial function; ///< one deep copy is made for each basis kernel ); /** * @brief Construct a spatially varying LinearCombinationKernel, where the spatial model * is described by a list of functions (one per basis kernel). *
    848 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if the length of spatialFunctionList != # kernels
    ? ^^^^^^ ^
    848 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the length of spatialFunctionList != # kernels
    ? ^^ ^ */ explicit LinearCombinationKernel( KernelList const &kernelList, ///< list of (shared pointers to const) kernels std::vector const &spatialFunctionList ///< list of spatial functions, one per basis kernel ); virtual ~LinearCombinationKernel() {} virtual PTR(Kernel) clone() const; virtual std::vector getKernelParameters() const; /** * @brief Get the fixed basis kernels */ virtual KernelList const &getKernelList() const; /** * @brief Get the sum of the pixels of each fixed basis kernel */ std::vector getKernelSumList() const; /** * @brief Get the number of basis kernels */ int getNBasisKernels() const { return static_cast(_kernelList.size()); }; /** * @brief Check that all kernels have the same size and center and that none are spatially varying *
    880 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if the check fails
    ? ^^^^^^ ^
    880 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if the check fails
    ? ^^ ^ */ void checkKernelList(const KernelList &kernelList) const; /** * Return true if all basis kernels are instances of DeltaFunctionKernel */ bool isDeltaFunctionBasis() const { return _isDeltaFunctionBasis; }; /** * @brief Refactor the kernel as a linear combination of N bases where N is the number of parameters * for the spatial model. * * Refactoring is only possible if all of the following are true: * * Kernel is spatially varying * * The spatial functions are a linear combination of coefficients (return isLinearCombination() true). * * The spatial functions all are the same class (and so have the same functional form) * Refactoring produces a kernel that is faster to compute only if the number of basis kernels * is greater than the number of parameters in the spatial model. * * Details: * A spatially varying LinearCombinationKernel consisting of M basis kernels * and using a spatial model that is a linear combination of N coefficients can be expressed as: * K(x,y) = K0 (C00 F0(x,y) + C10 F1(x,y) + C20 F2(x,y) + ... + CN0 FN(x,y)) * + K1 (C01 F0(x,y) + C11 F1(x,y) + C21 F2(x,y) + ... + CN1 FN(x,y)) * + K2 (C02 F0(x,y) + C12 F1(x,y) + C22 F2(x,y) + ... + CN2 FN(x,y)) * + ... * + KM (C0M F0(x,y) + C1M F1(x,y) + C2M F2(x,y) + ... + CNM FN(x,y)) * * This is equivalent to the following linear combination of N basis kernels: * * = K0' F0(x,y) + K1' F1(x,y) + K2' F2(x,y) + ... + KN' FN(x,y) * * where Ki' = sum over j of Kj Cij * * This is what refactor returns provided the required conditions are met. However, the spatial functions * for the refactored kernel are the same as those for the original kernel (for generality and simplicity) * with all coefficients equal to 0 except one that is set to 1; hence they are not computed optimally. * * Thanks to Kresimir Cosic for inventing or reinventing this useful technique. * * @return a shared pointer to new kernel, or empty pointer if refactoring not possible */ PTR(Kernel) refactor() const; virtual std::string toString(std::string const& prefix="") const; virtual bool isPersistable() const { return true; } class Factory; protected: virtual double doComputeImage( lsst::afw::image::Image &image, bool doNormalize ) const; virtual std::string getPersistenceName() const; virtual void write(OutputArchiveHandle & handle) const; virtual void setKernelParameter(unsigned int ind, double value) const; private: /** * @brief Set _kernelList by cloning each input kernel and update the kernel image cache. */ void _setKernelList(KernelList const &kernelList); KernelList _kernelList; ///< basis kernels std::vector)> _kernelImagePtrList; ///< image of each basis kernel (a cache) std::vector _kernelSumList; ///< sum of each basis kernel (a cache) mutable std::vector _kernelParams; bool _isDeltaFunctionBasis; friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("k", boost::serialization::base_object(*this)); ar & make_nvp("klist", _kernelList); ar & make_nvp("kimglist", _kernelImagePtrList); ar & make_nvp("ksumlist", _kernelSumList); ar & make_nvp("params", _kernelParams); if (version > 0) { ar & make_nvp("deltaBasis", _isDeltaFunctionBasis); } else if (Archive::is_loading::value) { _isDeltaFunctionBasis = false; } } }; /** * @brief A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y) * * The function's x, y arguments are as follows: * * -getCtr() for the lower left corner pixel * * 0, 0 for the center pixel * * (getDimensions() - 1) - getCtr() for the upper right pixel * * Note: each pixel is set to the value of the kernel function at the center of the pixel * (rather than averaging the function over the area of the pixel). * * @ingroup afw */ class SeparableKernel : public afw::table::io::PersistableFacade, public Kernel { public: typedef PTR(SeparableKernel) Ptr; typedef CONST_PTR(SeparableKernel) ConstPtr; typedef lsst::afw::math::Function1 KernelFunction; typedef PTR(KernelFunction) KernelFunctionPtr; /** * @brief Construct an empty spatially invariant SeparableKernel of size 0x0 */ explicit SeparableKernel(); /** * @brief Construct a spatially invariant SeparableKernel, or a spatially varying SeparableKernel * that uses the same functional form to model each function parameter. */ explicit SeparableKernel( int width, ///< width of kernel int height, ///< height of kernel KernelFunction const& kernelColFunction, ///< kernel column function KernelFunction const& kernelRowFunction, ///< kernel row function Kernel::SpatialFunction const& spatialFunction=NullSpatialFunction() ///< spatial function; ///< one deep copy is made for each kernel column and row function parameter; ///< if omitted or set to Kernel::NullSpatialFunction then the kernel is spatially invariant ); /** * @brief Construct a spatially varying SeparableKernel *
    1015 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException
    ? ^^^^^^ ^
    1015 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError
    ? ^^ ^ * if the length of spatialFunctionList != # kernel function parameters. */ explicit SeparableKernel( int width, ///< width of kernel int height, ///< height of kernel KernelFunction const& kernelColFunction, ///< kernel column function KernelFunction const& kernelRowFunction, ///< kernel row function std::vector const& spatialFunctionList ///< list of spatial funcs, ///< one per kernel column and row function parameter; a deep copy is made of each function ); virtual ~SeparableKernel() {} virtual PTR(Kernel) clone() const; /** * @brief Compute the column and row arrays in place, where kernel(col, row) = colList(col) * rowList(row) * * x, y are ignored if there is no spatial function. * * @return the kernel sum (1.0 if doNormalize true) *
    1037 92570c02 - * @throw lsst::pex::exceptions::InvalidParameterException if colList or rowList is the wrong size
    ? ^^^^^^ ^
    1037 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if colList or rowList is the wrong size
    ? ^^ ^
    1038 92570c02 - * @throw lsst::pex::exceptions::OverflowErrorException if doNormalize is true and the kernel sum is
    ? ---------
    1038 21597d88 + * @throw lsst::pex::exceptions::OverflowError if doNormalize is true and the kernel sum is
    * exactly 0 */ double computeVectors( std::vector &colList, ///< column vector std::vector &rowList, ///< row vector bool doNormalize, ///< normalize the image (so sum of each is 1)? double x = 0.0, ///< x (column position) at which to compute spatial function double y = 0.0 ///< y (row position) at which to compute spatial function ) const; virtual double getKernelParameter(unsigned int i) const { unsigned int const ncol = _kernelColFunctionPtr->getNParameters(); if (i < ncol) { return _kernelColFunctionPtr->getParameter(i); } else { i -= ncol; return _kernelRowFunctionPtr->getParameter(i); } } virtual std::vector getKernelParameters() const; /** * @brief Get a deep copy of the col kernel function */ KernelFunctionPtr getKernelColFunction() const; /** * @brief Get a deep copy of the row kernel function */ KernelFunctionPtr getKernelRowFunction() const; virtual std::string toString(std::string const& prefix="") const; /*** * @brief Compute a cache of values for the x and y kernel functions * * A value of 0 disables the cache for maximum accuracy. * 10,000 typically results in a warping error of a fraction of a count. * 100,000 typically results in a warping error of less than 0.01 count. */ virtual void computeCache( int const cacheSize ///< cache size (number of double precision array elements in the x and y caches) ); /** * @brief Get the current cache size (0 if none) */ virtual int getCacheSize() const; protected: virtual double doComputeImage( lsst::afw::image::Image &image, bool doNormalize ) const; virtual void setKernelParameter(unsigned int ind, double value) const; private: /** * @brief Compute the column and row arrays in place, where kernel(col, row) = colList(col) * rowList(row) * * @return the kernel sum (1.0 if doNormalize true) * * Warning: the length of colList and rowList are not verified! *
    1104 92570c02 - * @throw lsst::pex::exceptions::OverflowErrorException if doNormalize is true and the kernel sum is
    ? ---------
    1104 21597d88 + * @throw lsst::pex::exceptions::OverflowError if doNormalize is true and the kernel sum is
    * exactly 0 */ double basicComputeVectors( std::vector &colList, ///< column vector std::vector &rowList, ///< row vector bool doNormalize ///< normalize the arrays (so sum of each is 1)? ) const; KernelFunctionPtr _kernelColFunctionPtr; KernelFunctionPtr _kernelRowFunctionPtr; mutable std::vector _localColList; // used by doComputeImage mutable std::vector _localRowList; mutable std::vector _kernelX; // used by SeparableKernel::basicComputeVectors mutable std::vector _kernelY; // // Cached values of the row- and column- kernels // mutable std::vector > _kernelRowCache; mutable std::vector > _kernelColCache; friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("k", boost::serialization::base_object(*this)); ar & make_nvp("colfn", _kernelColFunctionPtr); ar & make_nvp("rowfn", _kernelRowFunctionPtr); ar & make_nvp("cols", _localColList); ar & make_nvp("rows", _localRowList); ar & make_nvp("kernelX", _kernelX); ar & make_nvp("kernelY", _kernelY); } virtual void _setKernelXY() { lsst::afw::geom::Extent2I const dim = getDimensions(); lsst::afw::geom::Point2I const ctr = getCtr(); assert (dim[0] == static_cast(_kernelX.size())); for (int i = 0; i != dim.getX(); ++i) { _kernelX[i] = i - ctr.getX(); } assert (dim[1] == static_cast(_kernelY.size())); for (int i = 0; i != dim.getY(); ++i) { _kernelY[i] = i - ctr.getY(); } } }; }}} // lsst:afw::math namespace boost { namespace serialization { template inline void save_construct_data( Archive& ar, lsst::afw::math::DeltaFunctionKernel const* k, unsigned int const file_version) { int width = k->getWidth(); int height = k->getHeight(); int x = k->getPixel().getX(); int y = k->getPixel().getY(); ar << make_nvp("width", width); ar << make_nvp("height", height); ar << make_nvp("pixX", x); ar << make_nvp("pixY", y); } template inline void load_construct_data( Archive& ar, lsst::afw::math::DeltaFunctionKernel* k, unsigned int const file_version) { int width; int height; int x; int y; ar >> make_nvp("width", width); ar >> make_nvp("height", height); ar >> make_nvp("pixX", x); ar >> make_nvp("pixY", y); ::new(k) lsst::afw::math::DeltaFunctionKernel( width, height, lsst::afw::geom::Point2I(x, y)); } }} #ifndef SWIG BOOST_CLASS_VERSION(lsst::afw::math::LinearCombinationKernel, 1) #endif #endif // !defined(LSST_AFW_MATH_KERNEL_H)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b79a02a2

    commit b79a02a2c6c1b70fadfb74623e481172a3376579
    Author: rowen 
    Date:   Mon Nov 23 21:16:07 2009 +0000
    
        Implemented ticket #992:
        - Kernel.computeImage now raises lsst::pex::except::InvalidParameterException
          if doNormalize true and kernel sum 0.
        - SeparableKernel.computeVectors and basicComputeVectors do the same.
        - Added unit tests for the above.
        - Fixed typos in tests/Statistics.py so all tests pass again.
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    74a931c5

    commit 74a931c5ef449f522f077892ca26d8db355bb811
    Author: rhl 
    Date:   Tue Mar 3 19:40:48 2009 +0000
    
        Added offsetImage
    

    92570c02

    commit 92570c02a059d1547b68e84d8a7326f68938b71b
    Author: Russell Owen 
    Date:   Tue May 7 10:23:10 2013 -0700
    
        Implement ticket #2620: computeImage should set xy0.
        Removed the ability to pass a smaller image to LinearCombinationKernel::computeImage.
        AnalyticKernel::computeImage can still be called with an image of any dimensions,
        but only on that class; if you try to do this on a pointer or reference to Kernel
        then Kernel::computeImage is called,which rejects images whose dimensions do not match that of Kernel
        (Jim Bosch and I consider this a feature).
        Added a unit test to tests/kernel.py that exercises the dimension checking code.
        Moved some boilerplate code for computeImage into a protected member function doComputeImage
        and made Kernel::computeImage nonvirtual.
    

    068759b9

    commit 068759b9de5ac7caee50d816e7ff6d2c468b4867
    Author: rowen 
    Date:   Mon Sep 28 21:26:58 2009 +0000
    
        Changed Kernel's PixelT to Pixel and PtrT to Ptr
        Added Kernel::ConstPtr
        Renamed KernelList specializations to remove final D (except KernelList itself,
        alas, because I could not make that work).
        Renamed some math .i files to the proper convention.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/math/detail/cudaConvWrapper.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * @file
                     *
                     * @brief Set up for convolution, calls GPU convolution kernels
                     *
                     * Functions in this file are used to allocate necessary buffers,
                     * transfer data from and to GPU memory, and to set up and perform convolution.
                     *
                     * @author Kresimir Cosic
                     *
                     * @ingroup afw
                     */
                    
                    #ifndef GPU_BUILD
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    namespace detail {
                    
                    
                    void TestGpuKernel(int& ret1, int& ret2) {
                        ret1 = 0;
                        ret2 = 0;
                    }
                    
                    bool IsSufficientSharedMemoryAvailable_ForImgBlock(int filterW, int filterH, int pixSize)
                    {
                        return false;
                    }
                    bool IsSufficientSharedMemoryAvailable_ForImgAndMaskBlock(int filterW, int filterH, int pixSize)
                    {
                        return false;
                    }
                    bool IsSufficientSharedMemoryAvailable_ForSfn(int order, int kernelN)
                    {
                        return false;
                    }
                    
                    }
                    }
                    }
                    }
                    
                    #else
                    
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/afw/image/LsstImageTypes.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/FunctionLibrary.h"
                    
                    #include "lsst/afw/gpu/detail/GpuBuffer2D.h"
                    #include "lsst/afw/math/detail/convCUDA.h"
                    #include "lsst/afw/math/detail/cudaConvWrapper.h"
                    #include "lsst/afw/gpu/detail/CudaQueryDevice.h"
                    #include "lsst/afw/math/detail/Convolve.h"
                    #include "lsst/afw/gpu/detail/CudaSelectGpu.h"
                    #include "lsst/afw/gpu/detail/CudaMemory.h"
                    
                    using namespace std;
                    using namespace lsst::afw::gpu;
                    using namespace lsst::afw::gpu::detail;
                    namespace afwImage = lsst::afw::image;
                    namespace afwMath = lsst::afw::math;
                    namespace mathDetailGpu = lsst::afw::math::detail::gpu;
                    
                    
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    namespace detail {
                    
                    namespace {
                    const int shMemBytesUsed = 200;
                    }
                    
                    
                    // Returns true if there is sufficient shared memory for loading an image block,
                    // where image block includes including filter frame.
                    bool IsSufficientSharedMemoryAvailable_ForImgBlock(int filterW, int filterH, int pixSize)
                    {
                        int shMemSize = GetCudaCurSMSharedMemorySize();
                        int bufferSize = (filterW + blockSizeX - 1) * (filterH + blockSizeY - 1) * pixSize;
                    
                        return shMemSize - shMemBytesUsed - bufferSize > 0;
                    }
                    
                    // Returns true if there is sufficient shared memory for loading an image block,
                    // and acommpanying block of mask data (mask image block),
                    // where image block and mask image block include including filter frame.
                    bool IsSufficientSharedMemoryAvailable_ForImgAndMaskBlock(int filterW, int filterH, int pixSize)
                    {
                        int shMemSize = GetCudaCurSMSharedMemorySize();
                        int imgBufferSize = (filterW + blockSizeX - 1) * (filterH + blockSizeY - 1) * pixSize;
                        int mskBufferSize = (filterW + blockSizeX - 1) * (filterH + blockSizeY - 1) * sizeof(MskPixel);
                    
                        int memRemaining = shMemSize - shMemBytesUsed - imgBufferSize - mskBufferSize ;
                    
                        return memRemaining > 0;
                    }
                    
                    // Returns true if there is sufficient shared memory for loading
                    // parameters and temporary values for Chebyshev function and normalization
                    bool IsSufficientSharedMemoryAvailable_ForSfn(int order, int kernelN)
                    {
                        int shMemSize = GetCudaCurSMSharedMemorySize();
                    
                        const int coeffN = order + 1;
                        const int coeffPadding = coeffN + 1 - (coeffN % 2);
                        int paramN = (order + 1) * (order + 2) / 2;
                    
                        int yCoeffsAll = coeffPadding * blockSizeX * sizeof(double);
                        int xChebyAll = coeffPadding * blockSizeX * sizeof(double);
                        int smemParams = paramN * sizeof(double);
                    
                        int  smemKernelSum = kernelN * sizeof(double);
                        int  smemSfnPtr   = kernelN * sizeof(double*);
                    
                        int memRemainingSfn = shMemSize - shMemBytesUsed - yCoeffsAll - xChebyAll - smemParams ;
                        int memRemainingNorm = shMemSize - shMemBytesUsed - smemKernelSum - smemSfnPtr;
                    
                        return min(memRemainingSfn, memRemainingNorm) > 0;
                    }
                    
                    // This function decides on the best GPU block count
                    // uses simple heuristics (not to much blocks and not too many)
                    // but guarantees that number of blocks will be a multiple of number of multiprocessors
                    int CalcBlockCount(int multiprocCount)
                    {
                        if (multiprocCount < 12)  return multiprocCount * 4;
                        if (multiprocCount < 24)  return multiprocCount * 2;
                        return multiprocCount;
                    }
                    
                    
                    // calls test gpu kernel
                    // should return 5 and 8 in ret1 and ret2
                    void TestGpuKernel(int& ret1, int& ret2)
                    {
                        int res[2];
                    
                        GpuMemOwner resGpu;
                        resGpu.Alloc(2);
                    
                        gpu::CallTestGpuKernel(resGpu.ptr);
                    
                        resGpu.CopyFromGpu(res);
                    
                        ret1 = res[0];
                        ret2 = res[1];
                    }
                    
                    namespace {
                    
                    //calculates sum of each image in 'images' vector
                    template 
                    vector SumsOfImages(const vector< GpuBuffer2D >&  images)
                    {
                        int n = int(images.size());
                        vector sum(n);
                        for (int i = 0; i < n; i++) {
                            ResultT totalSum = 0;
                            int h = images[i].height;
                            int w = images[i].width;
                    
                            for (int y = 0; y < h; y++) {
                                ResultT rowSum = 0;
                                for (int x = 0; x < w; x++) {
                                    rowSum += images[i].Pixel(x, y);
                                }
                                totalSum += rowSum;
                            }
                            sum[i] = totalSum;
                        }
                        return sum;
                    }
                    
                    /**
                        Convolves given inImage with linear combination kernel.
                    
                        Calculates:
                            - the sFn (spatial function) values, output in sFnValGPUPtr and sFnValGPU
                            - if doNormalize is true, will also compute normalization coefficients.
                                Normalization coefficients will be placed in normGPU buffer.
                            - the result of convolution with LinearCombination kernel (given
                                by sFn) in out image
                            - sFnValGPUPtr and normGPU reside in GPU memory
                    
                        Basis kernels, given by basisKernelsListGPU, must have been transfered to GPU memory previously.
                        Other GPU output data parameters (sFnValGPUPtr, sFnValGPU, normGPU) must be already allocated.
                    */
                    template 
                    void GPU_ConvolutionImage_LC_Img(
                        const GpuBuffer2D& inImage,
                        const vector& colPos,
                        const vector& rowPos,
                        const std::vector< afwMath::Kernel::SpatialFunctionPtr >& sFn,
                        const vector& sFnValGPUPtr, //output
                        double** sFnValGPU,    //output
                        SpatialFunctionType_t sfType,
                        GpuBuffer2D&  outImage, //output
                        KerPixel*   basisKernelsListGPU,
                        int kernelW, int kernelH,
                        const vector&   basisKernelSums,   //input
                        double* normGPU,   //output
                        bool doNormalize
                    )
                    {
                        const int kernelN = sFn.size();
                    
                        //transfer input image
                        GpuMemOwner inImageGPU;
                        inImageGPU.Transfer(inImage);
                        if (inImageGPU.ptr == NULL)  {
    
    243 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for input image");
    ? ^^^^^^ ^
    243 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for input image");
    ? ^^ ^ } // allocate output image planes on GPU GpuMemOwner outImageGPU; outImageGPU.Alloc( outImage.Size()); if (outImageGPU.ptr == NULL) {
    249 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for output image");
    ? ^^^^^^ ^
    249 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for output image");
    ? ^^ ^ } //transfer coordinate tranform data GpuMemOwner colPosGPU_Owner; colPosGPU_Owner.TransferVec(colPos); if (colPosGPU_Owner.ptr == NULL) {
    255 96dee205 - throw LSST_EXCEPT(GpuMemoryException,
    ? ^^^^^^ ^
    255 21597d88 + throw LSST_EXCEPT(GpuMemoryError,
    ? ^^ ^ "Not enough memory on GPU for row coordinate tranformation data"); } GpuMemOwner rowPosGPU_Owner; rowPosGPU_Owner.TransferVec(rowPos); if (rowPosGPU_Owner.ptr == NULL) {
    261 96dee205 - throw LSST_EXCEPT(GpuMemoryException,
    ? ^^^^^^ ^
    261 21597d88 + throw LSST_EXCEPT(GpuMemoryError,
    ? ^^ ^ "Not enough memory on GPU for column coordinate tranformation data"); } vector< double* > sFnParamsGPUPtr(kernelN); vector< GpuMemOwner > sFnParamsGPU_Owner(kernelN); //transfer sfn parameters to GPU for (int i = 0; i < kernelN; i++) { std::vector spatialParams = sFn[i]->getParameters(); sFnParamsGPUPtr[i] = sFnParamsGPU_Owner[i].TransferVec(spatialParams); if (sFnParamsGPUPtr[i] == NULL) {
    272 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for spatial function parameters");
    ? ^^^^^^ ^
    272 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for spatial function parameters");
    ? ^^ ^ } } int shMemSize = GetCudaCurSMSharedMemorySize() - shMemBytesUsed; for (int i = 0; i < kernelN; i++) { cudaGetLastError(); //clear error status if (sfType == sftPolynomial) { const afwMath::PolynomialFunction2* polySfn = dynamic_cast*>( sFn[i].get() ); gpu::Call_PolynomialImageValues( sFnValGPUPtr[i], outImage.width, outImage.height, polySfn->getOrder(), sFnParamsGPU_Owner[i].ptr, rowPosGPU_Owner.ptr, colPosGPU_Owner.ptr, shMemSize ); //cudaThreadSynchronize(); cudaError_t cuda_err = cudaGetLastError(); if (cuda_err != cudaSuccess) {
    298 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    298 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU calculation failed to run");
    } } if (sfType == sftChebyshev) { const afwMath::Chebyshev1Function2* chebSfn = dynamic_cast*>( sFn[i].get() ); lsst::afw::geom::Box2D const xyRange = chebSfn->getXYRange(); gpu::Call_ChebyshevImageValues( sFnValGPUPtr[i], outImage.width, outImage.height, chebSfn->getOrder(), sFnParamsGPU_Owner[i].ptr, rowPosGPU_Owner.ptr, colPosGPU_Owner.ptr, xyRange.getMinX(), xyRange.getMinY(), xyRange.getMaxX(), xyRange.getMaxY(), shMemSize ); //cudaThreadSynchronize(); cudaError_t cuda_err = cudaGetLastError(); if (cuda_err != cudaSuccess) {
    320 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    320 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU calculation failed to run");
    } } } cudaThreadSynchronize(); cudaError_t cuda_err = cudaGetLastError(); if (cuda_err != cudaSuccess) {
    327 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    327 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU calculation failed to run");
    } int blockN = CalcBlockCount( GetCudaCurSMCount()); //transfer basis kernel sums if (doNormalize) { GpuMemOwner basisKernelSumsGPU; basisKernelSumsGPU.TransferVec(basisKernelSums); bool isDivideByZero = false; GpuMemOwner isDivideByZeroGPU; isDivideByZeroGPU.Transfer(&isDivideByZero, 1); gpu::Call_NormalizationImageValues( normGPU, outImage.width, outImage.height, sFnValGPU, kernelN, basisKernelSumsGPU.ptr, isDivideByZeroGPU.ptr, blockN, shMemSize ); cudaThreadSynchronize(); if (cudaGetLastError() != cudaSuccess) {
    351 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    351 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU calculation failed to run");
    } CopyFromGpu(&isDivideByZero, isDivideByZeroGPU.ptr, 1); if (isDivideByZero) {
    355 76b599b9 - throw LSST_EXCEPT(pexExcept::OverflowErrorException, "Cannot normalize; kernel sum is 0");
    ? ---------
    355 21597d88 + throw LSST_EXCEPT(pexExcept::OverflowError, "Cannot normalize; kernel sum is 0");
    } } cudaGetLastError(); //clear error status mathDetailGpu::Call_ConvolutionKernel_LC_Img( inImageGPU.ptr, inImage.width, inImage.height, basisKernelsListGPU, kernelN, kernelW, kernelH, &sFnValGPU[0], normGPU, outImageGPU.ptr, blockN, shMemSize ); cudaThreadSynchronize(); if (cudaGetLastError() != cudaSuccess) {
    372 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    372 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU calculation failed to run");
    } CopyFromGpu(outImage.img, outImageGPU.ptr, outImage.Size() ); } } //local namespace ends template void GPU_ConvolutionImage_LinearCombinationKernel( GpuBuffer2D& inImage, vector colPos, vector rowPos, std::vector< afwMath::Kernel::SpatialFunctionPtr > sFn, GpuBuffer2D& outImage, std::vector< GpuBuffer2D >& basisKernels, SpatialFunctionType_t sfType, bool doNormalize ) { assert(basisKernels.size() == sFn.size()); int outWidth = outImage.width; int outHeight = outImage.height; const int kernelN = sFn.size(); const int kernelW = basisKernels[0].width; const int kernelH = basisKernels[0].height; const int kernelSize = kernelW * kernelH; for (int i = 0; i < kernelN; i++) { assert(kernelW == basisKernels[i].width); assert(kernelH == basisKernels[i].height); } // transfer array of basis kernels on GPU GpuMemOwner basisKernelsGPU; basisKernelsGPU.Alloc(kernelSize * kernelN); for (int i = 0; i < kernelN; i++) { KerPixel* kernelBeg = basisKernelsGPU.ptr + (kernelSize * i); CopyToGpu(kernelBeg, basisKernels[i].img, kernelSize ); } // allocate array of spatial function value images on GPU vector< double* > sFnValGPUPtr(kernelN); vector< GpuMemOwner > sFnValGPU_Owner(kernelN); for (int i = 0; i < kernelN; i++) { sFnValGPUPtr[i] = sFnValGPU_Owner[i].Alloc(outWidth * outHeight); if (sFnValGPUPtr[i] == NULL) {
    427 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for spatial function values");
    ? ^^^^^^ ^
    427 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for spatial function values");
    ? ^^ ^ } } GpuMemOwner sFnValGPU; sFnValGPU.TransferVec(sFnValGPUPtr); GpuMemOwner normGPU_Owner; vector basisKernelSums(kernelN); if (doNormalize) { //allocate normalization coeficients normGPU_Owner.Alloc(outWidth * outHeight); if (normGPU_Owner.ptr == NULL) {
    439 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for normalization coefficients");
    ? ^^^^^^ ^
    439 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for normalization coefficients");
    ? ^^ ^ } //calculate basis kernel sums basisKernelSums = SumsOfImages(basisKernels); } GPU_ConvolutionImage_LC_Img( inImage, colPos, rowPos, sFn, sFnValGPUPtr, //output sFnValGPU.ptr, //output sfType, outImage, //output basisKernelsGPU.ptr, kernelW, kernelH, basisKernelSums, //input normGPU_Owner.ptr, //output doNormalize ); } #define INSTANTIATE_GPU_ConvolutionImage_LinearCombinationKernel(OutPixelT,InPixelT) \ template void GPU_ConvolutionImage_LinearCombinationKernel( \ GpuBuffer2D& inImage, \ vector colPos, \ vector rowPos, \ std::vector< afwMath::Kernel::SpatialFunctionPtr > sFn, \ GpuBuffer2D& outImage, \ std::vector< GpuBuffer2D >& basisKernels, \ SpatialFunctionType_t sfType, \ bool doNormalize \ ); template void GPU_ConvolutionMI_LinearCombinationKernel( GpuBuffer2D& inImageImg, GpuBuffer2D& inImageVar, GpuBuffer2D& inImageMsk, vector colPos, vector rowPos, std::vector< afwMath::Kernel::SpatialFunctionPtr > sFn, GpuBuffer2D& outImageImg, GpuBuffer2D& outImageVar, GpuBuffer2D& outImageMsk, std::vector< GpuBuffer2D >& basisKernels, SpatialFunctionType_t sfType, bool doNormalize ) { assert(basisKernels.size() == sFn.size()); assert(outImageImg.width == outImageVar.width); assert(outImageImg.width == outImageMsk.width); assert(outImageImg.height == outImageVar.height); assert(outImageImg.height == outImageMsk.height); int outWidth = outImageImg.width; int outHeight = outImageImg.height; const int kernelN = sFn.size(); const int kernelW = basisKernels[0].width; const int kernelH = basisKernels[0].height; const int kernelSize = kernelW * kernelH; for (int i = 0; i < kernelN; i++) { assert(kernelW == basisKernels[i].width); assert(kernelH == basisKernels[i].height); } // transfer basis kernels to GPU GpuMemOwner basisKernelsGPU; basisKernelsGPU.Alloc(kernelSize * kernelN); for (int i = 0; i < kernelN; i++) { KerPixel* kernelBeg = basisKernelsGPU.ptr + (kernelSize * i); CopyToGpu(kernelBeg, basisKernels[i].img, kernelSize ); } //alloc sFn images on GPU vector< double* > sFnValGPUPtr(kernelN); vector< GpuMemOwner > sFnValGPU_Owner(kernelN); for (int i = 0; i < kernelN; i++) { sFnValGPUPtr[i] = sFnValGPU_Owner[i].Alloc(outWidth * outHeight); if (sFnValGPUPtr[i] == NULL) {
    529 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for spatial function values");
    ? ^^^^^^ ^
    529 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for spatial function values");
    ? ^^ ^ } } GpuMemOwner sFnValGPU; sFnValGPU.TransferVec(sFnValGPUPtr); //allocate normalization coeficients image on GPU GpuMemOwner normGPU_Owner; std::vector basisKernelSums(kernelN); if (doNormalize) { //allocate normalization coeficients normGPU_Owner.Alloc(outWidth * outHeight); if (normGPU_Owner.ptr == NULL) {
    542 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for normalization coefficients");
    ? ^^^^^^ ^
    542 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for normalization coefficients");
    ? ^^ ^ } //calculate basis kernel sums basisKernelSums = SumsOfImages(basisKernels); } GPU_ConvolutionImage_LC_Img( inImageImg, colPos, rowPos, sFn, sFnValGPUPtr, //output sFnValGPU.ptr, //output sfType, outImageImg, //output basisKernelsGPU.ptr, kernelW, kernelH, basisKernelSums, //input normGPU_Owner.ptr, //output doNormalize ); //transfer input image planes to GPU GpuMemOwner inImageGPUVar; inImageGPUVar.Transfer(inImageVar); if (inImageGPUVar.ptr == NULL) {
    567 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for input variance");
    ? ^^^^^^ ^
    567 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for input variance");
    ? ^^ ^ } GpuMemOwner inImageGPUMsk; inImageGPUMsk.Transfer(inImageMsk); if (inImageGPUMsk.ptr == NULL) {
    572 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for input mask");
    ? ^^^^^^ ^
    572 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for input mask");
    ? ^^ ^ } // allocate output image planes on GPU GpuMemOwner outImageGPUVar; outImageGPUVar.Alloc( outImageVar.Size()); if (outImageGPUVar.ptr == NULL) {
    579 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for output variance");
    ? ^^^^^^ ^
    579 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for output variance");
    ? ^^ ^ } GpuMemOwner outImageGPUMsk; outImageGPUMsk.Alloc( outImageMsk.Size()); if (outImageGPUMsk.ptr == NULL) {
    584 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for output mask");
    ? ^^^^^^ ^
    584 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for output mask");
    ? ^^ ^ } int shMemSize = GetCudaCurSMSharedMemorySize() - shMemBytesUsed; int blockN = CalcBlockCount( GetCudaCurSMCount()); cudaGetLastError(); //clear error status mathDetailGpu::Call_ConvolutionKernel_LC_Var( inImageGPUVar.ptr, inImageVar.width, inImageVar.height, inImageGPUMsk.ptr, basisKernelsGPU.ptr, kernelN, kernelW, kernelH, sFnValGPU.ptr, normGPU_Owner.ptr, outImageGPUVar.ptr, outImageGPUMsk.ptr, blockN, shMemSize ); cudaThreadSynchronize(); if (cudaGetLastError() != cudaSuccess)
    604 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    604 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU calculation failed to run");
    CopyFromGpu(outImageVar.img, outImageGPUVar.ptr, outImageVar.Size() ); CopyFromGpu(outImageMsk.img, outImageGPUMsk.ptr, outImageMsk.Size() ); } #define INSTANTIATE_GPU_ConvolutionMI_LinearCombinationKernel(OutPixelT,InPixelT) \ template void GPU_ConvolutionMI_LinearCombinationKernel( \ GpuBuffer2D& inImageImg, \ GpuBuffer2D& inImageVar, \ GpuBuffer2D& inImageMsk, \ vector colPos, \ vector rowPos, \ std::vector< afwMath::Kernel::SpatialFunctionPtr > sFn, \ GpuBuffer2D& outImageImg, \ GpuBuffer2D& outImageVar, \ GpuBuffer2D& outImageMsk, \ std::vector< GpuBuffer2D >& basisKernels, \ SpatialFunctionType_t sfType, \ bool doNormalize \ ); template void GPU_ConvolutionImage_SpatiallyInvariantKernel( GpuBuffer2D& inImage, GpuBuffer2D& outImage, GpuBuffer2D& kernel ) { int kernelW = kernel.width; int kernelH = kernel.height; GpuMemOwner inImageGPU; inImageGPU.Transfer(inImage); if (inImageGPU.ptr == NULL) {
    640 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU for input image");
    ? ^^^^^^ ^
    640 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU for input image");
    ? ^^ ^ } int shMemSize = GetCudaCurSMSharedMemorySize() - shMemBytesUsed; // allocate array of kernels on GPU GpuMemOwner basisKernelGPU; basisKernelGPU.Transfer(kernel); if (basisKernelGPU.ptr == NULL) {
    648 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for kernel");
    ? ^^^^^^ ^
    648 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for kernel");
    ? ^^ ^ } // allocate array of output images on GPU (one output image per kernel) vector< OutPixelT* > outImageGPUPtr(1); vector< GpuMemOwner > outImageGPU_Owner(1); outImageGPUPtr[0] = outImageGPU_Owner[0].Alloc( outImage.Size()); if (outImageGPUPtr[0] == NULL) {
    656 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for output image");
    ? ^^^^^^ ^
    656 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for output image");
    ? ^^ ^ } GpuMemOwner outImageGPU; outImageGPU.TransferVec(outImageGPUPtr); int blockN = CalcBlockCount( GetCudaCurSMCount()); cudaGetLastError(); //clear error status mathDetailGpu::Call_SpatiallyInvariantImageConvolutionKernel( inImageGPU.ptr, inImage.width, inImage.height, basisKernelGPU.ptr, 1, kernelW, kernelH, outImageGPU.ptr, blockN, shMemSize ); cudaThreadSynchronize(); if (cudaGetLastError() != cudaSuccess) {
    674 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU calculation failed to run");
    ? ---------
    674 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU calculation failed to run");
    } CopyFromGpu(outImage.img, outImageGPUPtr[0], outImage.Size() ); } #define INSTANTIATE_GPU_ConvolutionImage_SpatiallyInvariantKernel(OutPixelT,InPixelT) \ template void GPU_ConvolutionImage_SpatiallyInvariantKernel( \ GpuBuffer2D& inImage, \ GpuBuffer2D& outImage, \ GpuBuffer2D& kernel \ ); template void GPU_ConvolutionMI_SpatiallyInvariantKernel( GpuBuffer2D& inImageImg, GpuBuffer2D& inImageVar, GpuBuffer2D& inImageMsk, GpuBuffer2D& outImageImg, GpuBuffer2D& outImageVar, GpuBuffer2D& outImageMsk, GpuBuffer2D& kernel ) { int kernelW = kernel.width; int kernelH = kernel.height; GpuMemOwner inImageGPUImg; inImageGPUImg.Transfer(inImageImg); if (inImageGPUImg.ptr == NULL) {
    703 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for input image");
    ? ^^^^^^ ^
    703 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for input image");
    ? ^^ ^ } GpuMemOwner inImageGPUVar; inImageGPUVar.Transfer(inImageVar); if (inImageGPUVar.ptr == NULL) {
    708 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for input variance");
    ? ^^^^^^ ^
    708 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for input variance");
    ? ^^ ^ } GpuMemOwner inImageGPUMsk; inImageGPUMsk.Transfer(inImageMsk); if (inImageGPUMsk.ptr == NULL) {
    713 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for input mask");
    ? ^^^^^^ ^
    713 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for input mask");
    ? ^^ ^ } int shMemSize = GetCudaCurSMSharedMemorySize() - shMemBytesUsed; //allocate kernel on GPU GpuMemOwner basisKernelGPU; basisKernelGPU.Transfer(kernel); if (basisKernelGPU.ptr == NULL)
    721 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for kernel");
    ? ^^^^^^ ^
    721 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for kernel");
    ? ^^ ^ // allocate array of output image planes on GPU vector< OutPixelT* > outImageGPUPtrImg(1); vector< VarPixel* > outImageGPUPtrVar(1); vector< MskPixel* > outImageGPUPtrMsk(1); vector< GpuMemOwner > outImageGPU_OwnerImg(1); vector< GpuMemOwner > outImageGPU_OwnerVar(1); vector< GpuMemOwner > outImageGPU_OwnerMsk(1); outImageGPUPtrImg[0] = outImageGPU_OwnerImg[0].Alloc( outImageImg.Size()); if (outImageGPUPtrImg[0] == NULL) {
    734 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for output image");
    ? ^^^^^^ ^
    734 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for output image");
    ? ^^ ^ } outImageGPUPtrVar[0] = outImageGPU_OwnerVar[0].Alloc( outImageVar.Size()); if (outImageGPUPtrVar[0] == NULL) {
    738 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for output variance");
    ? ^^^^^^ ^
    738 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for output variance");
    ? ^^ ^ } outImageGPUPtrMsk[0] = outImageGPU_OwnerMsk[0].Alloc( outImageMsk.Size()); if (outImageGPUPtrMsk[0] == NULL) {
    742 96dee205 - throw LSST_EXCEPT(GpuMemoryException, "Not enough memory on GPU available for output mask");
    ? ^^^^^^ ^
    742 21597d88 + throw LSST_EXCEPT(GpuMemoryError, "Not enough memory on GPU available for output mask");
    ? ^^ ^ } GpuMemOwner outImageGPUImg; outImageGPUImg.TransferVec(outImageGPUPtrImg); GpuMemOwner outImageGPUVar; outImageGPUVar.TransferVec(outImageGPUPtrVar); GpuMemOwner outImageGPUMsk; outImageGPUMsk.TransferVec(outImageGPUPtrMsk); int blockN = CalcBlockCount( GetCudaCurSMCount()); mathDetailGpu::Call_SpatiallyInvariantImageConvolutionKernel( inImageGPUImg.ptr, inImageImg.width, inImageImg.height, basisKernelGPU.ptr, 1, kernelW, kernelH, outImageGPUImg.ptr, blockN, shMemSize ); //square kernel for (int y = 0; y < kernelH; y++) { for (int x = 0; x < kernelW; x++) { kernel.Pixel(x, y) *= kernel.Pixel(x, y); } } CopyFromGpu(outImageImg.img, outImageGPUPtrImg[0], outImageImg.Size() ); basisKernelGPU.CopyToGpu(kernel); cudaGetLastError(); //clear last error mathDetailGpu::Call_SpatiallyInvariantImageConvolutionKernel( inImageGPUVar.ptr, inImageVar.width, inImageVar.height, basisKernelGPU.ptr, 1, kernelW, kernelH, outImageGPUVar.ptr, blockN, shMemSize ); cudaThreadSynchronize(); if (cudaGetLastError() != cudaSuccess) {
    786 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU variance calculation failed to run");
    ? ---------
    786 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU variance calculation failed to run");
    } mathDetailGpu::Call_SpatiallyInvariantMaskConvolutionKernel( inImageGPUMsk.ptr, inImageMsk.width, inImageMsk.height, basisKernelGPU.ptr, 1, kernelW, kernelH, outImageGPUMsk.ptr, blockN, shMemSize ); cudaThreadSynchronize(); if (cudaGetLastError() != cudaSuccess) {
    798 96dee205 - throw LSST_EXCEPT(GpuRuntimeErrorException, "GPU mask calculation failed to run");
    ? ---------
    798 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "GPU mask calculation failed to run");
    } CopyFromGpu(outImageVar.img, outImageGPUPtrVar[0], outImageVar.Size() ); CopyFromGpu(outImageMsk.img, outImageGPUPtrMsk[0], outImageMsk.Size() ); } #define INSTANTIATE_GPU_ConvolutionMI_SpatiallyInvariantKernel(OutPixelT,InPixelT) \ template void GPU_ConvolutionMI_SpatiallyInvariantKernel( \ GpuBuffer2D& inImageImg, \ GpuBuffer2D& inImageVar, \ GpuBuffer2D& inImageMsk, \ GpuBuffer2D& outImageImg, \ GpuBuffer2D& outImageVar, \ GpuBuffer2D& outImageMsk, \ GpuBuffer2D& kernel \ ); /* * Explicit instantiation */ /// \cond #define INSTANTIATE(OutPixelT,InPixelT) \ INSTANTIATE_GPU_ConvolutionImage_LinearCombinationKernel(OutPixelT,InPixelT) \ INSTANTIATE_GPU_ConvolutionMI_LinearCombinationKernel(OutPixelT,InPixelT) \ INSTANTIATE_GPU_ConvolutionImage_SpatiallyInvariantKernel(OutPixelT,InPixelT) \ INSTANTIATE_GPU_ConvolutionMI_SpatiallyInvariantKernel(OutPixelT,InPixelT) INSTANTIATE(double, double) INSTANTIATE(double, float) INSTANTIATE(double, int) INSTANTIATE(double, boost::uint16_t) INSTANTIATE(float, float) INSTANTIATE(float, int) INSTANTIATE(float, boost::uint16_t) INSTANTIATE(int, int) INSTANTIATE(boost::uint16_t, boost::uint16_t) /// \endcond } } } } //namespace lsst::afw::math::detail ends #endif //GPU_BUILD

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    76b599b9

    commit 76b599b945af050d195cc5117dfda3c7e06b5d1b
    Author: cosic 
    Date:   Tue Aug 9 05:05:10 2011 +0000
    
        Spatial functions now calculated on GPU, and fix for a kernel-mask problem
    

    96dee205

    commit 96dee2059da27d99a2360145244d7a5260aa01ea
    Author: Kresimir Cosic 
    Date:   Mon Dec 5 23:40:17 2011 +0100
    
        miscellaneous fixes to get GPU build working again
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    doc/mainpage.dox

    Diff:

                    /**
                    \mainpage lsst::afw;  the LSST Application Framework
                    
                    \section afwSecIntro Introduction
                    
                    The LSST applications framework provides the basic functionality needed
                    by an image processing system.  In particular:
                       - \ref afwSecImage : Representation of Images (and Masks)
                       - \ref afwSecPyImage : How to manipulate images from python
                       - \ref afwSecDisplay : How to display images
                       - \ref afwSecMath :  Mathematical functions such as convolution and image statistics
                       - \ref afwSecDetection : Detection of sources in images
    
    13 2cebc2a3 - - \ref afwTable : Table and record classes for catalog data
    ? -
    13 9ac1c0ad + - \ref afwTable : Table and record classes for catalog data
    14 9ac1c0ad + - \ref afwCameraGeom : Camera geometry, including transformation between camera-based coordinate systems
    */ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- namespace lsst { namespace afw { namespace image { /** \page afwSecImage Images \section afwSecImage Images In LSST, 2-dimensional images are represented using a set of templated classes, all of which are ultimately derived from ImageBase: - Image : An %image of arithmetic type (e.g. short; int; float) - Mask : An %image representing a set of bitplanes - DecoratedImage : An Image that has associated metadata (e.g. from a FITS header) - MaskedImage : A combination of an Image, a Mask, and an Image giving the per-pixel variance - Exposure : A MaskedImage with additional \link Wcs WCS\endlink information
    32 0db2729c - You can use \ref afwSecDisplay "ds9" to display Image%s and their Mask%s.
    ? --------
    33 bde0ab27 + You can use \ref afwSecDisplay "displaying images" to display Image%s and their Mask%s.
    ? ++++++++++++++++++++++ \subsection afwSecPixelAccess How to Access Pixels %Image Pixels may be accessed via iterators or locators; the former are simpler if you want single-pixel access, while the latter provide you with access to a pixel's friends and neighbours. The following tutorials are available: - \link imageIterators Image iterators\endlink - \link imageLocators Image locators\endlink - \link maskedImageIterators MaskedImage iterators\endlink - \link maskedImageLocators MaskedImage locators\endlink See also \ref afwSecPixelAccessReference. LSST %image access is modelled after the boost::gil %image interface; see http://www.boost.org/doc/libs/1_48_0/libs/gil/doc/html/giltutorial.html and http://www.boost.org/doc/libs/1_48_0/libs/gil/doc/html/gildesignguide.html - \ref afwSecImageIO There are also some algorithms analogous to the STL's @c \; see \ref afwSecImageAlgorithm. \subsection Using Masks - \ref afwMaskPlanes */ /** \addtogroup afwSecPixelAccessReference Pixel Access Reference Manual (Return to \ref afwSecImage) %Image Pixels may be accessed via iterators or locators; the former are simpler if you want single-pixel access, while the latter provide you with access to a pixel's friends and neighbours. There are a set of tutorials: - \link imageIterators Image iterators\endlink - \link imageLocators Image locators\endlink - \link maskedImageIterators MaskedImage iterators\endlink - \link maskedImageLocators MaskedImage locators\endlink In the case of MaskedImage, the user-visible \c iterator%s and locator%s (and \c const variants) are derived from MaskedImageIteratorBase and MaskedImageLocatorBase; the following documentation refers to these base classes. \par Iterators - You can use an STL-compliant \c iterator to access the pixels: - ImageBase::begin() const - ImageBase::begin(bool) const - MaskedImage::begin() const - MaskedImage::begin(bool) const - ImageBase::end() const - ImageBase::end(bool) const - MaskedImage::end() const - MaskedImage::end(bool) const - ImageBase::rbegin() const - MaskedImage::rbegin() const - ImageBase::rend() const - MaskedImage::rend() const - ImageBase::at(int x, int y) const - MaskedImage::at(int x, int y) const N.b. These \c iterators aren't the most efficient way to access all the %image's pixels as they may not be contiguous in memory so a test for end-of-row is needed after every %pixel (we do guarantee that a \e row's pixels will be contiguous). The exceptions are the \c begin(bool) and \c end(bool) pairs which are only valid for contiguous images (they'll throw an exception if the %image isn't), but are the fastest way to traverse an %image if available. Note that they return an \c x_iterator not an \c iterator. - Incrementing an \c y_iterator moves it across the row - ImageBase::row_begin(int y) const - MaskedImage::row_begin(int y) const - ImageBase::row_end(int y) const - MaskedImage::row_end(int y) const - ImageBase::x_at(int x, int y) const - MaskedImage::x_at(int x, int y) const - Incrementing an \c y_iterator moves it up the column - ImageBase::col_begin(int x) const - MaskedImage::col_begin(int x) const - ImageBase::col_end(int x) const - MaskedImage::col_end(int x) const - ImageBase::y_at(int x, int y) const - MaskedImage::y_at(int x, int y) const - Iterators can be dereferenced: - imageIterator::operator*() - MaskedImage::MaskedImageIteratorBase::operator*() - Additionally, MaskedImage iterators support - MaskedImage::MaskedImageIteratorBase::image() - MaskedImage::MaskedImageIteratorBase::mask() - MaskedImage::MaskedImageIteratorBase::variance() - Iterators may be advanced with - imageIterator::operator++() - MaskedImage::MaskedImageIteratorBase::operator++() - imageIterator::operator++(int) - MaskedImage::MaskedImageIteratorBase::operator++(int) - imageIterator::operator+=(std::ptrdiff_t delta) - MaskedImage::MaskedImageIteratorBase::operator+=(std::ptrdiff_t delta) - imageIterator::operator-=(std::ptrdiff_t delta) - MaskedImage::MaskedImageIteratorBase::operator-=(std::ptrdiff_t delta) - and compared with - imageIterator::operator==(imageIterator const& rhs) - MaskedImage::MaskedImageIteratorBase::operator==(MaskedImageIteratorBase const& rhs) - imageIterator::operator!=(imageIterator const& rhs) - MaskedImage::MaskedImageIteratorBase::operator!=(MaskedImageIteratorBase const& rhs) - imageIterator::operator<(imageIterator const& rhs) - MaskedImage::MaskedImageIteratorBase::operator<(MaskedImageIteratorBase const& rhs) \par Locators \c Locators are more flexible than \c iterators, permitting us to manipulate regions of an %image - locators may be created with - ImageBase::xy_at(int x, int y) const - MaskedImage::xy_at(int x, int y) const - and dereferenced with: - imageLocator::operator*() - MaskedImage::MaskedImageLocatorBase::operator*() - imageLocator::operator()(int x, int y) - MaskedImage::MaskedImageLocatorBase::operator()(int x, int y) - Retrieve an x- or y-iterator that may be dereferenced or incremented - imageLocator::x() - MaskedImage::MaskedImageLocatorBase::x() - imageLocator::y() - MaskedImage::MaskedImageLocatorBase::y() - Manipulate those iterators (n.b. this moves the underlying locator, so \c ++locator.x() is the standard way to advance a locator) - imageLocator::xy_x_iterator::operator*() - MaskedImage::MaskedImageLocatorBase::xy_x_iterator::operator*() - imageLocator::xy_y_iterator::operator*() - MaskedImage::MaskedImageLocatorBase::xy_y_iterator::operator*() - Additionally, MaskedImage locator-iterators support - image() - mask() - variance() - Move those iterators (n.b. this moves the underlying locator, so \c ++locator.x() is the standard way to advance a locator) - imageLocator::xy_x_iterator::operator++() - imageLocator::xy_x_iterator::operator++(int) - imageLocator::xy_y_iterator::operator++() - imageLocator::xy_y_iterator::operator++(int) - Advance (or retreat) an \c xy_locator directly - ImageBase::operator+=(xy_locator& loc, pair2I const& off) - MaskedImage::MaskedImageLocatorBase::operator+=(pair2I const& off) - ImageBase::operator+=(const_xy_locator& loc, pair2I const& off) - ImageBase::operator-=(xy_locator& loc, pair2I const& off) - ImageBase::operator-=(const_xy_locator& loc, pair2I const& off) - Save or use a saved relative location - imageLocator::cache_location() - MaskedImage::MaskedImageLocatorBase::cache_location() - imageLocator::cache_location(int x, int y) - MaskedImage::MaskedImageLocatorBase::cache_location(int x, int y) const - imageLocator::operator[](cached_location_t const&); - MaskedImage::MaskedImageLocatorBase::operator[](cached_location_t const&); - MaskedImage locators also support - MaskedImage::MaskedImageLocatorBase::image(cached_location_t const&); - MaskedImage::MaskedImageLocatorBase::mask(cached_location_t const&); - MaskedImage::MaskedImageLocatorBase::variance(cached_location_t const&); (Note that these are function calls, as opposed to the \c operator[] in the previous APIs) */ }}} namespace lsst { namespace afw { namespace image { /** \page afwSecImageIO Image I/O \section afwSecImageIO Image/Mask/MaskedImage I/O Reading Image%s, Mask%s, and MaskedImage%s from FITS files is achieved via their constructors that take a string, e.g. \code Image::Image(fileName, hdu=0, metadata=lsst::daf::base::PropertySet::Ptr(), bbox=BBox()); \endcode - \c fileName gives the name of the file to be written (but see \ref MaskedImageIo). - The \c hdu is FITS jargon for the Header Data Unit; the 1-indexed offset of the desired block of data in the file. As a special favour, "0" is intepreted as the first HDU, and if it's empty, the next is read instead. - The \c metadata is basically the contents of the FITS header (n.b. it's read automatically if you call \link Exposure::Exposure\endlink(fileName)). - If the bounding box \c bbox is supplied, only that part of the file is read (n.b. in this case the image's origin is set correctly, cf. Image::getXY0). Writing to FITS files is done via a method, e.g. Image::writeFits (but once more, you should peruse \ref MaskedImageIo). \subsection MaskedImageIo Reading and writing MaskedImages MaskedImage%s are a bit more complicated, as there are three pieces of data to read or write, the %image, the mask, and the variance. What's more, LSST changed its mind about how to do this in the early summer of 2009. The old convention was to write three separate FITS files, so a call to MaskedImage::writeFits("foo") would result in three files, \b foo_img.fits, \b foo_msk.fits, and \b foo_var.fits. The new convention is that, if the filename looks like a complete FITS file, the data should be written to a single Multi Extension Fits (MEF) file. I.e. - MaskedImage::writeFits("foo.fits") writes the single MEF file, \b foo.fits - MaskedImage::writeFits("foo") still writes three files, \b foo_{img,msk,var}.fits, unless you explictly set writeMef in which case a single file, foo, will be written. In both cases, the FITS HDUs are identified with the \c EXTTYPE keyword; the possible values are \c IMAGE, \c MASK, and \c VARIANCE. If the \c EXTTYPE keyword is present in the file, it must have the expected value or \c lsst::pex::exceptions::InvalidParameterException is thrown. \deprecated Please do not use the three-separate-files APIs in new code. The corresponding constructors obeyed and obey the same conventions, so - MaskedImage::MaskedImage("foo") reads \b foo_{img,msk,var}.fits if \b foo_img.fits exists, otherwise it reads \b foo - MaskedImage::MaskedImage("foo.fits") reads \b foo.fits @note If \b foo.fits doesn't exist, the code tries to read \b foo.fits_img.fits for backward compatibility, but there's no way to force the code to write this file. \subsection afwSecAppendingToFits Appending to FITS files If you specify the mode in e.g. Image::writeFits to \b a (or \b ab), the desired data will be appended to the file. For Image%s and Mask%s this adds a single HDU, while for a MaskedImage it adds 3. You can read the HDU of your desires by passing an \c hdu to the constructor. \note For MaskedImage if you specify \b hdu, we'll read \b hdu, \b hdu+1, and \b hdu+2 so to get the nth MaskedImage, you should set hdu == 1 + 3*n */ }}} //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- namespace lsst { namespace afw { namespace math { /** \page afwSecMath Mathematical Operations \section afwSecMath Mathematical Operations - Statistics. Annotated examples are available for \link StatisticsExample Statistics\endlink. - Background estimation of images. Annotated examples are available for \link BackgroundExample Background Estimation\endlink. - Interpolate - Convolution of images is handled by convolve() - Warping Images is handled by warpImage() - Manipulating spatially-distributed sets of objects (e.g. PSF candidates); an annotated example is available as \link SpatialCellSetExample\endlink */ }}} //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- namespace lsst { namespace afw { namespace detection { /** \page afwSecDetection Detection \section afwSecDetection Detection Detected pixels are manipulated using the following classes: - Footprint : A set of pixels above (or below) a Threshold - FootprintFunctor : A functor to process the pixels in a Footprint - FootprintSet : A set of Footprints associated with a MaskedImage - Peak : A peak pixel in the %image - Source : The properties of a source of electrons (e.g. a star or cosmic ray) - Threshold : An object describing the threshold used to define a set of Footprint%s Annotated examples are available for \link FootprintFunctorsExample FootprintFunctors\endlink. */ }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0db2729c

    commit 0db2729c943e400b3d741354fd8399f7fdde3431
    Author: Robert Lupton the Good 
    Date:   Thu Dec 22 15:06:34 2011 -0500
    
        Initial version that compiles with MaskDict implementation of private Mask dictionaries
    

    2cebc2a3

    commit 2cebc2a311e636364b7c82c3a952e9f30cd65be0
    Author: Jim Bosch 
    Date:   Tue Feb 7 14:01:54 2012 -0500
    
        updated tutorial documentation, added __setitem__ for array fields in Python
    

    Commits in /Users/nate/repos_lsst/afw/

    9ac1c0ad

    commit 9ac1c0ad6e0ccf8ddc0a2219a14ed920f0925eba
    Author: Russell Owen 
    Date:   Wed Jun 25 16:41:56 2014 -0700
    
        Try this again. Somehow the changes didn't get committed last time.
    

    bde0ab27

    commit bde0ab27a9add858f810563213c1424f9e63ddde
    Author: Robert Lupton the Good 
    Date:   Sun Apr 12 16:00:47 2015 -0300
    
        Implement RFC-42
        
        N.b. that you need display_ds9 to use the ds9 backend
        N.b. support frame only in cameraGeom.utils top-level routine, showCamera
    

    Return to list

    include/lsst/afw/table/detail/SchemaImpl.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_DETAIL_SchemaImpl_h_INCLUDED
                    #define AFW_TABLE_DETAIL_SchemaImpl_h_INCLUDED
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/variant.hpp"
                    #include "boost/mpl/transform.hpp"
                    #include "boost/type_traits/remove_const.hpp"
                    #include "boost/type_traits/remove_reference.hpp"
                    
                    #include "lsst/daf/base/Citizen.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    class Schema;
                    class SubSchema;
                    
                    /**
                     *  @brief A simple pair-like struct for mapping a Field (name and description) with a Key
                     *         (used for actual data access).
                     */
                    template 
                    struct SchemaItem {
                    #ifndef SWIG  // see comment block in tableLib.i; workaround to avoid dangling references
                        Key key;
                        Field field;
                    #endif 
                        SchemaItem(Key const & key_, Field const & field_) : key(key_), field(field_) {}
                    };
                    
                    namespace detail {
                    
                    #ifndef SWIG
                    
                    class Access;
                    
                    /**
                     *  @brief A private implementation class to hide the messy details of Schema.
                     *
                     *  This can't be a real pimpl class, because some of the most important functionality
                     *  is in the forEach function, a templated function we can't explicitly instantiate
                     *  in a source file.  But putting all the details here draws a clear line between what
                     *  users should look at (Schema) and what they shouldn't (this).
                     *
                     *  Because Schema holds SchemaImpl by shared pointer, one SchemaImpl can be shared between
                     *  multiple Schemas (and SubSchemas), which implement copy-on-write by creating a new SchemaImpl
                     *  if the pointer they have isn't unique when they are modified.
                     *
                     *  SchemaImpl inherits from Citizen; this allows both Schemas and SubSchemas to be tracked in
                     *  a more meaningful way than if we derived either of those from Citizen.
                     */
                    class SchemaImpl : public daf::base::Citizen {
                    private:
                    
                        /// Boost.MPL metafunction that returns a SchemaItem given a T.
                        struct MakeItem {
                            template 
                            struct apply {
                                typedef SchemaItem type;
                            };
                        };
                    
                    public:
                    
    
    69 4223afcb + static int const DEFAULT_VERSION = 1;
    70 4223afcb +
    /// An MPL sequence of all the allowed SchemaItem templates. typedef boost::mpl::transform::type ItemTypes; /// A Boost.Variant type that can hold any one of the allowed SchemaItem types. typedef boost::make_variant_over< ItemTypes >::type ItemVariant; /// A std::vector whose elements can be any of the allowed SchemaItem types. typedef std::vector ItemContainer; /// A map from field names to position in the vector, so we can do name lookups. typedef std::map NameMap; /// A map from standard field offsets to position in the vector, so we can do field lookups. typedef std::map OffsetMap; /// A map from Flag field offset/bit pairs to position in the vector, so we can do Flag field lookups. typedef std::map,int> FlagMap; /// The size of a record in bytes. int getRecordSize() const { return _recordSize; } /// The total number of fields. int getFieldCount() const { return _names.size(); } /// The number of Flag fields. int getFlagFieldCount() const { return _flags.size(); } /// The number of non-Flag fields. int getNonFlagFieldCount() const { return _offsets.size(); } /// Find an item by name (used to implement Schema::find). template SchemaItem find(std::string const & name) const; /// Find an item by key (used to implement Schema::find). template SchemaItem find(Key const & key) const; /// Find an item by key (used to implement Schema::find). SchemaItem find(Key const & key) const; /// Return a set of field names (used to implement Schema::getNames). std::set getNames(bool topOnly) const; /// Return a set of field names (used to implement SubSchema::getNames). std::set getNames(bool topOnly, std::string const & prefix) const; template int contains(SchemaItem const & item, int flags) const; /// Add a field to the schema (used to implement Schema::addField). template Key addField(Field const & field, bool doReplace=false); /// Add a field to the schema (used to implement Schema::addField). Key addField(Field const & field, bool doReplace=false); /// Add a field to the schema (used to implement Schema::addField). template Key< Array > addField(Field< Array > const & field, bool doReplace=false); /// Replace the Field in an existing SchemaItem without changing the Key. template void replaceField(Key const & key, Field const & field); /** * @brief Return the vector of SchemaItem variants. * * Fields are in the order they are added. That means they're also ordered with increasing * Key offsets, except for Flag fields, which are in increasing order of (offset, bit) relative * to each other, but not relative to all the other fields. */ ItemContainer const & getItems() const { return _items; } /// Default constructor. explicit SchemaImpl() : daf::base::Citizen(typeid(this)),
    141 8d0209b2 - _recordSize(0), _lastFlagField(-1), _lastFlagBit(-1), _items()
    143 4c2ea6d5 + _recordSize(0), _lastFlagField(-1), _lastFlagBit(-1), _items(), _version(DEFAULT_VERSION)
    ? +++++++++++++++++++++++++++ {} /** * @brief A functor-wrapper used in the implementation of Schema::forEach. * * Visitor functors used with Boost.Variant (see the Boost.Variant docs) * must inherit from boost::static_visitor<> to declare their return type * (void, in this case). By wrapping user-supplied functors with this class, * we can hide the fact that we've implemented SchemaImpl using Boost.Variant * (because they won't need to inherit from static_visitor themselves. */ template struct VisitorWrapper : public boost::static_visitor<> { /// Call the wrapped function. template void operator()(SchemaItem const & x) const { _func(x); }; /** * @brief Invoke the visitation. * * The call to boost::apply_visitor will call the appropriate template of operator(). * * This overload allows a VisitorWrapper to be applied directly on a variant object * with function-call syntax, allowing us to use it on our vector of variants with * std::for_each and other STL algorithms. */ void operator()(ItemVariant const & v) const { boost::apply_visitor(*this, v); } /// @brief Construct the wrapper. explicit VisitorWrapper(F func) : _func(func) {} private: F _func; };
    182 bd692192 + /// @brief Return the table's version.
    183 bd692192 + int getVersion() const { return _version; }
    184 bd692192 +
    185 bd692192 + /// @brief Set the table's version.
    186 bd692192 + void setVersion(int version) { _version = version; }
    187 bd692192 +
    188 bd692192 +
    private: friend class detail::Access; template Key addFieldImpl(int elementSize, int elementCount, Field const & field, bool doReplace); int _recordSize; // Size of a record in bytes. int _lastFlagField; // Offset of the last flag field in bytes. int _lastFlagBit; // Bit of the last flag field. ItemContainer _items; // Vector of variants of SchemaItem. NameMap _names; // Field name to vector-index map.
    192 d6480e01 - OffsetMap _offsets; // Offset to vector-index map.
    ? ----
    201 02e44d9b + OffsetMap _offsets; // Offset to vector-index map for regular fields.
    ? +++++++++++++++++++
    193 d6480e01 - FlagMap _flags; // Offset to vector-index map.
    202 02e44d9b + FlagMap _flags; // Offset to vector-index map for flags.
    ? ++++++++++
    203 bd692192 + int _version; // temporary flag for version 0/1 tables
    }; #endif }}}} // namespace lsst::afw::table::detail #endif // !AFW_TABLE_DETAIL_SchemaImpl_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d6480e01

    commit d6480e01cf98ec6e6ebea9b7f58d2d9dcef6beef
    Author: Jim Bosch 
    Date:   Sun Feb 5 23:11:25 2012 -0500
    
        lots of documentation, and a little refactoring to improve readability
    

    8d0209b2

    commit 8d0209b2df833174da15fa6aacff8feb4d77dc7b
    Author: Jim Bosch 
    Date:   Sat Jan 28 17:16:24 2012 -0500
    
        added tests for SourceSet and fixed bugs; added Citizen base class to SchemaImpl
    

    Commits in /Users/nate/repos_lsst/afw/

    02e44d9b

    commit 02e44d9b44fd74662b230dc5858419ca24d10788
    Author: Jim Bosch 
    Date:   Mon Oct 1 18:50:43 2012 -0400
    
        first implementation of aliases for Schemas; no persistence yet
    

    4223afcb

    commit 4223afcb1247eb4bf8ed03f919d169b2fba462ca
    Author: Perry Gee 
    Date:   Fri Aug 29 17:54:47 2014 -0700
    
        DM-1070 Change the DEFAULT_VERSION of Schema from 0 to 1
        
        DEFAULT_VERSION moved to SchemaImpl, but is copied by Schema so that
        it is visible to SWIG.
        Fix up tests which assumed version 0.
    

    4c2ea6d5

    commit 4c2ea6d5c82fcbe92c0495ec4fffbdc3440f639f
    Author: Perry Gee 
    Date:   Tue Sep 2 14:18:59 2014 -0700
    
        Missed setting the DEFAULT_VERSION in the constructor
    

    bd692192

    commit bd692192367d33bb64a79ca008bff10eb9b41932
    Author: pgee 
    Date:   Mon Aug 18 15:06:04 2014 -0700
    
        Move API version number from BaseTable to Schema
        
        In FitsReader, move reading the AFW_TABLE_VERSION header key into the
        Schema-from-metadata constructor.
        In FitsWriter, use the version attached to the table schema to write the
        metadata.
    

    Return to list

    src/formatters/MaskedImageFormatter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    /** @file
                     * @brief Implementation of MaskedImageFormatter class
                     *
                     * @author $Author: ktlim $
                     * @version $Revision: 2151 $
                     * @date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * @ingroup afw
                     */
                    
                    #ifndef __GNUC__
                    #  define __attribute__(x) /*NOTHING*/
                    #endif
                    static char const* SVNid __attribute__((unused)) =
                        "$Id$";
                    
                    #include "boost/serialization/shared_ptr.hpp"
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/persistence.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/formatters/MaskedImageFormatter.h"
                    #include "lsst/afw/formatters/ImageFormatter.h"
                    #include "lsst/afw/formatters/MaskFormatter.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.MaskedImageFormatter", level, s);
                    }
                    
                    using lsst::daf::base::Persistable;
                    using lsst::daf::persistence::BoostStorage;
                    using lsst::daf::persistence::FitsStorage;
                    using lsst::daf::persistence::Storage;
                    using lsst::afw::image::MaskedImage;
                    using lsst::afw::image::MaskPixel;
                    using lsst::afw::image::VariancePixel;
                    
                    namespace lsst {
                    namespace afw {
                    namespace formatters {
                    
                    template 
                    class MaskedImageFormatterTraits {
                    public:
                        static std::string name();
                    };
                    
                    template<> std::string MaskedImageFormatterTraits::name() {
                        static std::string name = "MaskedImageU";
                        return name;
                    }
                    template<> std::string MaskedImageFormatterTraits::name() {
                        static std::string name = "MaskedImageI";
                        return name;
                    }
                    template<> std::string MaskedImageFormatterTraits::name() {
                        static std::string name = "MaskedImageF";
                        return name;
                    }
                    template<> std::string MaskedImageFormatterTraits::name() {
                        static std::string name = "MaskedImageD";
                        return name;
                    }
                    template<> std::string MaskedImageFormatterTraits::name() {
                        static std::string name = "MaskedImageL";
                        return name;
                    }
                    
                    template 
                    lsst::daf::persistence::FormatterRegistration MaskedImageFormatter::registration(
                        MaskedImageFormatterTraits::name(),
                        typeid(MaskedImage),
                        createInstance);
                    
                    template 
                    MaskedImageFormatter::MaskedImageFormatter(
                        lsst::pex::policy::Policy::Ptr
                                                                                                       )
                        :
                        lsst::daf::persistence::Formatter(typeid(this)) {
                    }
                    
                    template 
                    MaskedImageFormatter::~MaskedImageFormatter(void) {
                    }
                    
                    template 
                    void MaskedImageFormatter::write(
                        Persistable const* persistable,
                        Storage::Ptr storage,
                        lsst::daf::base::PropertySet::Ptr) {
                        execTrace("MaskedImageFormatter write start");
                        MaskedImage const* ip =
                            dynamic_cast const*>(persistable);
                        if (ip == 0) {
    
    131 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Persisting non-MaskedImage");
    ? ---------
    131 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Persisting non-MaskedImage");
    } if (typeid(*storage) == typeid(BoostStorage)) { execTrace("MaskedImageFormatter write BoostStorage"); BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & *ip; execTrace("MaskedImageFormatter write end"); return; } else if (typeid(*storage) == typeid(FitsStorage)) { execTrace("MaskedImageFormatter write FitsStorage"); FitsStorage* fits = dynamic_cast(storage.get()); ip->writeFits(fits->getPath()); execTrace("MaskedImageFormatter write end"); return; }
    147 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for MaskedImage");
    ? ---------
    147 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for MaskedImage");
    } template Persistable* MaskedImageFormatter::read( Storage::Ptr storage, lsst::daf::base::PropertySet::Ptr ) { execTrace("MaskedImageFormatter read start"); if (typeid(*storage) == typeid(BoostStorage)) { execTrace("MaskedImageFormatter read BoostStorage"); BoostStorage* boost = dynamic_cast(storage.get()); MaskedImage* ip = new MaskedImage; boost->getIArchive() & *ip; execTrace("MaskedImageFormatter read end"); return ip; } else if (typeid(*storage) == typeid(FitsStorage)) { execTrace("MaskedImageFormatter read FitsStorage"); FitsStorage* fits = dynamic_cast(storage.get()); MaskedImage* ip = new MaskedImage(fits->getPath()); execTrace("MaskedImageFormatter read end"); return ip; }
    172 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for MaskedImage");
    ? ---------
    172 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for MaskedImage");
    } template void MaskedImageFormatter::update( Persistable*, Storage::Ptr, lsst::daf::base::PropertySet::Ptr ) {
    182 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    182 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Unexpected call to update for MaskedImage"); } template template void MaskedImageFormatter::delegateSerialize( Archive& ar, unsigned int const, Persistable* persistable) { execTrace("MaskedImageFormatter delegateSerialize start"); MaskedImage* ip = dynamic_cast*>(persistable); if (ip == 0) {
    193 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Serializing non-MaskedImage");
    ? ---------
    193 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Serializing non-MaskedImage");
    } ar & ip->_image & ip->_variance & ip->_mask; execTrace("MaskedImageFormatter delegateSerialize end"); } template lsst::daf::persistence::Formatter::Ptr MaskedImageFormatter::createInstance( lsst::pex::policy::Policy::Ptr policy) { return lsst::daf::persistence::Formatter::Ptr( new MaskedImageFormatter(policy)); } /// \cond #define INSTANTIATE(I, M, V) \ template class MaskedImageFormatter; \ template void MaskedImageFormatter::delegateSerialize( \ boost::archive::text_oarchive &, unsigned int const, Persistable *); \ template void MaskedImageFormatter::delegateSerialize( \ boost::archive::text_iarchive &, unsigned int const, Persistable *); \ template void MaskedImageFormatter::delegateSerialize( \ boost::archive::binary_oarchive &, unsigned int const, Persistable *); \ template void MaskedImageFormatter::delegateSerialize( \ boost::archive::binary_iarchive &, unsigned int const, Persistable *); INSTANTIATE(uint16_t, MaskPixel, VariancePixel) INSTANTIATE(int, MaskPixel, VariancePixel) INSTANTIATE(float, MaskPixel, VariancePixel) INSTANTIATE(double, MaskPixel, VariancePixel) INSTANTIATE(uint64_t, MaskPixel, VariancePixel) /// \endcond }}} // namespace lsst::afw::formatters

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    7a6ea5ce

    commit 7a6ea5ce178494cb61090089847aacd809082e36
    Author: bick 
    Date:   Wed Jan 6 20:50:58 2010 +0000
    
        #1113 sundry style corrections on afw.
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/image/Image.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief Implementation for ImageBase and Image
                     */
                    #include 
                    #include "boost/mpl/vector.hpp"
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/lambda/lambda.hpp"
                    #pragma clang diagnostic pop
                    #include "boost/bind/bind.hpp"
                    #include "boost/format.hpp"
                    #include "boost/filesystem/path.hpp"
                    #include "boost/gil/gil_all.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/image/ImageAlgorithm.h"
                    #include "lsst/afw/image/Wcs.h"
                    #include "lsst/afw/fits.h"
                    #include "lsst/afw/image/fits/fits_io.h"
                    #include "lsst/afw/image/fits/fits_io_mpl.h"
                    
                    namespace image = lsst::afw::image;
                    namespace geom = lsst::afw::geom;
                    
                    /************************************************************************************************************/
                    template 
                    typename image::ImageBase::_view_t image::ImageBase::_allocateView(
                        geom::Extent2I const & dimensions,
                        Manager::Ptr & manager
                    ) {
                        if (dimensions.getX() < 0 || dimensions.getY() < 0) {
    
    58 4abc0a0c - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    58 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    str(boost::format("Both width and height must be non-negative: %d, %d") % dimensions.getX() % dimensions.getY())); } if (dimensions.getX() != 0 && dimensions.getY() > std::numeric_limits::max()/dimensions.getX()) {
    63 eed281cb + throw LSST_EXCEPT(pex::exceptions::LengthError,
    63 b59c0db7 - throw LSST_EXCEPT(
    64 b59c0db7 - pex::exceptions::LengthErrorException,
    65 b59c0db7 - str(boost::format("Image dimensions (%d x %d) too large; int overflow detected.")
    64 eed281cb + str(boost::format("Image dimensions (%d x %d) too large; int overflow detected.")
    ? ++++++++++++++
    66 b59c0db7 - % dimensions.getX() % dimensions.getY())
    65 eed281cb + % dimensions.getX() % dimensions.getY()));
    ? ++++++++++++++ ++
    67 b59c0db7 - );
    } std::pair r = ndarray::SimpleManager::allocate( dimensions.getX() * dimensions.getY() ); manager = r.first; return boost::gil::interleaved_view( dimensions.getX(), dimensions.getY(), (typename _view_t::value_type* )r.second, dimensions.getX()*sizeof(PixelT) ); } template typename image::ImageBase::_view_t image::ImageBase::_makeSubView( geom::Extent2I const & dimensions, geom::Extent2I const & offset, const _view_t & view ) { if (offset.getX() < 0 || offset.getY() < 0 || offset.getX() + dimensions.getX() > view.width() || offset.getY() + dimensions.getY() > view.height() ) { throw LSST_EXCEPT(
    88 3263f939 - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    86 21597d88 + lsst::pex::exceptions::LengthError,
    (boost::format("Box2I(Point2I(%d,%d),Extent2I(%d,%d)) doesn't fit in image %dx%d") % offset.getX() % offset.getY() % dimensions.getX() % dimensions.getY() % view.width() % view.height() ).str() ); } return boost::gil::subimage_view( view, offset.getX(), offset.getY(), dimensions.getX(), dimensions.getY() ); } /** * Allocator Constructor * * allocate a new image with the specified dimensions. * Sets origin at (0,0) */ template image::ImageBase::ImageBase( geom::Extent2I const & dimensions ) : lsst::daf::base::Citizen(typeid(this)), _origin(0,0), _manager(), _gilView(_allocateView(dimensions, _manager)) {} /** * Allocator Constructor * * allocate a new image with the specified dimensions and origin */ template image::ImageBase::ImageBase( geom::Box2I const & bbox ) : lsst::daf::base::Citizen(typeid(this)), _origin(bbox.getMin()), _manager(), _gilView(_allocateView(bbox.getDimensions(), _manager)) {} /** * Copy constructor. * * \note Unless \c deep is \c true, the new %image will share the old %image's pixels; * this may not be what you want. See also operator<<=() to copy pixels between Image%s */ template image::ImageBase::ImageBase( ImageBase const& rhs, ///< Right-hand-side %image bool const deep ///< If false, new ImageBase shares storage with rhs; ///< if true make a new, standalone, ImageBase ) : lsst::daf::base::Citizen(typeid(this)), _origin(rhs._origin), _manager(rhs._manager), _gilView(rhs._gilView) { if (deep) {
    148 3263f939 - ImageBase tmp(getBBox(PARENT));
    ? ------
    146 93994d54 + ImageBase tmp(getBBox());
    tmp <<= *this; // now copy the pixels swap(tmp); } } /** * Copy constructor to make a copy of part of an %image. * * The bbox ignores X0/Y0 if origin == LOCAL, and uses it if origin == PARENT. * * \note Unless \c deep is \c true, the new %image will share the old %image's pixels; * this is probably what you want */ template image::ImageBase::ImageBase( ImageBase const& rhs, ///< Right-hand-side %image geom::Box2I const& bbox, ///< Specify desired region ImageOrigin const origin, ///< Specify the coordinate system of the bbox bool const deep ///< If false, new ImageBase shares storage with rhs; ///< if true make a new, standalone, ImageBase ) : lsst::daf::base::Citizen(typeid(this)), _origin((origin==PARENT) ? bbox.getMin(): rhs._origin + geom::Extent2I(bbox.getMin())), _manager(rhs._manager), // reference counted pointer, don't copy pixels _gilView(_makeSubView(bbox.getDimensions(), _origin - rhs._origin, rhs._gilView)) {
    175 3263f939 -
    if (deep) {
    177 3263f939 - ImageBase tmp(getBBox(PARENT));
    ? ------
    174 93994d54 + ImageBase tmp(getBBox());
    tmp <<= *this; // now copy the pixels swap(tmp); } } /** * Construction from ndarray::Array and NumPy. * * \note ndarray and NumPy indexes are ordered (y,x), but Image indices are ordered (x,y). * * Unless deep is true, the new image will share memory with the array if the the * dimension is contiguous in memory. If the last dimension is not contiguous, the array * will be deep-copied in Python, but the constructor will fail to compile in pure C++. */ template image::ImageBase::ImageBase(Array const & array, bool deep, geom::Point2I const & xy0) : lsst::daf::base::Citizen(typeid(this)), _origin(xy0), _manager(array.getManager()), _gilView( boost::gil::interleaved_view( array.template getSize<1>(), array.template getSize<0>(), (typename _view_t::value_type* )array.getData(), array.template getStride<0>() * sizeof(PixelT) ) ) { if (deep) { ImageBase tmp(*this, true); swap(tmp); } } /// Shallow assignment operator. /// /// \note that this has the effect of making the lhs share pixels with the rhs which may /// not be what you intended; to copy the pixels, use operator<<=() /// /// \note this behaviour is required to make the swig interface work, otherwise I'd /// declare this function private template image::ImageBase& image::ImageBase::operator=(ImageBase const& rhs) { ImageBase tmp(rhs); swap(tmp); // See Meyers, Effective C++, Item 11 return *this; } /// Set the lhs's %pixel values to equal the rhs's template void image::ImageBase::operator<<=(ImageBase const& rhs) { if (getDimensions() != rhs.getDimensions()) {
    230 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    227 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Dimension mismatch: %dx%d v. %dx%d") % getWidth() % getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } copy_pixels(rhs._gilView, _gilView); } /// Return a reference to the pixel (x, y) template typename image::ImageBase::PixelReference image::ImageBase::operator()(int x, int y) { return const_cast::PixelReference>( static_cast::PixelConstReference>(_gilView(x, y)[0]) ); } /// Return a reference to the pixel (x, y) with bounds checking template typename image::ImageBase::PixelReference image::ImageBase::operator()( int x, int y, image::CheckIndices const& check ) { if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
    254 35b5e4e6 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    251 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y % (getWidth() - 1) % (getHeight() - 1)).str()); } return const_cast::PixelReference>( static_cast::PixelConstReference>(_gilView(x, y)[0]) ); } /// Return a const reference to the pixel (x, y) template typename image::ImageBase::PixelConstReference image::ImageBase::operator()(int x, int y) const { return _gilView(x, y)[0]; } /// Return a const reference to the pixel (x, y) with bounds checking template typename image::ImageBase::PixelConstReference image::ImageBase::operator()(int x, int y, image::CheckIndices const& check) const { if (check && (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())) {
    276 35b5e4e6 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    273 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Index (%d, %d) is out of range [0--%d], [0--%d]") % x % y % (this->getWidth() - 1) % (this->getHeight() - 1)).str()); } return _gilView(x, y)[0]; } template void image::ImageBase::swap(ImageBase &rhs) { using std::swap; // See Meyers, Effective C++, Item 25 swap(_manager, rhs._manager); // just swapping the pointers swap(_gilView, rhs._gilView); swap(_origin, rhs._origin); } template void image::swap(ImageBase& a, ImageBase& b) { a.swap(b); } template typename image::ImageBase::Array image::ImageBase::getArray() { int rowStride = reinterpret_cast(row_begin(1)) - reinterpret_cast(row_begin(0)); return ndarray::external( reinterpret_cast(row_begin(0)), ndarray::makeVector(getHeight(), getWidth()), ndarray::makeVector(rowStride, 1), this->_manager ); } template typename image::ImageBase::ConstArray image::ImageBase::getArray() const { int rowStride = reinterpret_cast(row_begin(1)) - reinterpret_cast(row_begin(0)); return ndarray::external( reinterpret_cast(row_begin(0)), ndarray::makeVector(getHeight(), getWidth()), ndarray::makeVector(rowStride, 1), this->_manager ); } // // Iterators // /// Return an STL compliant iterator to the start of the %image /// /// Note that this isn't especially efficient; see \link imageIterators\endlink for /// a discussion template typename image::ImageBase::iterator image::ImageBase::begin() const { return _gilView.begin(); } /// Return an STL compliant iterator to the end of the %image template typename image::ImageBase::iterator image::ImageBase::end() const { return _gilView.end(); } /// Return an STL compliant reverse iterator to the start of the %image template typename image::ImageBase::reverse_iterator image::ImageBase::rbegin() const { return _gilView.rbegin(); } /// Return an STL compliant reverse iterator to the end of the %image template typename image::ImageBase::reverse_iterator image::ImageBase::rend() const { return _gilView.rend(); } /// Return an STL compliant iterator at the point (x, y) template typename image::ImageBase::iterator image::ImageBase::at(int x, int y) const { return _gilView.at(x, y); } /// Return a fast STL compliant iterator to the start of the %image which must be contiguous /// /// \exception lsst::pex::exceptions::Runtime /// Argument \a contiguous is false, or the pixels are not in fact contiguous template typename image::ImageBase::fast_iterator image::ImageBase::begin( bool contiguous ///< Pixels are contiguous (must be true) ) const { if (!contiguous) {
    365 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    362 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Only contiguous == true makes sense"); } if (!this->isContiguous()) {
    369 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    366 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Image's pixels are not contiguous"); } return row_begin(0); } /// Return a fast STL compliant iterator to the end of the %image which must be contiguous /// /// \exception lsst::pex::exceptions::Runtime /// Argument \a contiguous is false, or the pixels are not in fact contiguous template typename image::ImageBase::fast_iterator image::ImageBase::end( bool contiguous ///< Pixels are contiguous (must be true) ) const { if (!contiguous) {
    385 7a6ea5ce - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    382 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Only contiguous == true makes sense"); } if (!this->isContiguous()) {
    389 086429f9 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException,
    ? ---------
    386 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError,
    "Image's pixels are not contiguous"); } return row_end(getHeight()-1); } /************************************************************************************************************/ /// Set the %image's pixels to rhs template image::ImageBase& image::ImageBase::operator=(PixelT const rhs) { fill_pixels(_gilView, rhs); return *this; } /************************************************************************************************************/ // // On to Image itself. ctors, cctors, and operator= // /** * Create an initialised Image of the specified size * * \note Many lsst::afw::image and lsst::afw::math objects define a \c dimensions member * which may be conveniently used to make objects of an appropriate size */ template image::Image::Image(unsigned int width, ///< number of columns unsigned int height, ///< number of rows PixelT initialValue ///< Initial value ) : image::ImageBase(geom::ExtentI(width, height)) { *this = initialValue; } /** * Create an initialised Image of the specified size * * \note Many lsst::afw::image and lsst::afw::math objects define a \c dimensions member * which may be conveniently used to make objects of an appropriate size */ template image::Image::Image(geom::Extent2I const & dimensions, ///< Number of columns, rows PixelT initialValue ///< Initial value ) : image::ImageBase(dimensions) { *this = initialValue; } /** * Create an initialized Image of the specified size */ template image::Image::Image(geom::Box2I const & bbox, ///< dimensions and origin of desired Image PixelT initialValue ///< Initial value ) : image::ImageBase(bbox) { *this = initialValue; } /** * Copy constructor. * * \note Unless \c deep is \c true, the new %image will share the old %image's pixels; * this may not be what you want. See also operator<<=() to copy pixels between Image%s */ template image::Image::Image(Image const& rhs, ///< Right-hand-side Image bool const deep ///< If false, new Image shares storage with rhs; if true ///< make a new, standalone, ImageBase ) : image::ImageBase(rhs, deep) {} /** * Copy constructor to make a copy of part of an Image. * * The bbox ignores X0/Y0 if origin == LOCAL, and uses it if origin == PARENT. * * \note Unless \c deep is \c true, the new %image will share the old %image's pixels; * this is probably what you want */ template image::Image::Image(Image const& rhs, ///< Right-hand-side Image geom::Box2I const& bbox, ///< Specify desired region ImageOrigin const origin, ///< Coordinate system of the bbox bool const deep ///< If false, new ImageBase shares storage with rhs; if true ///< make a new, standalone, ImageBase ) : image::ImageBase(rhs, bbox, origin, deep) {} /// Set the %image's pixels to rhs template image::Image& image::Image::operator=(PixelT const rhs) { this->ImageBase::operator=(rhs); return *this; } /// Assignment operator. /// /// \note that this has the effect of making the lhs share pixels with the rhs which may /// not be what you intended; to copy the pixels, use operator<<=() /// /// \note this behaviour is required to make the swig interface work, otherwise I'd /// declare this function private template image::Image& image::Image::operator=(Image const& rhs) { this->ImageBase::operator=(rhs); return *this; } /************************************************************************************************************/ #ifndef DOXYGEN // doc for this section has been moved to header template image::Image::Image( std::string const & fileName, int hdu, PTR(daf::base::PropertySet) metadata, geom::Box2I const & bbox, ImageOrigin origin ) : image::ImageBase() { fits::Fits fitsfile(fileName, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); fitsfile.setHdu(hdu); try { *this = Image(fitsfile, metadata, bbox, origin); } catch(lsst::afw::fits::FitsError &e) { fitsfile.status = 0; // reset so we can read NAXIS if (fitsfile.getImageDim() == 0) { // no pixels to read LSST_EXCEPT_ADD(e, str(boost::format("HDU %d has NAXIS == 0") % hdu)); } throw e; } } template image::Image::Image( fits::MemFileManager & manager, int const hdu, PTR(daf::base::PropertySet) metadata, geom::Box2I const& bbox, ImageOrigin const origin ) : image::ImageBase() { fits::Fits fitsfile(manager, "r", fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); fitsfile.setHdu(hdu); *this = Image(fitsfile, metadata, bbox, origin); } template image::Image::Image( fits::Fits & fitsfile, PTR(daf::base::PropertySet) metadata, geom::Box2I const& bbox, ImageOrigin const origin ) : image::ImageBase() { typedef boost::mpl::vector< unsigned char, unsigned short, short, int, unsigned int, float, double, boost::uint64_t > fits_image_types; if (!metadata) { metadata.reset(new daf::base::PropertyList()); } fits_read_image(fitsfile, *this, *metadata, bbox, origin); } template void image::Image::writeFits( std::string const & fileName, CONST_PTR(lsst::daf::base::PropertySet) metadata_i, std::string const & mode ) const { fits::Fits fitsfile(fileName, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); writeFits(fitsfile, metadata_i); } template void image::Image::writeFits( fits::MemFileManager & manager, CONST_PTR(lsst::daf::base::PropertySet) metadata_i, std::string const & mode ) const { fits::Fits fitsfile(manager, mode, fits::Fits::AUTO_CLOSE | fits::Fits::AUTO_CHECK); writeFits(fitsfile, metadata_i); } template void image::Image::writeFits( fits::Fits & fitsfile, CONST_PTR(lsst::daf::base::PropertySet) metadata_i ) const { PTR(daf::base::PropertySet) metadata; PTR(daf::base::PropertySet) wcsAMetadata = image::detail::createTrivialWcsAsPropertySet(image::detail::wcsNameForXY0, this->getX0(), this->getY0()); if (metadata_i) { metadata = metadata_i->deepCopy(); metadata->combine(wcsAMetadata); } else { metadata = wcsAMetadata; } image::fits_write_image(fitsfile, *this, metadata); } #endif // !DOXYGEN /************************************************************************************************************/ template void image::Image::swap(Image &rhs) { using std::swap; // See Meyers, Effective C++, Item 25 ImageBase::swap(rhs); ; // no private variables to swap } template void image::swap(Image& a, Image& b) { a.swap(b); } /************************************************************************************************************/ // // N.b. We could use the STL, but I find boost::lambda clearer, and more easily extended // to e.g. setting random numbers // transform_pixels(_gilView, _gilView, lambda::ret(lambda::_1 + rhs)); // is equivalent to // transform_pixels(_gilView, _gilView, std::bind2nd(std::plus(), rhs)); // namespace bl = boost::lambda; // dstn: being a bear of little brain when it comes to templated lambdas, I found it easier to // write out this sqrt function which does the casts explicitly. template static PixelT mysqrt(PixelT x) { return static_cast(std::sqrt(x)); } // In-place, per-pixel, sqrt(). template void image::Image::sqrt() { transform_pixels(_getRawView(), _getRawView(), boost::bind(mysqrt, bl::_1)); } /// Add scalar rhs to lhs template void image::Image::operator+=(PixelT const rhs) { transform_pixels(_getRawView(), _getRawView(), bl::ret(bl::_1 + rhs)); } /// Add Image rhs to lhs template void image::Image::operator+=(Image const& rhs) { if (this->getDimensions() != rhs.getDimensions()) {
    654 b3aef277 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    651 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 + bl::_2)); } /** * @brief Add a Function2(x, y) to an Image */ template void image::Image::operator+=( lsst::afw::math::Function2 const& function ///< function to add ) { for (int y = 0; y != this->getHeight(); ++y) { double const yPos = this->indexToPosition(y, image::Y); double xPos = this->indexToPosition(0, image::X); for (typename Image::x_iterator ptr = this->row_begin(y), end = this->row_end(y); ptr != end; ++ptr, ++xPos) { *ptr += function(xPos, yPos); } } } /// Add Image c*rhs to lhs template void image::Image::scaledPlus(double const c, Image const& rhs) { if (this->getDimensions() != rhs.getDimensions()) {
    682 b3aef277 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    679 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 + bl::ret(c*bl::_2))); } /// Subtract scalar rhs from lhs template void image::Image::operator-=(PixelT const rhs) { transform_pixels(_getRawView(), _getRawView(), bl::ret(bl::_1 - rhs)); } /// Subtract Image rhs from lhs template void image::Image::operator-=(Image const& rhs) { if (this->getDimensions() != rhs.getDimensions()) {
    700 b3aef277 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    697 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 - bl::_2)); } /// Subtract Image c*rhs from lhs template void image::Image::scaledMinus(double const c, Image const& rhs) { if (this->getDimensions() != rhs.getDimensions()) {
    711 b3aef277 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    708 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 - bl::ret(c*bl::_2))); } /** * @brief Subtract a Function2(x, y) from an Image */ template void image::Image::operator-=( lsst::afw::math::Function2 const& function ///< function to add ) { for (int y = 0; y != this->getHeight(); ++y) { double const yPos = this->indexToPosition(y, image::Y); double xPos = this->indexToPosition(0, image::X); for (typename Image::x_iterator ptr = this->row_begin(y), end = this->row_end(y); ptr != end; ++ptr, ++xPos) { *ptr -= function(xPos, yPos); } } } /// Multiply lhs by scalar rhs template void image::Image::operator*=(PixelT const rhs) { transform_pixels(_getRawView(), _getRawView(), bl::ret(bl::_1 * rhs)); } /// Multiply lhs by Image rhs (i.e. %pixel-by-%pixel multiplication) template void image::Image::operator*=(Image const& rhs) { if (this->getDimensions() != rhs.getDimensions()) {
    746 b3aef277 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    743 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 * bl::_2)); } /// Multiply lhs by Image c*rhs (i.e. %pixel-by-%pixel multiplication) template void image::Image::scaledMultiplies(double const c, Image const& rhs) { if (this->getDimensions() != rhs.getDimensions()) {
    757 b3aef277 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    754 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 * bl::ret(c*bl::_2))); } /// Divide lhs by scalar rhs /// /// \note Floating point types implement this by multiplying by the 1/rhs template void image::Image::operator/=(PixelT const rhs) { transform_pixels(_getRawView(), _getRawView(), bl::ret(bl::_1 / rhs)); } // // Specialize float and double for efficiency // namespace lsst { namespace afw { namespace image { template<> void Image::operator/=(double const rhs) { double const irhs = 1/rhs; *this *= irhs; } template<> void Image::operator/=(float const rhs) { float const irhs = 1/rhs; *this *= irhs; } }}} /// Divide lhs by Image rhs (i.e. %pixel-by-%pixel division) template void image::Image::operator/=(Image const& rhs) { if (this->getDimensions() != rhs.getDimensions()) {
    793 b3aef277 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    790 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 / bl::_2)); } /// Divide lhs by Image c*rhs (i.e. %pixel-by-%pixel division) template void image::Image::scaledDivides(double const c, Image const& rhs) { if (this->getDimensions() != rhs.getDimensions()) {
    804 b3aef277 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    801 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % this->getWidth() % this->getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } transform_pixels(_getRawView(), rhs._getRawView(), _getRawView(), bl::ret(bl::_1 / bl::ret(c*bl::_2))); } /************************************************************************************************************/ namespace { /* * Worker routine for manipulating images; */ template struct plusEq : public lsst::afw::image::pixelOp2 { LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const { return static_cast(lhs + rhs); } }; template struct minusEq : public lsst::afw::image::pixelOp2 { LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const { return static_cast(lhs - rhs); } }; template struct timesEq : public lsst::afw::image::pixelOp2 { LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const { return static_cast(lhs*rhs); } }; template struct divideEq : public lsst::afw::image::pixelOp2 { LhsPixelT operator()(LhsPixelT lhs, RhsPixelT rhs) const { return static_cast(lhs/rhs); } }; } /// Add lhs to Image rhs (i.e. %pixel-by-%pixel addition) where types are different /// template void image::operator+=(image::Image &lhs, image::Image const& rhs) { image::for_each_pixel(lhs, rhs, plusEq()); } /// Subtract lhs from Image rhs (i.e. %pixel-by-%pixel subtraction) where types are different /// template void image::operator-=(image::Image &lhs, image::Image const& rhs) { image::for_each_pixel(lhs, rhs, minusEq()); } /// Multiply lhs by Image rhs (i.e. %pixel-by-%pixel multiplication) where types are different /// template void image::operator*=(image::Image &lhs, image::Image const& rhs) { image::for_each_pixel(lhs, rhs, timesEq()); } /// Divide lhs by Image rhs (i.e. %pixel-by-%pixel division) where types are different /// template void image::operator/=(image::Image &lhs, image::Image const& rhs) { image::for_each_pixel(lhs, rhs, divideEq()); } /************************************************************************************************************/ // // Explicit instantiations // /// \cond #define INSTANTIATE_OPERATOR(OP_EQ, T) \ template void image::operator OP_EQ(image::Image& lhs, image::Image const& rhs); \ template void image::operator OP_EQ(image::Image& lhs, image::Image const& rhs); \ template void image::operator OP_EQ(image::Image& lhs, image::Image const& rhs); \ template void image::operator OP_EQ(image::Image& lhs, image::Image const& rhs); \ template void image::operator OP_EQ(image::Image& lhs, image::Image const& rhs); #define INSTANTIATE(T) \ template class image::ImageBase; \ template class image::Image; \ INSTANTIATE_OPERATOR(+=, T); \ INSTANTIATE_OPERATOR(-=, T); \ INSTANTIATE_OPERATOR(*=, T); \ INSTANTIATE_OPERATOR(/=, T) INSTANTIATE(boost::uint16_t); INSTANTIATE(int); INSTANTIATE(float); INSTANTIATE(double); INSTANTIATE(boost::uint64_t); /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    35b5e4e6

    commit 35b5e4e6989c4fb4200064992a6d0c3e12576081
    Author: rhl 
    Date:   Sat Aug 28 12:08:21 2010 +0000
    
        Added bounds-checking pixel assessors (#1417/#1420)
    

    4abc0a0c

    commit 4abc0a0c1cb02ebb55321c22f691ceacba8c1cdd
    Author: Robert Lupton the Good 
    Date:   Sun Nov 25 21:38:46 2012 -0500
    
        Check that an image's dimensions are >= 0
    

    b59c0db7

    commit b59c0db7867c1e3193a8b3c6886d299320ce5671
    Author: Jim Bosch 
    Date:   Fri Apr 18 03:21:54 2014 +0900
    
        Check for overflow in number of pixels when allocating images
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    7a6ea5ce

    commit 7a6ea5ce178494cb61090089847aacd809082e36
    Author: bick 
    Date:   Wed Jan 6 20:50:58 2010 +0000
    
        #1113 sundry style corrections on afw.
    

    086429f9

    commit 086429f941378473de1fa07be4a7f111704d776c
    Author: dubcovsky 
    Date:   Sun Feb 6 06:34:01 2011 +0000
    
        #1556 lsst::afw::ellipses swig wrappers updated. Changed afw::image::ImageBase and derived class to own their data using a boost::shared_ptr rather than a gil::image, this change is completely internal, and does not alter the behavior or public API of afw::image
    

    b3aef277

    commit b3aef277e273fdd2da5e145bf78da598ba6a3444
    Author: rhl 
    Date:   Tue Mar 17 14:49:25 2009 +0000
    
        Arithmetic ops of Images (and logicals on Masks) need to check image sizes; #711
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    eed281cb

    commit eed281cbf0960739bb3907a784c5106c8c01e8e3
    Author: Jim Bosch 
    Date:   Fri Apr 18 03:21:54 2014 +0900
    
        Check for pixel count overflow on image allocation.
        
        Ported from HSC-523.
    

    Return to list

    src/geom/Extent.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include "lsst/afw/geom/CoordinateBase.h"
                    #include "lsst/afw/geom/Point.h"
                    #include "lsst/afw/geom/Extent.h"
                    #include 
                    #include 
                    namespace geom = lsst::afw::geom;
                    
                    template 
                    geom::Extent::Extent(Point const & other) :
                        Super(other.asEigen())
                    {}
                    
                    // The following two template specializations raise Doxygen warnings and produce no documenation.
                    // This is a known Doxygen bug: 
                    /// \cond DOXYGEN_BUG
                    template 
                    geom::Extent::Extent(Point const & other) :
                        Super(other.asEigen())
                    {}
                    
                    template 
                    geom::Extent::Extent(Point const & other) :
                        Super(other.asEigen())
                    {}
                    /// \endcond
                    
                    template 
                    geom::CoordinateExpr geom::ExtentBase::eq(Extent const & other) const {
                        CoordinateExpr r;
    
    52 6e365968 - for (register int n=0; n_vector[n] == other[n];
    ? ---------
    52 51a67dff + for (int n=0; n_vector[n] == other[n];
    return r; } template geom::CoordinateExpr geom::ExtentBase::ne(Extent const & other) const { CoordinateExpr r;
    59 6e365968 - for (register int n=0; n_vector[n] != other[n];
    ? ---------
    59 51a67dff + for (int n=0; n_vector[n] != other[n];
    return r; } template geom::CoordinateExpr geom::ExtentBase::lt(Extent const & other) const { CoordinateExpr r;
    66 7ccf406e - for (register int n=0; n_vector[n] < other[n];
    ? ---------
    66 51a67dff + for (int n=0; n_vector[n] < other[n];
    return r; } template geom::CoordinateExpr geom::ExtentBase::le(Extent const & other) const { CoordinateExpr r;
    73 7ccf406e - for (register int n=0; n_vector[n] <= other[n];
    ? ---------
    73 51a67dff + for (int n=0; n_vector[n] <= other[n];
    return r; } template geom::CoordinateExpr geom::ExtentBase::gt(Extent const & other) const { CoordinateExpr r;
    80 7ccf406e - for (register int n=0; n_vector[n] > other[n];
    ? ---------
    80 51a67dff + for (int n=0; n_vector[n] > other[n];
    return r; } template geom::CoordinateExpr geom::ExtentBase::ge(Extent const & other) const { CoordinateExpr r;
    87 7ccf406e - for (register int n=0; n_vector[n] >= other[n];
    ? ---------
    87 51a67dff + for (int n=0; n_vector[n] >= other[n];
    return r;
    89 7ccf406e + }
    90 7ccf406e +
    91 7ccf406e + template
    92 b449d4b3 + geom::Point geom::ExtentBase::asPoint() const {
    93 b449d4b3 + return Point(static_cast const &>(*this));
    } template geom::Point geom::ExtentBase::operator+(Point const & other) const { return Point(this->_vector + other.asEigen());
    99 7ccf406e + }
    100 6e365968 +
    101 4567a4cd + template
    102 4567a4cd + geom::Extent geom::truncate(Extent const & input) {
    103 4567a4cd + Extent result;
    104 4567a4cd + for (int i = 0; i < N; ++i) {
    105 4567a4cd + result[i] = static_cast(input[i]);
    106 4567a4cd + }
    107 4567a4cd + return result;
    108 4567a4cd + }
    109 4567a4cd +
    110 4567a4cd + template
    111 4567a4cd + geom::Extent geom::floor(Extent const & input) {
    112 4567a4cd + Extent result;
    113 4567a4cd + for (int i = 0; i < N; ++i) {
    114 4567a4cd + result[i] = std::floor(input[i]);
    115 4567a4cd + }
    116 4567a4cd + return result;
    117 4567a4cd + }
    118 4567a4cd +
    119 4567a4cd + template
    120 4567a4cd + geom::Extent geom::ceil(Extent const & input) {
    121 4567a4cd + Extent result;
    122 4567a4cd + for (int i = 0; i < N; ++i) {
    123 4567a4cd + result[i] = std::ceil(input[i]);
    124 4567a4cd + }
    125 4567a4cd + return result;
    } #ifndef DOXYGEN template class geom::ExtentBase; template class geom::ExtentBase; template class geom::ExtentBase; template class geom::ExtentBase; template class geom::Extent; template class geom::Extent; template class geom::Extent; template class geom::Extent; template geom::Extent::Extent(geom::Extent const &); template geom::Extent::Extent(geom::Extent const &); template geom::Extent::Extent(geom::Point const &); template geom::Extent::Extent(geom::Point const &);
    143 4567a4cd + template geom::Extent geom::truncate(geom::Extent const &);
    144 4567a4cd + template geom::Extent geom::truncate(geom::Extent const &);
    145 4567a4cd + template geom::Extent geom::floor(geom::Extent const &);
    146 4567a4cd + template geom::Extent geom::floor(geom::Extent const &);
    147 4567a4cd + template geom::Extent geom::ceil(geom::Extent const &);
    148 4567a4cd + template geom::Extent geom::ceil(geom::Extent const &);
    149 4567a4cd +
    #endif // !DOXYGEN

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6e365968

    commit 6e3659683208d3284beba48d035e588c0aa10cf1
    Author: jbosch 
    Date:   Tue Dec 15 03:11:05 2009 +0000
    
        afw/892:
         - removed new Box objects (will implement in a new ticket)
         - fixed up documentation a bit
         - finished implementing Point and Extent
    

    7ccf406e

    commit 7ccf406eabf8ad8f018a7d66cf517ddeaa94d9e1
    Author: jbosch 
    Date:   Mon Dec 14 19:43:59 2009 +0000
    
        afw/892:
         - implementations for geom (all but Box now done)
         - fixed compilation errors in ellipses and tests for ellipses
         - merged updates from trunk in (fixed an obvious typo introduced in math::offsetImage by the merge)
    

    Commits in /Users/nate/repos_lsst/afw/

    6e365968

    commit 6e3659683208d3284beba48d035e588c0aa10cf1
    Author: jbosch 
    Date:   Tue Dec 15 03:11:05 2009 +0000
    
        afw/892:
         - removed new Box objects (will implement in a new ticket)
         - fixed up documentation a bit
         - finished implementing Point and Extent
    

    7ccf406e

    commit 7ccf406eabf8ad8f018a7d66cf517ddeaa94d9e1
    Author: jbosch 
    Date:   Mon Dec 14 19:43:59 2009 +0000
    
        afw/892:
         - implementations for geom (all but Box now done)
         - fixed compilation errors in ellipses and tests for ellipses
         - merged updates from trunk in (fixed an obvious typo introduced in math::offsetImage by the merge)
    

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    b449d4b3

    commit b449d4b3dd5e2b050d522b7c3990f50277096ef0
    Author: Jim Bosch 
    Date:   Fri Apr 3 18:17:10 2015 -0400
    
        Add conversion between Point and Extent as methods.
        
        Methods are much less verbose than the existing conversion constructors
        in Python.
    

    51a67dff

    commit 51a67dff1f2d5067d66ad025fe1efee37aeca339
    Author: Russell Owen 
    Date:   Tue Oct 14 12:50:44 2014 -0700
    
        Remove use of deprecated C++ keyword "register"
    

    Return to list

    src/table/io/FitsReader.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    #include 
                    
                    #include "boost/regex.hpp"
                    #include "boost/lexical_cast.hpp"
                    #include "boost/cstdint.hpp"
                    #include "boost/multi_index_container.hpp"
                    #include "boost/multi_index/sequenced_index.hpp"
                    #include "boost/multi_index/ordered_index.hpp"
                    #include "boost/multi_index/member.hpp"
                    #include "boost/math/special_functions/round.hpp"
                    
                    #include "lsst/afw/table/io/FitsReader.h"
                    #include "lsst/afw/table/BaseRecord.h"
                    #include "lsst/afw/table/BaseTable.h"
                    
                    namespace lsst { namespace afw { namespace table { namespace io {
                    
                    namespace {
                    
                    typedef FitsReader::Fits Fits;
                    
                    /*
                     *  This file contains most of the code for reading FITS binary tables.  There's also a little
                     *  in Source.cc, where we read the stuff that's specific to SourceTable/SourceRecord (footprints
                     *  and aliases).
                     */
                    
                    // ------------ FITS header to Schema implementation -------------------------------------------------------
                    
                    /*
                     *  We read FITS headers in two stages - first we read all the information we care about into
                     *  a temporary structure (FitsSchema) we can access more easily than a raw FITS header,
                     *  and then we iterate through that to fill the actual Schema object.
                     *
                     *  The driver code is at the bottom of this section; it's easier to understand if you start there
                     *  and work your way up.
                     */
                    
                    // A structure that describes a field as a bunch of strings read from the FITS header.
                    struct FitsSchemaItem {
                        int col;             // column number (0-indexed)
                        int bit;             // bit number for flag fields; -1 for others.
                        std::string name;    // name of the field (from TTYPE keys)
                        std::string units;   // field units (from TUNIT keys)
                        std::string doc;     // field docs (from comments on TTYPE keys)
                        std::string format;  // FITS column format code (from TFORM keys)
                        std::string cls;     // which field class to use (from our own TCCLS keys)
                    
                        // Add the field defined by the strings to a schema.
                        void addField(Schema & schema) const {
                            static boost::regex const regex("(\\d+)?([PQ])?(\\u)\\(?(\\d)*\\)?", boost::regex::perl);
                            // start by parsing the format; this tells the element type of the field and the number of elements
                            boost::smatch m;
                            if (!boost::regex_match(format, m, regex)) {
                                throw LSST_EXCEPT(
                                    afw::fits::FitsError,
                                    (boost::format("Could not parse TFORM value for field '%s': '%s'.") % name % format).str()
                                );
                            }
                            int size = 1;
                            if (m[1].matched) {
                                size = boost::lexical_cast(m[1].str());
                            }
                            char code = m[3].str()[0];
                            if (m[2].matched) {
                                // P or Q presence indicates a variable-length array, which we can get by just setting the
                                // size to zero and letting the rest of the logic run its course.
                                size = 0;
                            }
                            // switch code over FITS codes that correspond to different element types
                            switch (code) {
                            case 'I': // 16-bit integers - can only be scalars or Arrays (we assume they're unsigned, since
                                      // that's all we ever write, and CFITSIO will complain later if they aren't)
    
    76 e5abbc0c + if (size == 1) {
    76 c6e7f30d - if (size == 1 && cls != "Array") {
    ? ------------- -
    77 e5abbc0c + if (cls == "Array") {
    ? ++++ +
    78 e5abbc0c + schema.addField< Array >(name, doc, units, size);
    79 e5abbc0c + } else {
    77 c6e7f30d - schema.addField(name, doc, units);
    80 e5abbc0c + schema.addField(name, doc, units);
    ? ++++
    81 e5abbc0c + }
    } else { schema.addField< Array >(name, doc, units, size); } break; case 'J': // 32-bit integers - can only be scalars, Point fields, or Arrays if (size == 1) { if (cls == "Array") { schema.addField< Array >(name, doc, units, size); } else { schema.addField(name, doc, units); } } else if (size == 2) { if (cls == "Array") { schema.addField< Array >(name, doc, units, size); } else { schema.addField< Point >(name, doc, units); } } else { schema.addField< Array >(name, doc, units, size); } break; case 'K': // 64-bit integers - can only be scalars. if (size != 1) { throw LSST_EXCEPT( afw::fits::FitsError, (boost::format("Unsupported FITS column type: '%s'.") % format).str() ); } schema.addField(name, doc, units); break; case 'E': // floats and doubles can be any number of things; delegate to a separate function addFloatField(schema, size); break; case 'D': addFloatField(schema, size); break; case 'A': // strings schema.addField(name, doc, units, size); break; default: // We throw if we encounter a column type we can't handle. // This raises probem when we want to save footprints as variable length arrays // later, so we add the nCols argument to Reader::_readSchema to allow SourceFitsReader // to call FitsReader::_readSchema in a way that prevents it from ever getting here. throw LSST_EXCEPT( afw::fits::FitsError, (boost::format("Unsupported FITS column type: '%s'.") % format).str() ); } } // Add a field with a float or double element type to the schema. template void addFloatField(Schema & schema, int size) const { if (size == 1) { if (cls == "Angle") { schema.addField< Angle >(name, doc, units); } else if (cls == "Array") { schema.addField< Array >(name, doc, units, 1); } else if (cls == "Covariance") { schema.addField< Covariance >(name, doc, units, 1); } else { schema.addField(name, doc, units); } return; } else if (size == 2) { if (cls == "Point") { schema.addField< Point >(name, doc, units); return; } if (cls == "Coord") { schema.addField< Coord >(name, doc, units); return; } } else if (size == 3) { if (cls == "Moments") { schema.addField< Moments >(name, doc, units); return; } if (cls == "Covariance(Point)") { schema.addField< Covariance< Point > >(name, doc, units); return; } } else if (size == 6) { if (cls == "Covariance(Moments)") { schema.addField< Covariance< Moments > >(name, doc, units); return; } } if (cls == "Covariance") { double v = 0.5 * (std::sqrt(1 + 8 * size) - 1); int n = boost::math::iround(v); if (n * (n + 1) != size * 2) { throw LSST_EXCEPT( afw::fits::FitsError, "Covariance field has invalid size." ); } schema.addField< Covariance >(name, doc, units, n); } else { schema.addField< Array >(name, doc, units, size); } } FitsSchemaItem(int col_, int bit_) : col(col_), bit(bit_) {} }; // A quirk of Boost.MultiIndex (which we use for our container of FitsSchemaItems) // that you have to use a special functor (like this one) to set data members // in a container with set indices (because setting those values might require // the element to be moved to a different place in the set). Check out // the Boost.MultiIndex docs for more information. template struct SetFitsSchemaString { void operator()(FitsSchemaItem & item) { item.*Member = _v; } explicit SetFitsSchemaString(std::string const & v) : _v(v) {} private: std::string const & _v; }; // A container class (based on Boost.MultiIndex) that provides two sort orders, // on column number and on flag bit. This allows us to insert fields into the // schema in the correct order, regardless of which order they appear in the // FITS header. struct FitsSchema { typedef boost::multi_index_container< FitsSchemaItem, boost::multi_index::indexed_by< boost::multi_index::ordered_non_unique< boost::multi_index::member >, boost::multi_index::ordered_non_unique< boost::multi_index::member >, boost::multi_index::sequenced<> > > Container; // Typedefs for the special functors used to set data members. typedef SetFitsSchemaString<&FitsSchemaItem::name> SetName; typedef SetFitsSchemaString<&FitsSchemaItem::units> SetUnits; typedef SetFitsSchemaString<&FitsSchemaItem::doc> SetDoc; typedef SetFitsSchemaString<&FitsSchemaItem::format> SetFormat; typedef SetFitsSchemaString<&FitsSchemaItem::cls> SetCls; // Typedefs for the different indices. typedef Container::nth_index<0>::type ColSet; typedef Container::nth_index<1>::type BitSet; typedef Container::nth_index<2>::type List; // Getters for the different indices. ColSet & asColSet() { return container.get<0>(); } BitSet & asBitSet() { return container.get<1>(); } List & asList() { return container.get<2>(); } Container container; }; } // anonymous void FitsReader::_readSchema( Schema & schema, daf::base::PropertyList & metadata, bool stripMetadata ) {
    250 a5b331c9 +
    FitsSchema intermediate;
    252 f5c0126e + // Set the table version. If AFW_TABLE_VERSION tag exists, use that
    253 f5c0126e + // If not, set to 0 if it has an AFW_TYPE, Schema default otherwise (DM-590)
    254 f5c0126e + int version = 0;
    255 f5c0126e + if (!metadata.exists("AFW_TYPE")) {
    256 f5c0126e + version = lsst::afw::table::Schema::DEFAULT_VERSION;
    257 f5c0126e + }
    258 f5c0126e + version = metadata.get("AFW_TABLE_VERSION", version);
    259 bd692192 + schema.setVersion(version);
    260 bd692192 + if (stripMetadata && metadata.exists("AFW_TABLE_VERSION")) metadata.remove("AFW_TABLE_VERSION");
    int flagCol = metadata.get("FLAGCOL", 0); if (flagCol > 0) { metadata.remove("FLAGCOL"); metadata.remove((boost::format("TTYPE%d") % flagCol).str()); metadata.remove((boost::format("TFORM%d") % flagCol).str()); } --flagCol; // switch from 1-indexed to 0-indexed
    268 a5b331c9 +
    269 0c8edce7 + // read aliases stored in the new, expected way
    270 a5b331c9 + try {
    271 a5b331c9 + std::vector rawAliases = metadata.getArray("ALIAS");
    272 a5b331c9 + for (std::vector::const_iterator i = rawAliases.begin(); i != rawAliases.end(); ++i) {
    273 a5b331c9 + std::size_t pos = i->find_first_of(':');
    274 a5b331c9 + if (pos == std::string::npos) {
    275 a5b331c9 + throw LSST_EXCEPT(
    276 a5b331c9 + afw::fits::FitsError,
    277 a5b331c9 + (boost::format("Malformed alias definition: '%s'") % (*i)).str()
    278 a5b331c9 + );
    279 a5b331c9 + }
    280 a7452ce2 + schema.getAliasMap()->set(i->substr(0, pos), i->substr(pos+1, std::string::npos));
    281 a5b331c9 + }
    282 a5b331c9 + } catch (pex::exceptions::NotFoundError &) {
    283 a5b331c9 + // if there are no aliases, just move on
    284 a5b331c9 + }
    285 a5b331c9 + metadata.remove("ALIAS");
    286 a5b331c9 +
    287 0c8edce7 + if (schema.getVersion() == 0) {
    288 0c8edce7 + // Read slots saved using an old mechanism in as aliases, since the new slot mechanism delegates
    289 0c8edce7 + // slot definition to the AliasMap.
    290 0c8edce7 + static boost::array,6> oldSlotKeys = {
    291 0c8edce7 + {
    292 f05aa3ed + std::make_pair("PSF_FLUX", "slot.PsfFlux"),
    293 f05aa3ed + std::make_pair("AP_FLUX", "slot.ApFlux"),
    294 f05aa3ed + std::make_pair("INST_FLUX", "slot.InstFlux"),
    295 f05aa3ed + std::make_pair("MODEL_FLUX", "slot.ModelFlux"),
    296 f05aa3ed + std::make_pair("CENTROID", "slot.Centroid"),
    297 f05aa3ed + std::make_pair("SHAPE", "slot.Shape")
    298 0c8edce7 + }
    299 0c8edce7 + };
    300 0c8edce7 + for (std::size_t i = 0; i < oldSlotKeys.size(); ++i) {
    301 f05aa3ed + std::string target = metadata.get(oldSlotKeys[i].first + "_SLOT", std::string(""));
    302 7d46deaa + std::replace(target.begin(), target.end(), '_', '.');
    303 0c8edce7 + if (!target.empty()) {
    304 0c8edce7 + schema.getAliasMap()->set(oldSlotKeys[i].second, target);
    305 f05aa3ed + if (stripMetadata) {
    306 f05aa3ed + metadata.remove(oldSlotKeys[i].first);
    307 f05aa3ed + metadata.remove(oldSlotKeys[i].first + "_ERR_SLOT");
    308 f05aa3ed + metadata.remove(oldSlotKeys[i].first + "_FLAG_SLOT");
    309 f05aa3ed + }
    310 0c8edce7 + }
    311 0c8edce7 + }
    312 0c8edce7 + }
    313 0c8edce7 +
    std::vector keyList = metadata.getOrderedNames(); for (std::vector::const_iterator key = keyList.begin(); key != keyList.end(); ++key) { if (key->compare(0, 5, "TTYPE") == 0) { int col = boost::lexical_cast(key->substr(5)) - 1; FitsSchema::ColSet::iterator i = intermediate.asColSet().lower_bound(col); if (i == intermediate.asColSet().end() || i->col != col) { i = intermediate.asColSet().insert(i, FitsSchemaItem(col, -1)); } std::string v = metadata.get(*key);
    323 aa977b5e + if (version < 1) {
    263 5f0980b1 - std::replace(v.begin(), v.end(), '_', '.');
    324 aa977b5e + std::replace(v.begin(), v.end(), '_', '.');
    ? ++++
    325 aa977b5e + }
    intermediate.asColSet().modify(i, FitsSchema::SetName(v)); if (i->doc.empty()) // don't overwrite if already set with TDOCn intermediate.asColSet().modify(i, FitsSchema::SetDoc(metadata.getComment(*key))); if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TFLAG") == 0) { int bit = boost::lexical_cast(key->substr(5)) - 1; FitsSchema::BitSet::iterator i = intermediate.asBitSet().lower_bound(bit); if (i == intermediate.asBitSet().end() || i->bit != bit) { i = intermediate.asBitSet().insert(i, FitsSchemaItem(-1, bit)); } std::string v = metadata.get(*key);
    337 aa977b5e + if (version < 1) {
    275 5f0980b1 - std::replace(v.begin(), v.end(), '_', '.');
    338 aa977b5e + std::replace(v.begin(), v.end(), '_', '.');
    ? ++++
    339 aa977b5e + }
    intermediate.asBitSet().modify(i, FitsSchema::SetName(v)); if (i->doc.empty()) // don't overwrite if already set with TFDOCn intermediate.asBitSet().modify(i, FitsSchema::SetDoc(metadata.getComment(*key))); if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 4, "TDOC") == 0) { int col = boost::lexical_cast(key->substr(4)) - 1; FitsSchema::ColSet::iterator i = intermediate.asColSet().lower_bound(col); if (i == intermediate.asColSet().end() || i->col != col) { i = intermediate.asColSet().insert(i, FitsSchemaItem(col, -1)); } intermediate.asColSet().modify(i, FitsSchema::SetDoc(metadata.get(*key))); if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TFDOC") == 0) { int bit = boost::lexical_cast(key->substr(5)) - 1; FitsSchema::BitSet::iterator i = intermediate.asBitSet().lower_bound(bit); if (i == intermediate.asBitSet().end() || i->bit != bit) { i = intermediate.asBitSet().insert(i, FitsSchemaItem(-1, bit)); } intermediate.asBitSet().modify(i, FitsSchema::SetDoc(metadata.get(*key))); if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TUNIT") == 0) { int col = boost::lexical_cast(key->substr(5)) - 1; FitsSchema::ColSet::iterator i = intermediate.asColSet().lower_bound(col); if (i == intermediate.asColSet().end() || i->col != col) { i = intermediate.asColSet().insert(i, FitsSchemaItem(col, -1)); } intermediate.asColSet().modify(i, FitsSchema::SetUnits(metadata.get(*key))); if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TCCLS") == 0) { int col = boost::lexical_cast(key->substr(5)) - 1; FitsSchema::ColSet::iterator i = intermediate.asColSet().lower_bound(col); if (i == intermediate.asColSet().end() || i->col != col) { i = intermediate.asColSet().insert(i, FitsSchemaItem(col, -1)); } intermediate.asColSet().modify(i, FitsSchema::SetCls(metadata.get(*key))); if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TFORM") == 0) { int col = boost::lexical_cast(key->substr(5)) - 1; FitsSchema::ColSet::iterator i = intermediate.asColSet().lower_bound(col); if (i == intermediate.asColSet().end() || i->col != col) { i = intermediate.asColSet().insert(i, FitsSchemaItem(col, -1)); } intermediate.asColSet().modify(i, FitsSchema::SetFormat(metadata.get(*key))); if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TZERO") == 0) { if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TSCAL") == 0) { if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TNULL") == 0) { if (stripMetadata) metadata.remove(*key); } else if (key->compare(0, 5, "TDISP") == 0) { if (stripMetadata) metadata.remove(*key); } } for ( FitsSchema::List::const_iterator i = intermediate.asList().begin(); i != intermediate.asList().end(); ++i ) { if (i->bit >= 0) { schema.addField(i->name, i->doc); } else if (i->col != flagCol) { i->addField(schema); } } } void FitsReader::_startRecords(BaseTable & table) {
    409 bc5cccae +
    410 bc5cccae + PTR(daf::base::PropertyList) metadata = table.getMetadata();
    411 bc5cccae + // get the version number from the metadata. If the entry is not there, set to 0
    412 bc5cccae + // remove it from the metadata while the table is in memory
    413 bc5cccae + if (metadata) {
    414 c74dc9a8 + if (metadata->exists("AFW_TYPE")) metadata->remove("AFW_TYPE");
    415 bc5cccae + }
    416 bc5cccae +
    _row = -1; _nRows = _fits->countRows(); _processor = boost::make_shared(_fits, _row); table.preallocate(_nRows); } PTR(BaseTable) FitsReader::_readTable() { PTR(daf::base::PropertyList) metadata = boost::make_shared(); _fits->readMetadata(*metadata, true); Schema schema(*metadata, true); PTR(BaseTable) table = BaseTable::make(schema);
    428 813b4228 + table->setMetadata(metadata);
    _startRecords(*table);
    357 813b4228 - if (metadata->exists("AFW_TYPE")) metadata->remove("AFW_TYPE");
    358 813b4228 - table->setMetadata(metadata);
    return table; } // ------------ FITS records reading ------------------------------------------------------------------------ /* * Compared to reading the header, reading the records is pretty easy. We just * create a Schema::forEach functor (ProcessRecords) and have the schema use * it to iterate over all the fields for each record. We actually create that * object above, in _readSchema, and then call Schema::forEach in _readRecord. * * The driver code is at the bottom of this section; it's easier to understand if you start there * and work your way up. */ struct FitsReader::ProcessRecords { template void operator()(SchemaItem const & item) const { if (col == flagCol) ++col; fits->readTableArray(row, col, item.key.getElementCount(), record->getElement(item.key)); ++col; } template void operator()(SchemaItem< Array > const & item) const { if (col == flagCol) ++col; if (item.key.isVariableLength()) { int size = fits->getTableArraySize(row, col); ndarray::Array array = ndarray::allocate(size); fits->readTableArray(row, col, size, array.getData()); record->set(item.key, array); } else { fits->readTableArray(row, col, item.key.getElementCount(), record->getElement(item.key)); } ++col; } void operator()(SchemaItem const & item) const { if (col == flagCol) ++col; std::string s; fits->readTableScalar(row, col, s); record->set(item.key, s); ++col; } void operator()(SchemaItem const & item) const { assert(nFlags > 0); assert(flagCol >= 0); record->set(item.key, flags[bit]); ++bit; } void apply(Schema const & schema) { col = 0; bit = 0; if (flagCol >= 0) { fits->readTableArray(row, flagCol, nFlags, flags.get()); } schema.forEach(boost::ref(*this)); } ProcessRecords(Fits * fits_, std::size_t const & row_) : row(row_), col(0), bit(0), nFlags(0), flagCol(-1), fits(fits_) { fits->behavior &= ~ Fits::AUTO_CHECK; // temporarily disable automatic FITS exceptions fits->readKey("FLAGCOL", flagCol); if (fits->status == 0) { --flagCol; // we want 0-indexed column numbers, not FITS' 1-indexed numbers nFlags = fits->getTableArraySize(flagCol); if (nFlags) flags.reset(new bool[nFlags]); } else { fits->status = 0; flagCol = -1; } fits->behavior |= Fits::AUTO_CHECK; } std::size_t const & row; // this is a reference back to the _row data member in FitsReader mutable int col; // the current column (0-indexed) mutable int bit; // the current flag bit (in the FITS table, not the Schema) int nFlags; // the total number of flags int flagCol; // the column number (0-indexed) that holds all the flag bits Fits * fits; // the FITS file pointer boost::scoped_array flags; // space to hold a bool array of the flags to pass to cfitsio BaseRecord * record; // record to write values to }; PTR(BaseRecord) FitsReader::_readRecord(PTR(BaseTable) const & table) { PTR(BaseRecord) record; if (++_row == _nRows) return record; record = table->makeRecord(); _processor->record = record.get(); _processor->apply(table->getSchema()); return record; } // ------------ FitsReader Registry implementation ---------------------------------------------------------- namespace { typedef std::map Registry; Registry & getRegistry() { static Registry it; return it; } // here's an example of how you register a FitsReader static FitsReader::FactoryT baseReaderFactory("BASE"); } // anonymous FitsReader::Factory::Factory(std::string const & name) { getRegistry()[name] = this; } PTR(FitsReader) FitsReader::make(Fits * fits, PTR(io::InputArchive) archive, int flags) { std::string name; fits->behavior &= ~Fits::AUTO_CHECK; // temporarily disable automatic FITS exceptions fits->readKey("AFW_TYPE", name); if (fits->status != 0) { name = "BASE"; fits->status = 0; } fits->behavior |= Fits::AUTO_CHECK; Registry::iterator i = getRegistry().find(name); if (i == getRegistry().end()) { throw LSST_EXCEPT(
    488 d6480e01 - lsst::pex::exceptions::NotFoundException,
    ? ^^^^^^ ^
    559 21597d88 + lsst::pex::exceptions::NotFoundError,
    ? ^^ ^ (boost::format("FitsReader with name '%s' does not exist; check AFW_TYPE keyword.") % name).str() ); } return (*i->second)(fits, archive, flags); } }}}} // namespace lsst::afw::table::io

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    813b4228

    commit 813b4228386f4cd6e022b175cf9b3466d58b28a1
    Author: Jim Bosch 
    Date:   Wed Feb 8 22:41:54 2012 -0500
    
        added flexible metadata to BaseTable (read-only persistence so far)
    

    d6480e01

    commit d6480e01cf98ec6e6ebea9b7f58d2d9dcef6beef
    Author: Jim Bosch 
    Date:   Sun Feb 5 23:11:25 2012 -0500
    
        lots of documentation, and a little refactoring to improve readability
    

    c6e7f30d

    commit c6e7f30d3de1f7f388a298203bc540aac2930611
    Author: Jim Bosch 
    Date:   Mon Dec 1 14:24:24 2014 -0500
    
        Add support for uint16 scalars and arrays in afw::table
    

    5f0980b1

    commit 5f0980b13f25349d67fd8c160519ed0fe11450e7
    Author: Jim Bosch 
    Date:   Sun Jan 29 00:12:48 2012 -0500
    
        fixed period-handling bug in table FITS reading, added slot reading/writing in FITS
    

    Commits in /Users/nate/repos_lsst/afw/

    f05aa3ed

    commit f05aa3ed81bf92c5bfe281d4ab725c89ecf180aa
    Author: Jim Bosch 
    Date:   Mon Aug 25 15:42:54 2014 -0400
    
        Test, fix backwards compatibility for old slot persistence
    

    f5c0126e

    commit f5c0126ee21ec72bce6af997b2efe30a3a70feb0
    Author: Perry Gee 
    Date:   Fri Aug 29 11:31:17 2014 -0700
    
        fix comment in FitsReader.cc
    

    e5abbc0c

    commit e5abbc0c13a5849fe6401b05a5da5ff00b1cb5ca
    Author: Jim Bosch 
    Date:   Sat Nov 22 17:06:39 2014 -0500
    
        Add support for uint16 scalars and arrays in afw::table
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    a7452ce2

    commit a7452ce222551998eaff639f457528a35a31dd54
    Author: Jim Bosch 
    Date:   Thu Jul 10 11:36:08 2014 -0400
    
        Rename AliasMap accessors
    

    bc5cccae

    commit bc5cccaefd7b295975759bfd5213afb4e79a8f9e
    Author: Perry Gee 
    Date:   Mon Apr 14 12:45:10 2014 -0500
    
        Change to the _readTable routines in these 4 types plus BaseTable so that the
        AFW_TABLE_VERSION entry in the header is used to version each type of table.
        The getVersion() routine from BaseTable is used to get the version number during
        save, and it is written to the metadata of the table before the metadata is persisted.
        
        On read, the metadata is searched at the beginning of FitsReader::_startRecords,
        and the version number is set on the table then.  The table-getMetadata() is cleansed.
        I also moved the removal code for AFW_TYPE to here.
        
        Jim, please check the code to be sure that there are not unintended consquences from
        moving the table->setMetadata to the middle of the _readTable routines
    

    7d46deaa

    commit 7d46deaacfa50ece030d9884110aaba911e07d17
    Author: Jim Bosch 
    Date:   Fri Sep 5 20:34:51 2014 -0400
    
        Fix oversight in backwards compatibility for slots.
    

    0c8edce7

    commit 0c8edce7dfb2db4539497ac18187e75d2494f4e4
    Author: Jim Bosch 
    Date:   Mon Aug 25 01:48:39 2014 -0400
    
        Switch to new slot definition classes, using aliases for version>0
    

    bd692192

    commit bd692192367d33bb64a79ca008bff10eb9b41932
    Author: pgee 
    Date:   Mon Aug 18 15:06:04 2014 -0700
    
        Move API version number from BaseTable to Schema
        
        In FitsReader, move reading the AFW_TABLE_VERSION header key into the
        Schema-from-metadata constructor.
        In FitsWriter, use the version attached to the table schema to write the
        metadata.
    

    813b4228

    commit 813b4228386f4cd6e022b175cf9b3466d58b28a1
    Author: Jim Bosch 
    Date:   Wed Feb 8 22:41:54 2012 -0500
    
        added flexible metadata to BaseTable (read-only persistence so far)
    

    aa977b5e

    commit aa977b5e9cec2808c5751ba795da4ce21c066e7b
    Author: Jim Bosch 
    Date:   Sun Apr 20 10:44:26 2014 -0400
    
        Stop replacing periods with underscores in table I/O (DM-242)
    

    a5b331c9

    commit a5b331c97e6edf3d5c012f6d99dd1b39f494c9fa
    Author: Jim Bosch 
    Date:   Thu Jul 10 11:24:55 2014 -0400
    
        Add persistence for Schema aliases
    

    c74dc9a8

    commit c74dc9a8f70225a0785d93493bef18ccaaee7b6b
    Author: Perry Gee 
    Date:   Mon Apr 14 16:01:39 2014 -0500
    
        Move removal of AFW_TYPE tag to inside check that table->getMetadata() is not null
    

    Return to list

    tests/ticket2233.py

    Diff:

    1 249d34f8 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Sogo Mineo writes: ''' If I read Wcs from, e.g., the following file: master:/data1a/Subaru/SUPA/rerun/mineo-Abell1689/03430/W-S-I+/corr/wcs01098593.fits then Wcs::_nWcsInfo becomes 2. But WcsFormatter assumes that Wcs::_nWcsInfo is 1. When the stacking program tries bcasting Wcs: - In serializing Wcs, the value _nWcsInfo = 2 is recorded and so read in deserialization. - But in the deserialization, the formatter allocates only a single element of _wcsInfo. It causes inconsistency at the destructor, and SEGV arrises. ''' The example file above has been copied and is used in the below test. """ import os, os.path import unittest import pickle import lsst.afw.image as afwImage import lsst.utils.tests as utilsTests
    54 249d34f8 - import lsst.pex.exceptions.exceptionsLib as exceptions
    DATA = os.path.join("tests", "data", "ticket2233.fits") #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class WcsFormatterTest(unittest.TestCase): """Test the WCS formatter, by round-trip pickling.""" def setUp(self): exposure = afwImage.ExposureF(DATA) self.wcs = exposure.getWcs() def tearDown(self): del self.wcs def testFormat(self): dumped = pickle.dumps(self.wcs) wcs = pickle.loads(dumped) self.assertEqual(wcs.getFitsMetadata().toString(), self.wcs.getFitsMetadata().toString()) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(WcsFormatterTest) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    249d34f8

    commit 249d34f87b4b444ed90d2a2af0c5b9a9c6e5e460
    Author: Paul Price 
    Date:   Thu Jul 19 10:36:18 2012 +0900
    
        Squashed merge of tickets/2233 (fix pickling of Wcs and TanWcs): fixed SEGV in WcsFormatter, discovered that unpickled TanWcs (when used polymorphically as a Wcs) got sliced, pickle Wcs by dumping the header as a PropertySet to an archive and unpickle using makeWcs.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    src/formatters/KernelFormatter.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    
                    /** \file
                     * \brief Implementation of KernelFormatter class
                     *
                     * \version $Revision: 2151 $
                     * \date $Date$
                     *
                     * Contact: Kian-Tat Lim (ktl@slac.stanford.edu)
                     *
                     * \ingroup afw_math
                     */
                    
                    #ifndef __GNUC__
                    #  define __attribute__(x) /*NOTHING*/
                    #endif
                    static char const* SVNid __attribute__((unused)) =
                        "$Id$";
                    
                    #include "lsst/afw/formatters/KernelFormatter.h"
                    
                    #include 
                    #include 
                    #include 
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include 
                    
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/Function.h"
                    #include "lsst/afw/math/FunctionLibrary.h"
                    #include "lsst/daf/persistence/FormatterImpl.h"
                    #include "lsst/daf/persistence/LogicalLocation.h"
                    #include "lsst/daf/persistence/BoostStorage.h"
                    #include "lsst/daf/persistence/XmlStorage.h"
                    #include 
                    #include 
                    #include 
                    
                    
                    BOOST_CLASS_EXPORT(lsst::afw::math::Kernel)
                    BOOST_CLASS_EXPORT(lsst::afw::math::FixedKernel)
                    BOOST_CLASS_EXPORT(lsst::afw::math::AnalyticKernel)
                    BOOST_CLASS_EXPORT(lsst::afw::math::DeltaFunctionKernel)
                    BOOST_CLASS_EXPORT(lsst::afw::math::LinearCombinationKernel)
                    BOOST_CLASS_EXPORT(lsst::afw::math::SeparableKernel)
                    
                    BOOST_CLASS_EXPORT(lsst::afw::math::Function)
                    BOOST_CLASS_EXPORT(lsst::afw::math::NullFunction1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::NullFunction2)
                    
                    BOOST_CLASS_EXPORT(lsst::afw::math::Function)
                    BOOST_CLASS_EXPORT(lsst::afw::math::NullFunction1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::NullFunction2)
                    
                    BOOST_CLASS_EXPORT(lsst::afw::math::IntegerDeltaFunction2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::GaussianFunction1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::GaussianFunction2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::DoubleGaussianFunction2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::PolynomialFunction1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::PolynomialFunction2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::Chebyshev1Function1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::Chebyshev1Function2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::LanczosFunction1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::LanczosFunction2)
                    
                    BOOST_CLASS_EXPORT(lsst::afw::math::IntegerDeltaFunction2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::GaussianFunction1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::GaussianFunction2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::DoubleGaussianFunction2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::PolynomialFunction1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::PolynomialFunction2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::Chebyshev1Function1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::Chebyshev1Function2)
                    BOOST_CLASS_EXPORT(lsst::afw::math::LanczosFunction1)
                    BOOST_CLASS_EXPORT(lsst::afw::math::LanczosFunction2)
                    
                    #define EXEC_TRACE  20
                    static void execTrace(std::string s, int level = EXEC_TRACE) {
                        lsst::pex::logging::Trace("afw.math.KernelFormatter", level, s);
                    }
                    
                    namespace afwMath = lsst::afw::math;
                    namespace afwForm = lsst::afw::formatters;
                    namespace dafBase = lsst::daf::base;
                    namespace dafPersist = lsst::daf::persistence;
                    namespace pexPolicy = lsst::pex::policy;
                    
                    using boost::serialization::make_nvp;
                    
                    /** Register this Formatter subclass through a static instance of
                     * FormatterRegistration.
                     */
                    dafPersist::FormatterRegistration
                    afwForm::KernelFormatter::kernelRegistration(
                        "Kernel", typeid(afwMath::Kernel), createInstance);
                    dafPersist::FormatterRegistration
                    afwForm::KernelFormatter::fixedKernelRegistration(
                        "FixedKernel", typeid(afwMath::FixedKernel), createInstance);
                    dafPersist::FormatterRegistration
                    afwForm::KernelFormatter::analyticKernelRegistration(
                        "AnalyticKernel", typeid(afwMath::AnalyticKernel), createInstance);
                    dafPersist::FormatterRegistration
                    afwForm::KernelFormatter::deltaFunctionKernelRegistration(
                        "DeltaFunctionKernel", typeid(afwMath::DeltaFunctionKernel),
                        createInstance);
                    dafPersist::FormatterRegistration
                    afwForm::KernelFormatter::linearCombinationKernelRegistration(
                        "LinearCombinationKernel", typeid(afwMath::LinearCombinationKernel),
                        createInstance);
                    dafPersist::FormatterRegistration
                    afwForm::KernelFormatter::separableKernelRegistration(
                        "SeparableKernel", typeid(afwMath::SeparableKernel), createInstance);
                    
                    /** Constructor.
                     * \param[in] policy Policy for configuring this Formatter
                     */
                    afwForm::KernelFormatter::KernelFormatter(
                        pexPolicy::Policy::Ptr policy) :
                        dafPersist::Formatter(typeid(this)), _policy(policy) {
                    }
                    
                    /** Minimal destructor.
                     */
                    afwForm::KernelFormatter::~KernelFormatter(void) {
                    }
                    
                    void afwForm::KernelFormatter::write(
                        dafBase::Persistable const* persistable,
                        dafPersist::Storage::Ptr storage,
                        dafBase::PropertySet::Ptr) {
                        execTrace("KernelFormatter write start");
                        afwMath::Kernel const* kp =
                            dynamic_cast(persistable);
                        if (kp == 0) {
    
    168 47a633de - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Persisting non-Kernel");
    ? ---------
    168 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Persisting non-Kernel");
    } if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { execTrace("KernelFormatter write BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getOArchive() & kp; execTrace("KernelFormatter write end"); return; } else if (typeid(*storage) == typeid(dafPersist::XmlStorage)) { execTrace("KernelFormatter write XmlStorage"); dafPersist::XmlStorage* xml = dynamic_cast(storage.get()); xml->getOArchive() & make_nvp("ptr", kp); execTrace("KernelFormatter write end"); return; }
    186 47a633de - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Kernel");
    ? ---------
    186 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Kernel");
    } dafBase::Persistable* afwForm::KernelFormatter::read( dafPersist::Storage::Ptr storage, dafBase::PropertySet::Ptr) { execTrace("KernelFormatter read start"); afwMath::Kernel* kp; if (typeid(*storage) == typeid(dafPersist::BoostStorage)) { execTrace("KernelFormatter read BoostStorage"); dafPersist::BoostStorage* boost = dynamic_cast(storage.get()); boost->getIArchive() & kp; execTrace("KernelFormatter read end"); return kp; } else if (typeid(*storage) == typeid(dafPersist::XmlStorage)) { execTrace("KernelFormatter read XmlStorage"); dafPersist::XmlStorage* xml = dynamic_cast(storage.get()); xml->getIArchive() & make_nvp("ptr", kp); execTrace("KernelFormatter read end"); return kp; }
    209 47a633de - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unrecognized Storage for Kernel");
    ? ---------
    209 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unrecognized Storage for Kernel");
    } void afwForm::KernelFormatter::update(dafBase::Persistable*, dafPersist::Storage::Ptr, dafBase::PropertySet::Ptr) {
    215 47a633de - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Unexpected call to update for Kernel");
    ? ---------
    215 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unexpected call to update for Kernel");
    } /** Serialize a Kernel to a Boost archive. Handles text or XML * archives, input or output. * \param[in,out] ar Boost archive * \param[in] version Version of the Kernel class * \param[in,out] persistable Pointer to the Kernel as a Persistable */ template void afwForm::KernelFormatter::delegateSerialize( Archive& ar, unsigned int const, dafBase::Persistable* persistable) { execTrace("KernelFormatter delegateSerialize start"); afwMath::Kernel* kp = dynamic_cast(persistable); if (kp == 0) {
    231 47a633de - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "Serializing non-Kernel");
    ? ---------
    231 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Serializing non-Kernel");
    } ar & make_nvp("base", boost::serialization::base_object(*kp)); ar & make_nvp("width", kp->_width); ar & make_nvp("height", kp->_height); ar & make_nvp("ctrX", kp->_ctrX); ar & make_nvp("ctrY", kp->_ctrY); ar & make_nvp("nParams", kp->_nKernelParams); ar & make_nvp("spatialFunctionList", kp->_spatialFunctionList); execTrace("KernelFormatter delegateSerialize end"); } template void afwForm::KernelFormatter::delegateSerialize( boost::archive::text_oarchive& ar, unsigned int const, dafBase::Persistable*); template void afwForm::KernelFormatter::delegateSerialize( boost::archive::text_iarchive& ar, unsigned int const, dafBase::Persistable*); template void afwForm::KernelFormatter::delegateSerialize( boost::archive::xml_oarchive& ar, unsigned int const, dafBase::Persistable*); template void afwForm::KernelFormatter::delegateSerialize( boost::archive::xml_iarchive& ar, unsigned int const, dafBase::Persistable*); template void afwForm::KernelFormatter::delegateSerialize( boost::archive::binary_oarchive& ar, unsigned int const, dafBase::Persistable*); template void afwForm::KernelFormatter::delegateSerialize( boost::archive::binary_iarchive& ar, unsigned int const, dafBase::Persistable*); /** Factory method for KernelFormatter. * \param[in] policy Policy for configuring the KernelFormatter * \return Shared pointer to a new instance */ dafPersist::Formatter::Ptr afwForm::KernelFormatter::createInstance( pexPolicy::Policy::Ptr policy) { return dafPersist::Formatter::Ptr(new afwForm::KernelFormatter(policy)); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    47a633de

    commit 47a633de7b0dbe1ab8a1496cd5c09e6bb6e4435a
    Author: ktlim 
    Date:   Thu Mar 5 15:15:43 2009 +0000
    
        Major update for persistence of Kernels and Functions.
        
         * Add test cases for Kernel (and indirectly Function) persistence.
         * Make Kernel a Persistable.
         * Include %lsst_persistable() invocation for all Kernel types.
         * Move KernelFormatter from lsst::afw::math to lsst::afw::formatters.
         * Add registrations for Kernel subclasses (using same Formatter).
         * Make SConscript for lib and tests more generic.
         * Add boost::serialization::void_cast_register for non-default-constructor subclasses.
         * Template Function save_construct_data friends properly.
         * Move BOOST_CLASS_EXPORT invocations to Formatter.
         * Fix DeltaFunctionKernel save/load_construct_data.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/statistics.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    #include 
                    
                    #define BOOST_TEST_DYN_LINK
                    #define BOOST_TEST_MODULE Statistics
                    
                    #pragma clang diagnostic push
                    #pragma clang diagnostic ignored "-Wunused-variable"
                    #include "boost/test/unit_test.hpp"
                    #pragma clang diagnostic pop
                    #include "boost/test/floating_point_comparison.hpp"
                    
    
    38 a9aec7fc + #include "lsst/utils/Utils.h"
    39 a9aec7fc + #include "lsst/pex/exceptions.h"
    #include "lsst/afw/image/Image.h" #include "lsst/afw/math/Statistics.h" #include "lsst/utils/ieee.h" using namespace std; namespace image = lsst::afw::image; namespace math = lsst::afw::math; namespace geom = lsst::afw::geom; typedef image::Image Image; typedef image::DecoratedImage DecoratedImage; BOOST_AUTO_TEST_CASE(StatisticsBasic) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ Image img(geom::Extent2I(10, 40)); Image::Pixel const pixval = 10000; img = pixval; { math::Statistics stats = math::makeStatistics(img, math::NPOINT | math::STDEV | math::MEAN); double const mean = stats.getValue(math::MEAN); double const dmean = stats.getError(math::MEAN); double const sd = stats.getValue(math::STDEV); BOOST_CHECK_EQUAL(stats.getValue(math::NPOINT), img.getWidth()*img.getHeight()); BOOST_CHECK_EQUAL(mean, img(0, 0)); BOOST_CHECK(lsst::utils::isnan(dmean)); // we didn't ask for the error, so it's a NaN BOOST_CHECK_EQUAL(sd, 0); } { math::Statistics stats = math::makeStatistics(img, math::STDEV | math::MEAN | math::ERRORS); std::pair const mean = stats.getResult(math::MEAN); double const sd = stats.getValue(math::STDEV); BOOST_CHECK_EQUAL(mean.first, img(0, 0)); BOOST_CHECK_EQUAL(mean.second, sd/sqrt(img.getWidth()*img.getHeight())); } { math::Statistics stats = math::makeStatistics(img, math::NPOINT);
    79 3771b5eb - BOOST_CHECK_THROW(stats.getValue(math::MEAN), lsst::pex::exceptions::InvalidParameterException);
    ? ^^^^^^ ^
    81 21597d88 + BOOST_CHECK_THROW(stats.getValue(math::MEAN), lsst::pex::exceptions::InvalidParameterError);
    ? ^^ ^ } // =============================================================================== // sjb code for percentiles and clipped stats { math::Statistics stats = math::makeStatistics(img, math::MEDIAN); BOOST_CHECK_EQUAL(pixval, stats.getValue(math::MEDIAN)); } { math::Statistics stats = math::makeStatistics(img, math::IQRANGE); BOOST_CHECK_EQUAL(0.0, stats.getValue(math::IQRANGE)); } { math::Statistics stats = math::makeStatistics(img, math::MEANCLIP); BOOST_CHECK_EQUAL(pixval, stats.getValue(math::MEANCLIP)); } { math::Statistics stats = math::makeStatistics(img, math::VARIANCECLIP); BOOST_CHECK_EQUAL(0.0, stats.getValue(math::VARIANCECLIP)); } { Image img2(img); // // Add 1 to every other row, so the variance is 1/4 // BOOST_REQUIRE(img.getHeight()%2 == 0); for (int y = 1; y < img.getHeight(); y += 2) { for (Image::x_iterator ptr = img.row_begin(y), end = ptr + img.getWidth(); ptr != end; ++ptr) { *ptr += 1; } } math::Statistics stats = math::makeStatistics(img2, math::NPOINT | math::STDEV | math::MEAN | math::ERRORS); std::pair const mean = stats.getResult(math::MEAN); double const n = stats.getValue(math::NPOINT); double const sd = stats.getValue(math::STDEV); BOOST_CHECK_EQUAL(mean.first, img(0, 0) + 0.5); BOOST_CHECK_EQUAL(sd, 1/sqrt(4.0)*sqrt(n/(n - 1))); BOOST_CHECK_CLOSE(mean.second, sd/sqrt(img.getWidth()*img.getHeight()), 1e-10); } } BOOST_AUTO_TEST_CASE(StatisticsRamp) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ int nx = 101; int ny = 64; Image img(geom::Extent2I(nx, ny)); double z0 = 10.0; double dzdx = 1.0; double mean = z0 + (nx/2)*dzdx; double stdev = 0.0; for (int iY = 0; iY < ny; ++iY) { double x = 0; for (Image::x_iterator ptr = img.row_begin(iY); ptr != img.row_end(iY); ++ptr) { *ptr = z0 + dzdx*x; x += 1.0; stdev += (*ptr - mean)*(*ptr - mean); } } stdev = sqrt(stdev/(nx*ny - 1)); { math::Statistics stats = math::makeStatistics(img, math::NPOINT | math::STDEV | math::MEAN); double const testmean = stats.getValue(math::MEAN); double const teststdev = stats.getValue(math::STDEV); BOOST_CHECK_EQUAL(stats.getValue(math::NPOINT), nx*ny); BOOST_CHECK_EQUAL(testmean, mean); BOOST_CHECK_CLOSE(teststdev, stdev, 1e-9); } { math::Statistics stats = math::makeStatistics(img, math::STDEV | math::MEAN | math::ERRORS); std::pair const mean_meanErr = stats.getResult(math::MEAN); double const sd = stats.getValue(math::STDEV); BOOST_CHECK_EQUAL(mean_meanErr.first, img(nx/2, ny/2)); BOOST_CHECK_EQUAL(mean_meanErr.second, sd/sqrt(img.getWidth()*img.getHeight())); } // =============================================================================== // sjb code for percentiles and clipped stats { math::Statistics stats = math::makeStatistics(img, math::MEDIAN); BOOST_CHECK_EQUAL(z0 + dzdx*(nx - 1)/2.0, stats.getValue(math::MEDIAN)); } { math::Statistics stats = math::makeStatistics(img, math::IQRANGE); BOOST_CHECK_EQUAL(dzdx*(nx - 1)/2.0, stats.getValue(math::IQRANGE)); } { math::Statistics stats = math::makeStatistics(img, math::MEANCLIP); BOOST_CHECK_EQUAL(z0 + dzdx*(nx - 1)/2.0, stats.getValue(math::MEANCLIP)); } //{ // math::Statistics stats = math::makeStatistics(img, math::VARIANCECLIP); // BOOST_CHECK_EQUAL(0.0, stats.getValue(math::VARIANCECLIP)); //} } BOOST_AUTO_TEST_CASE(StatisticsTestAllNanButOne) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ /* * The mean/stddev/min/max are computed in a single pass, but there's a pre-pass * to get a crude mean with a stride of 10. If there are no valid points * in the pre-pass, 'crude_mean' is set to zero, and min/max are initialized * to +/- MaxDouble. * This test verifies that when the only valid numbers present aren't on a 10-stride, * the mean,min,max are set correctly. * The problem was apparent when parasoft found a possible div-by-zero error * for crude_mean = sum/n with no valid points. */ double const NaN = std::numeric_limits::quiet_NaN(); int nx = 101; int ny = 64; Image img(geom::Extent2I(nx, ny)); img = NaN; double z0 = 10.0; // set two pixels to non-nan ... neither on stride 10 img(4, 4) = z0; img(3, 3) = z0 + 1.0; double const mean = z0 + 0.5; double const stdev = std::sqrt( (0.5*0.5 + 0.5*0.5)/(2.0 - 1.0) ); double const min = z0; double const max = z0 + 1.0; { math::Statistics stats = math::makeStatistics(img, math::NPOINT | math::STDEV | math::MEAN | math::MIN | math::MAX); double const testmean = stats.getValue(math::MEAN); double const teststdev = stats.getValue(math::STDEV); double const testmin = stats.getValue(math::MIN); double const testmax = stats.getValue(math::MAX); BOOST_CHECK_EQUAL(stats.getValue(math::NPOINT), 2); BOOST_CHECK_EQUAL(testmean, mean); BOOST_CHECK_EQUAL(teststdev, stdev ); BOOST_CHECK_EQUAL(testmin, min); BOOST_CHECK_EQUAL(testmax, max); } } BOOST_AUTO_TEST_CASE(StatisticsTestImages) { /* parasoft-suppress LsstDm-3-2a LsstDm-3-4a LsstDm-4-6 LsstDm-5-25 "Boost non-Std" */ /* ============================================================================= * Tests of mean and standard deviation for Russ Laher's noise images. * - only one for now (time consuming) */ { vector imgfiles; imgfiles.push_back("v1_i1_g_m400_s20_f.fits"); imgfiles.push_back("v1_i1_g_m400_s20_u16.fits"); imgfiles.push_back("v1_i2_g_m400_s20_f.fits"); imgfiles.push_back("v1_i2_g_m400_s20_u16.fits"); imgfiles.push_back("v2_i1_p_m9_f.fits"); imgfiles.push_back("v2_i1_p_m9_u16.fits"); imgfiles.push_back("v2_i2_p_m9_f.fits"); imgfiles.push_back("v2_i2_p_m9_u16.fits");
    263 ff0c8fc4 - string afwdata_dir = getenv("AFWDATA_DIR");
    265 a9aec7fc + std::string afwdata_dir;
    266 a9aec7fc + try {
    267 7cbb2bb9 + afwdata_dir = lsst::utils::getPackageDir("afwdata");
    268 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    269 a9aec7fc + std::cout << "Warning: test skipped because afwdata is not setup" << std::endl;
    270 a9aec7fc + return;
    271 a9aec7fc + }
    for (vector::iterator imgfile = imgfiles.begin(); imgfile != imgfiles.end(); ++imgfile) { string img_path = afwdata_dir + "/Statistics/" + *imgfile; // get the image and header DecoratedImage dimg(img_path); lsst::daf::base::PropertySet::Ptr fitsHdr = dimg.getMetadata(); // the FITS header // get the true values of the mean and stdev double const trueMean = fitsHdr->getAsDouble("MEANCOMP"); double const trueStdev = fitsHdr->getAsDouble("SIGCOMP"); // measure the mean and stdev with the Statistics class Image::Ptr img = dimg.getImage(); math::Statistics statobj = math::makeStatistics(*img, math::MEAN | math::STDEV); //int n = img->getWidth() * img->getHeight(); //double sampleToPop = 1.0; //sqrt( n/static_cast(n - 1) ); double const mean = statobj.getValue(math::MEAN); double const stdev = statobj.getValue(math::STDEV); BOOST_CHECK_CLOSE(mean, trueMean, 1e-8); BOOST_CHECK_CLOSE(stdev, trueStdev, 1e-8); } } }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ff0c8fc4

    commit ff0c8fc4d3fb8d3e18c90ccf5d5efac743619b4a
    Author: bick 
    Date:   Wed Jan 14 16:50:33 2009 +0000
    
        Merging ticket 395 (image statistics and background estimation) on to trunk.
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    tests/testMakeWcs.py

    Diff:

    1 5de7a2ad - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . #
    25 5de7a2ad - import os
    26 5de7a2ad - import math
    27 5de7a2ad - import pdb # we may want to say pdb.set_trace()
    import unittest
    30 5de7a2ad - import eups
    import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.afw.coord as afwCoord import lsst.utils.tests as utilsTests
    35 5de7a2ad - import lsst.afw.display.ds9 as ds9
    36 5de7a2ad - import lsst.pex.exceptions.exceptionsLib as exceptions
    import lsst.daf.base as dafBase import lsst try: type(verbose) except NameError: verbose = 0 class MakeWcsTestCase(unittest.TestCase): """Test that makeWcs correctly returns a Wcs or TanWcs object as appropriate based on the contents of a fits header """ def setUp(self): #metadata taken from CFHT data #v695856-e0/v695856-e0-c000-a00.sci_img.fits self.metadata = dafBase.PropertySet() self.metadata.set("SIMPLE", "T") self.metadata.set("BITPIX", -32) self.metadata.set("NAXIS", 2) self.metadata.set("NAXIS1", 1024) self.metadata.set("NAXIS2", 1153) self.metadata.set("RADECSYS", 'FK5') self.metadata.set("EQUINOX", 2000.) self.metadata.setDouble("CRVAL1", 215.604025685476) self.metadata.setDouble("CRVAL2", 53.1595451514076) self.metadata.setDouble("CRPIX1", 1109.99981456774) self.metadata.setDouble("CRPIX2", 560.018167811613) self.metadata.set("CTYPE1", 'RA---SIN') self.metadata.set("CTYPE2", 'DEC--SIN') self.metadata.setDouble("CD1_1", 5.10808596133527E-05) self.metadata.setDouble("CD1_2", 1.85579539217196E-07) self.metadata.setDouble("CD2_2", -5.10281493481982E-05) self.metadata.setDouble("CD2_1", -8.27440751733828E-07) def tearDown(self): del self.metadata def testCreateBaseWcs(self): """Check that a non-TAN projection in the header creates a base Wcs object""" wcs = afwImage.makeWcs(self.metadata) strRepresentation = str(wcs) self.assertNotEqual( strRepresentation.find("image::Wcs"), -1, "non Wcs object returned") def testNoCreateTanWcs(self): """Test than an exception is thrown if we try to upcast to a TanWcs inappropriately""" wcs = afwImage.makeWcs(self.metadata)
    94 93ce91ea - excpt = lsst.pex.exceptions.exceptionsLib.LsstCppException
    ? ---------------------
    89 6fc1c3d1 + excpt = lsst.pex.exceptions.Exception
    self.assertRaises(excpt, afwImage.cast_TanWcs, wcs) def testCreateTanWcs(self): """Check that a non-TAN projection in the header creates a base Wcs object""" self.metadata.set("CTYPE1", "RA---TAN") self.metadata.set("CTYPE2", "DEC--TAN") wcs0 = afwImage.makeWcs(self.metadata) wcs = afwImage.cast_TanWcs(afwImage.makeWcs(self.metadata)) strRepresentation = str(wcs) self.assertNotEqual( strRepresentation.find("image::TanWcs"), -1, "non TanWcs object returned") def testCreateTanSipWcs(self): self.metadata.set("CTYPE1", "RA---TAN") self.metadata.set("CTYPE2", "DEC--TAN") wcs = afwImage.cast_TanWcs(afwImage.makeWcs(self.metadata)) strRepresentation = str(wcs) self.assertNotEqual( strRepresentation.find("image::TanWcs"), -1, "non TanWcs object returned") def testPythonLevelMakeWcs(self): """Verify that we can make a Wcs by providing the CD matrix elements in python.""" m = self.metadata crval = afwCoord.makeCoord(afwCoord.ICRS, m.getDouble("CRVAL1") * afwGeom.degrees, m.getDouble("CRVAL2") * afwGeom.degrees) crpix = afwGeom.Point2D(m.getDouble("CRPIX1"), m.getDouble("CRPIX2")) cd11, cd12 = m.getDouble("CD1_1"), m.getDouble("CD1_2") cd21, cd22 = m.getDouble("CD2_1"), m.getDouble("CD2_2") print 'CRVAL:', crval # this is defined at the c++ level in src/image/makeWcs.cc wcsMade = afwImage.makeWcs(crval, crpix, cd11, cd12, cd21, cd22) # trivial test ... verify that we get back what we put in. for wcs in [wcsMade]: crvalTest = wcs.getSkyOrigin().getPosition(afwGeom.degrees) crpixTest = wcs.getPixelOrigin() CD = wcs.getCDMatrix() self.assertAlmostEqual(crvalTest[0], crval.getLongitude().asDegrees()) self.assertAlmostEqual(crvalTest[1], crval.getLatitude().asDegrees()) self.assertAlmostEqual(crpixTest[0], crpix[0]) self.assertAlmostEqual(crpixTest[1], crpix[1]) self.assertAlmostEqual(CD[0,0], cd11) self.assertAlmostEqual(CD[0,1], cd12) self.assertAlmostEqual(CD[1,0], cd21) self.assertAlmostEqual(CD[1,1], cd22) def testReadDESHeader(self): """Verify that we can read a DES header""" self.metadata.set("RADESYS", "FK5 ") # note trailing white space self.metadata.set("CTYPE1", 'RA---TPV') self.metadata.set("CTYPE2", 'DEC--TPV') afwImage.makeWcs(self.metadata) ##### def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(MakeWcsTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    5de7a2ad

    commit 5de7a2ad1f776e6c5584f1a7a0cd2b49b2da0a7c
    Author: fergal 
    Date:   Fri Mar 12 18:02:04 2010 +0000
    
        Test that makeWcs returns a TanWcs when appropriate.
    

    93ce91ea

    commit 93ce91ea31745314de0fdfefbc008a40e43e8204
    Author: fergal 
    Date:   Fri Mar 12 18:06:41 2010 +0000
    
        Added test that incorrectly upcasting a Wcs throws an exception
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    src/math/BackgroundMI.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    /**
                     * @file Background.cc
                     * @ingroup afw
                     * @brief Background estimation class code
                     * @author Steve Bickerton
                     * @date Jan 26, 2009
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    #include "lsst/utils/ieee.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/Interpolate.h"
                    #include "lsst/afw/math/Approximate.h"
                    #include "lsst/afw/math/Background.h"
                    #include "lsst/afw/math/Statistics.h"
                    
                    namespace lsst {
                    namespace ex = pex::exceptions;
                    
                    namespace afw {
                    namespace math {
                    
                    namespace {
                    
                        // Given two vectors x and y, with some nans in y we want vectors x' and y' that correspond to the data
                        // without the nans basic idea is that 'x' is the values, and 'y' is the ref (where nan checking happens)
                        //    cullNan(x, y, x', y')
                        void cullNan(std::vector const &values, std::vector const &refs,
                                     std::vector &culledValues, std::vector &culledRefs,
                                     double const defaultValue=std::numeric_limits::quiet_NaN()
                                    ) {
                            if (culledValues.capacity() == 0) {
                                culledValues.reserve(refs.size());
                            } else {
                                culledValues.clear();
                            }
                            if (culledRefs.capacity() == 0) {
                                culledRefs.reserve(refs.size());
                            } else {
                                culledRefs.clear();
                            }
                    
                            bool const haveDefault = !lsst::utils::isnan(defaultValue);
                    
                            for (std::vector::const_iterator pVal = values.begin(), pRef = refs.begin();
                                 pRef != refs.end(); ++pRef, ++pVal) {
                                if (!lsst::utils::isnan(*pRef)) {
                                    culledValues.push_back(*pVal);
                                    culledRefs.push_back(*pRef);
                                } else if(haveDefault) {
                                    culledValues.push_back(*pVal);
                                    culledRefs.push_back(defaultValue);
                                } else {
                                    ;                       // drop a NaN
                                }
                            }
                        }
                    }
                    
                    /**
                     * @brief Constructor for BackgroundMI
                     *
                     * Estimate the statistical properties of the Image in a grid of cells;  we'll later call
                     * getImage() to interpolate those values, creating an image the same size as the original
                     *
                     * \note If there are heavily masked or Nan regions in the image we may not be able to estimate
                     * all the cells in the "statsImage".  Interpolation will still work, but if you want to prevent
                     * the code wildly extrapolating, it may be better to set the values directly; e.g.
                     * \code
                     * defaultValue = 10
                     * statsImage = afwMath.cast_BackgroundMI(bkgd).getStatsImage()
                     * sim = statsImage.getImage().getArray()
                     * sim[np.isnan(sim)] = defaultValue # replace NaN by defaultValue
                     * bkgdImage = bkgd.getImageF(afwMath.Interpolate.NATURAL_SPLINE, afwMath.REDUCE_INTERP_ORDER)
                     * \endcode
                     * There is a ticket (#2825) to allow getImage to specify a default value to use when interpolation fails
                     *
                     * \deprecated The old and deprecated API specified the interpolation style as part of the BackgroundControl
                     * object passed to this ctor.  This is still supported, but the work isn't done until the getImage()
                     * method is called
                     */
                    template
                    BackgroundMI::BackgroundMI(ImageT const& img, ///< ImageT (or MaskedImage) whose properties we want
                                                 BackgroundControl const& bgCtrl ///< Control how the BackgroundMI is estimated
                                                ) :
                        Background(img, bgCtrl), _statsImage(image::MaskedImage())
                    {
                        // =============================================================
                        // Loop over the cells in the image, computing statistical properties
                        // of each cell in turn and using them to set _statsImage
                        int const nxSample = bgCtrl.getNxSample();
                        int const nySample = bgCtrl.getNySample();
                        _statsImage = image::MaskedImage(nxSample, nySample);
                    
                        image::MaskedImage::Image &im = *_statsImage.getImage();
                        image::MaskedImage::Variance &var = *_statsImage.getVariance();
                    
                        for (int iX = 0; iX < nxSample; ++iX) {
                            for (int iY = 0; iY < nySample; ++iY) {
                                ImageT subimg = ImageT(img, geom::Box2I(geom::Point2I(_xorig[iX], _yorig[iY]),
                                                                        geom::Extent2I(_xsize[iX], _ysize[iY])), image::LOCAL);
                                
                                std::pair res = makeStatistics(subimg, bgCtrl.getStatisticsProperty() | ERRORS,
                                                                               *bgCtrl.getStatisticsControl()).getResult();
                                im(iX, iY) = res.first;
                                var(iX, iY) = res.second;
                            }
                        }
                    }
                    /**
                     * Recreate a BackgroundMI from the statsImage and the original Image's BBox
                     */
                    BackgroundMI::BackgroundMI(geom::Box2I const imageBBox,                         ///< unbinned Image's BBox
                                               image::MaskedImage const& statsImage ///< Internal stats image
                                              ) :
                        Background(imageBBox, statsImage.getWidth(), statsImage.getHeight()),
                        _statsImage(statsImage)
                    {
                    }
                    
                    void BackgroundMI::_setGridColumns(Interpolate::Style const interpStyle,
                                                       UndersampleStyle const undersampleStyle,
                                                       int const iX, std::vector const& ypix) const
                    {
                        image::MaskedImage::Image &im = *_statsImage.getImage();
                    
                        int const height = _imgBBox.getHeight();
                        _gridColumns[iX].resize(height);
                    
                        // Set _grid as a transitional measure
                        std::vector _grid(_statsImage.getHeight());
                        std::copy(im.col_begin(iX), im.col_end(iX), _grid.begin());
                        
                        // remove nan from the grid values before computing columns
                        // if we do it here (ie. in _setGridColumns), it should
                        // take care of all future occurrences, so we don't need to do this elsewhere
                        std::vector ycenTmp, gridTmp;
                        cullNan(_ycen, _grid, ycenTmp, gridTmp);
                        
                        PTR(Interpolate) intobj;
                        try {
                            intobj = makeInterpolate(ycenTmp, gridTmp, interpStyle);
    
    169 654709ea - } catch(pex::exceptions::OutOfRangeException &e) {
    ? ^^^^^^ ^
    169 21597d88 + } catch(pex::exceptions::OutOfRangeError &e) {
    ? ^^ ^ switch (undersampleStyle) { case THROW_EXCEPTION: LSST_EXCEPT_ADD(e, "setting _gridcolumns"); throw; case REDUCE_INTERP_ORDER: { if (gridTmp.empty()) { // Set the column to NaN. We'll deal with this properly when interpolating in x ycenTmp.push_back(0); gridTmp.push_back(std::numeric_limits::quiet_NaN()); intobj = makeInterpolate(ycenTmp, gridTmp, Interpolate::CONSTANT); break; } else { return _setGridColumns(lookupMaxInterpStyle(gridTmp.size()), undersampleStyle, iX, ypix); } } case INCREASE_NXNYSAMPLE: LSST_EXCEPT_ADD(e, "The BackgroundControl UndersampleStyle INCREASE_NXNYSAMPLE is not supported."); throw; default: LSST_EXCEPT_ADD(e, str(boost::format("The selected BackgroundControl " "UndersampleStyle %d is not defined.") % undersampleStyle)); throw; } } catch(ex::Exception &e) { LSST_EXCEPT_ADD(e, "setting _gridcolumns"); throw; } for (int iY = 0; iY < height; ++iY) { _gridColumns[iX][iY] = intobj->interpolate(ypix[iY]); } } /** * @brief Add a scalar to the Background (equivalent to adding a constant to the original image) */ void BackgroundMI::operator+=(float const delta ///< Value to add ) { _statsImage += delta; } /** * @brief Subtract a scalar from the Background (equivalent to subtracting a constant from the original image) */ void BackgroundMI::operator-=(float const delta ///< Value to subtract ) { _statsImage -= delta; } /** * @brief Method to retrieve the background level at a pixel coord. * * @return an estimated background at x,y (double) * * \deprecated Don't call this image (not even in test code). * This can be a very costly function to get a single pixel. If you want an image, use the getImage() method. */ double BackgroundMI::getPixel(Interpolate::Style const interpStyle, ///< How to interpolate int const x, ///< x-pixel coordinate (column) int const y ///< y-pixel coordinate (row) ) const {
    236 264e671e - (void)getImage(interpStyle); // setup the interpolation
    ? ^^^ ----------
    236 c16ef84d + (void)getImage(interpStyle); // setup the interpolation
    ? ^^^^^ // build an interpobj along the row y and get the x'th value int const nxSample = _statsImage.getWidth(); std::vector bg_x(nxSample); for (int iX = 0; iX < nxSample; iX++) { bg_x[iX] = _gridColumns[iX][y]; } std::vector xcenTmp, bgTmp; cullNan(_xcen, bg_x, xcenTmp, bgTmp); try { PTR(Interpolate) intobj = makeInterpolate(xcenTmp, bgTmp, interpStyle); return static_cast(intobj->interpolate(x)); } catch(ex::Exception &e) { LSST_EXCEPT_ADD(e, "in getPixel()"); throw; } } /* * Worker routine for getImage */ template PTR(image::Image) BackgroundMI::doGetImage( geom::Box2I const& bbox, Interpolate::Style const interpStyle_, // Style of the interpolation UndersampleStyle const undersampleStyle // Behaviour if there are too few points ) const { if (!_imgBBox.contains(bbox)) {
    266 104a6fcc - throw LSST_EXCEPT(ex::LengthErrorException,
    ? ---------
    266 21597d88 + throw LSST_EXCEPT(ex::LengthError,
    str(boost::format("BBox (%d:%d,%d:%d) out of range (%d:%d,%d:%d)") % bbox.getMinX() % bbox.getMaxX() % bbox.getMinY() % bbox.getMaxY() % _imgBBox.getMinX() % _imgBBox.getMaxX() % _imgBBox.getMinY() % _imgBBox.getMaxY())); } int const nxSample = _statsImage.getWidth(); int const nySample = _statsImage.getHeight(); Interpolate::Style interpStyle = interpStyle_; // not const -- may be modified if REDUCE_INTERP_ORDER /* * Save the as-used interpStyle and undersampleStyle. * * N.b. The undersampleStyle may actually be overridden for some columns of the statsImage if they * have too few good values. This doesn't prevent you reproducing the results of getImage() by * calling getImage(getInterpStyle(), getUndersampleStyle()) */ _asUsedInterpStyle = interpStyle; _asUsedUndersampleStyle = undersampleStyle; /* * Check if the requested nx,ny are sufficient for the requested interpolation style, * making suitable adjustments */ bool const isXundersampled = (nxSample < lookupMinInterpPoints(interpStyle)); bool const isYundersampled = (nySample < lookupMinInterpPoints(interpStyle)); switch (undersampleStyle) { case THROW_EXCEPTION: if (isXundersampled && isYundersampled) {
    295 1c68e3a7 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    295 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "nxSample and nySample have too few points for requested interpolation style."); } else if (isXundersampled) {
    298 1c68e3a7 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    298 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "nxSample has too few points for requested interpolation style."); } else if (isYundersampled) {
    301 1c68e3a7 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    301 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "nySample has too few points for requested interpolation style."); } break; case REDUCE_INTERP_ORDER: if (isXundersampled || isYundersampled) { Interpolate::Style const xStyle = lookupMaxInterpStyle(nxSample); Interpolate::Style const yStyle = lookupMaxInterpStyle(nySample); interpStyle = (nxSample < nySample) ? xStyle : yStyle; _asUsedInterpStyle = interpStyle; } break; case INCREASE_NXNYSAMPLE: if (isXundersampled || isYundersampled) {
    315 1c68e3a7 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    315 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ "The BackgroundControl UndersampleStyle INCREASE_NXNYSAMPLE is not supported."); } break; default:
    320 1c68e3a7 - throw LSST_EXCEPT(ex::InvalidParameterException,
    ? ^^^^^^ ^
    320 21597d88 + throw LSST_EXCEPT(ex::InvalidParameterError,
    ? ^^ ^ str(boost::format("The selected BackgroundControl " "UndersampleStyle %d is not defined.") % undersampleStyle)); }
    324 264e671e -
    325 264e671e - // if we're approximating, don't bother with the rest of the interp-related work. Return from here.
    326 264e671e - if (_bctrl->getApproximateControl()->getStyle() != ApproximateControl::UNKNOWN) {
    327 264e671e - return doGetApproximate(*_bctrl->getApproximateControl(), _asUsedUndersampleStyle)->getImage();
    328 264e671e - }
    329 264e671e -
    324 2b4b80a5 +
    ? +++ // ============================================================= // --> We'll store nxSample fully-interpolated columns to interpolate the rows over // make a vector containing the y pixel coords for the column int const width = _imgBBox.getWidth(); int const height = _imgBBox.getHeight();
    330 034610f9 + auto const bboxOff = bbox.getMin() - _imgBBox.getMin();
    335 104a6fcc - int const x0 = bbox.getMinX();
    336 104a6fcc - int const y0 = bbox.getMinY();
    std::vector ypix(height); for (int iY = 0; iY < height; ++iY) { ypix[iY] = iY; } _gridColumns.resize(width); for (int iX = 0; iX < nxSample; ++iX) { _setGridColumns(interpStyle, undersampleStyle, iX, ypix); } // create a shared_ptr to put the background image in and return to caller
    343 034610f9 + // start with xy0 = 0 and set final xy0 later
    PTR(image::Image) bg = PTR(image::Image)(new image::Image(bbox.getDimensions())); // go through row by row // - interpolate on the gridcolumns that were pre-computed by the constructor // - copy the values to an ImageT to return to the caller. std::vector xcenTmp, bgTmp; // N.b. There's no API to set defaultValue to other than NaN (due to issues with persistence // that I don't feel like fixing; #2825). If we want to address this, this is the place // to start, but note that NaN is treated specially -- it means, "Interpolate" so to allow // us to put a NaN into the outputs some changes will be needed double defaultValue = std::numeric_limits::quiet_NaN();
    363 104a6fcc - for (int iY = y0; iY <= bbox.getMaxY(); ++iY) {
    358 034610f9 + for (int y = 0, iY = bboxOff.getY(); y < bbox.getHeight(); ++y, ++iY) {
    // build an interp object for this row std::vector bg_x(nxSample); for (int iX = 0; iX < nxSample; iX++) { bg_x[iX] = static_cast(_gridColumns[iX][iY]); } cullNan(_xcen, bg_x, xcenTmp, bgTmp, defaultValue); PTR(Interpolate) intobj; try { intobj = makeInterpolate(xcenTmp, bgTmp, interpStyle);
    374 ecc83dad - } catch(pex::exceptions::OutOfRangeException &e) {
    ? ^^^^^^ ^
    369 21597d88 + } catch(pex::exceptions::OutOfRangeError &e) {
    ? ^^ ^ switch (undersampleStyle) { case THROW_EXCEPTION: LSST_EXCEPT_ADD(e, str(boost::format("Interpolating in y (iY = %d)") % iY)); throw; case REDUCE_INTERP_ORDER: { if (bgTmp.empty()) { xcenTmp.push_back(0); bgTmp.push_back(defaultValue); intobj = makeInterpolate(xcenTmp, bgTmp, Interpolate::CONSTANT); break; } else { intobj = makeInterpolate(xcenTmp, bgTmp, lookupMaxInterpStyle(bgTmp.size())); } } break; case INCREASE_NXNYSAMPLE: LSST_EXCEPT_ADD(e, "The BackgroundControl UndersampleStyle INCREASE_NXNYSAMPLE is not supported."); throw; default: LSST_EXCEPT_ADD(e, str(boost::format("The selected BackgroundControl " "UndersampleStyle %d is not defined.") % undersampleStyle)); throw; } } catch(ex::Exception &e) { LSST_EXCEPT_ADD(e, str(boost::format("Interpolating in y (iY = %d)") % iY)); throw; } // fill the image with interpolated values
    406 104a6fcc - int const y = iY - y0;
    407 104a6fcc - for (int iX = x0, x = 0; iX <= bbox.getMaxX(); ++iX, ++x) {
    ? ^ ^^ - ^^^^
    401 034610f9 + for (int iX = bboxOff.getX(), x = 0; x < bbox.getWidth(); ++iX, ++x) {
    ? +++ ^^^^^^^^^^ ^ ^^^^^ (*bg)(x, y) = static_cast(intobj->interpolate(iX)); } }
    411 104a6fcc - bg->setXY0(x0, y0);
    405 034610f9 + bg->setXY0(bbox.getMin());
    return bg; } /************************************************************************************************************/ template PTR(Approximate) BackgroundMI::doGetApproximate( ApproximateControl const& actrl, /* Approximation style */ UndersampleStyle const undersampleStyle /* Behaviour if there are too few points */ ) const {
    418 034610f9 + auto const localBBox = afw::geom::Box2I(afw::geom::Point2I(0, 0), _imgBBox.getDimensions());
    424 d9899645 - return makeApproximate(_xcen, _ycen, _statsImage, _imgBBox, actrl);
    ? ^^^^
    419 034610f9 + return makeApproximate(_xcen, _ycen, _statsImage, localBBox, actrl);
    ? ^^^^^ }
    422 b4f73cbf + /// \cond
    /* * Create the versions we need of _get{Approximate,Image} and Explicit instantiations *
    430 1c68e3a7 - * \cond
    */ #define CREATE_BACKGROUND(m, v, TYPE) \ template BackgroundMI::BackgroundMI(image::Image const& img, \ BackgroundControl const& bgCtrl); \ template BackgroundMI::BackgroundMI(image::MaskedImage const& img, \ BackgroundControl const& bgCtrl); \ PTR(image::Image) \ BackgroundMI::_getImage( \ geom::Box2I const& bbox, \ Interpolate::Style const interpStyle, /* Style of the interpolation */ \ UndersampleStyle const undersampleStyle, /* Behaviour if there are too few points */ \ TYPE /* disambiguate */ \ ) const \ { \ return BackgroundMI::doGetImage(bbox, interpStyle, undersampleStyle); \ } #define CREATE_getApproximate(m, v, TYPE) \ PTR(Approximate) BackgroundMI::_getApproximate( \ ApproximateControl const& actrl, /* Approximation style */ \ UndersampleStyle const undersampleStyle, /* Behaviour if there are too few points */ \ TYPE /* disambiguate */ \ ) const \ { \ return BackgroundMI::doGetApproximate(actrl, undersampleStyle); \ } BOOST_PP_SEQ_FOR_EACH(CREATE_BACKGROUND, , LSST_makeBackground_getImage_types) BOOST_PP_SEQ_FOR_EACH(CREATE_getApproximate, , LSST_makeBackground_getApproximate_types)
    461 264e671e - /// \endcond
    ? -
    456 1c68e3a7 + // \endcond
    }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    1c68e3a7

    commit 1c68e3a7ed6015c789c0d27765ffbc3f67ffd6e6
    Author: Robert Lupton the Good 
    Date:   Tue Oct 16 13:19:16 2012 -0400
    
        Changed names of Background classes
        
        BackgroundBase -> Background
        Background     -> BackgroundMI
    

    104a6fcc

    commit 104a6fcc6b9e6f1bb13fc88943ff59e0e2926221
    Author: Paul Price 
    Date:   Fri Feb 7 16:18:14 2014 -0500
    
        Background: add option to produce background sub-image
        
        This is especially important for getting the image for a background model
        corresponding to an entire tract (e.g., 10k pixels square or more), as it
        is not possible to produce the entire image and then just use the region
        of interest because of memory constraints (which is also much slower).
    

    654709ea

    commit 654709ea3d38a99d4b20e11cbf7d9ab8eb43d8de
    Author: Robert Lupton the Good 
    Date:   Wed Mar 6 21:52:05 2013 -0500
    
        Use undersampleStyle to decide how to handle not having enough valid data points
    

    ecc83dad

    commit ecc83dadc3e7c194f68ee4a4c44a05090e83eecb
    Author: Robert Lupton the Good 
    Date:   Thu Apr 25 16:08:17 2013 -0400
    
        Handle the case that not only columns are bad but rows too
        
        And an entirely bad image, for that matter (sets background to NaN).  A
        single good pixel is enough to avoid this fate
    

    d9899645

    commit d98996458b0f4ccd9e386f9d76e0fbe652d30b16
    Author: Robert Lupton the Good 
    Date:   Tue Mar 12 06:23:09 2013 +0900
    
        MaskedImages like _statsImage are quite light weight, and can be copied
    

    264e671e

    commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
    Author: Steven Bickerton 
    Date:   Fri Oct 24 14:37:15 2014 +0900
    
        Use shared_ptr.  Add test.  Disable double,int backgrounds.
    

    Commits in /Users/nate/repos_lsst/afw/

    c16ef84d

    commit c16ef84dbc57a40a79480b3b277261cb6bbe22c6
    Author: Robert Lupton the Good 
    Date:   Wed Apr 3 16:45:18 2013 -0400
    
        Cleanups as proposed by REO in code review for #2732
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    1c68e3a7

    commit 1c68e3a7ed6015c789c0d27765ffbc3f67ffd6e6
    Author: Robert Lupton the Good 
    Date:   Tue Oct 16 13:19:16 2012 -0400
    
        Changed names of Background classes
        
        BackgroundBase -> Background
        Background     -> BackgroundMI
    

    034610f9

    commit 034610f9b20b86a988c52e9b09a15dc49affadbd
    Author: Russell Owen 
    Date:   Fri Mar 20 15:40:36 2015 -0700
    
        Change Background to use the xy0 of the image bbox
        
        The Background and BackgroundMI objects ignored the xy0 of the image
        from which they were constructed. This code modifies these classes
        to record the xy0, so that the background images constructed from an image
        have the same xy0 as the image.
        
        It appears that ignoring the image's xy0 was an accident based
        on a misunderstanding about the old default behavior of Image.getBBox(),
        which used to return a LOCAL bounding box (xy0=0,0). Much of the existing
        code seems to be based on the bounding box possibly having a non-zero xy0.
        Nonetheless, simply changing the way the bounding box was read from the image
        was insufficient and I had to make additional changes. There were two possible
        approaches:
        - Use PARENT coordinates everywhere. This requires changingmore code, but results in all
        variables using the same coordinate system (PARENT coordinates), so I felt it was
        worth trying. Unfortunately I was not able to get it to work.
        - Continue to use LOCAL coordinates for all the math and just apply the XY0
        after computing the background image. This is a minimally invasive approach,
        but result in the code using two coordinate systems, which is potentially confusing.
        Nonetheless this is the approach I took.
        
        tests/background.py includes two new tests for these changes. I also made
        other changes to this test, including:
        - Minor changes to make the file pass the pyflakes linter with no warnings
        - Use @skipIt for tests if afwdata is not setup, as requested by the reviewer
        
        Improve the background.py unit test as per John S's review
    

    2b4b80a5

    commit 2b4b80a531b4f37ae62b237534c8142eb3450449
    Author: Robert Lupton the Good 
    Date:   Sat Mar 9 07:01:06 2013 +0900
    
        Make it possible to round-trip a list of Backgrounds via disk
        
        This involved adding a ctor to make a BackgroundMI from a statsImage
        and the full-resolution image bounding box (n.b. the origin is
        still ignored).   Because much task code still uses legacy API where
        the interpolation style is specified in the ctor, not as arguments to
        getImage where it's actually used, it seemed out of scope to expect
        the list to be of tuples (Background, interpStyle, undersampleStyle)
        so I use the values that were last used to get an Image.  This is
        probably safe, but is a little ugly.
    

    b4f73cbf

    commit b4f73cbf3097165062c02aa04905ab10b06c6bec
    Author: Russell Owen 
    Date:   Mon Sep 8 16:05:52 2014 -0700
    
        First pass at DM-840
        Added UNDEFINED ImageOrigin enum value
        Made UNDEFINED the default for image constructors (which have lots of defaults,
        so I can't just delete the origin default).
        Eliminated the default value for ImageBase.getBBox.
        Modified all code that calls functions that accept an ImageOrigin argument to specify it explicitly.
    

    Return to list

    src/image/Wcs.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/format.hpp"
                    
                    #include "wcslib/wcs.h"
                    #include "wcslib/wcsfix.h"
                    #include "wcslib/wcshdr.h"
                    
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/afw/formatters/Utils.h"
                    #include "lsst/afw/formatters/WcsFormatter.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/image/ImageUtils.h"
                    #include "lsst/afw/image/Wcs.h"
                    #include "lsst/afw/coord/Coord.h"
                    #include "lsst/afw/geom/Angle.h"
                    #include "lsst/afw/table/io/OutputArchive.h"
                    #include "lsst/afw/table/io/InputArchive.h"
                    #include "lsst/afw/table/io/CatalogVector.h"
                    
                    namespace except = lsst::pex::exceptions; 
                    namespace afwImg = lsst::afw::image;
                    namespace afwCoord = lsst::afw::coord;
                    namespace afwGeom = lsst::afw::geom;
                    
                    
                    using namespace std;
                    
                    typedef lsst::daf::base::PropertySet PropertySet;
                    typedef lsst::daf::base::PropertyList PropertyList;
                    typedef lsst::afw::image::Wcs Wcs;
                    typedef lsst::afw::geom::Point2D GeomPoint;
                    typedef lsst::afw::coord::Coord::Ptr CoordPtr;
                    typedef lsst::afw::image::XYTransformFromWcsPair XYTransformFromWcsPair;
                    
                    //The amount of space allocated to strings in wcslib
                    const int STRLEN = 72;
                    
                    //Set internal params for wcslib
                    void lsst::afw::image::Wcs::_setWcslibParams()
                    {
                        _wcsfixCtrl =                       // ctrl for wcsfix
                            2;                              // Translate "H" to "h"
                        _wcshdrCtrl =                       // ctrl for wcspih
                            2;                              // Report each rejected keyrecord and the reason why it was rejected
                        _relax =                            // relax parameter for wcspih;
                            WCSHDR_all;                     // Accept all extensions recognized by the parser
                    }
                    
                    const int lsstToFitsPixels = +1;
                    const int fitsToLsstPixels = -1;
                    
                    //
                    // Constructors
                    //
                    
                    
                    ///@brief Construct an invalid Wcs given no arguments
                    lsst::afw::image::Wcs::Wcs() :
                        daf::base::Citizen(typeid(this)),
                        _wcsInfo(NULL), _nWcsInfo(0), _relax(0), _wcsfixCtrl(0), _wcshdrCtrl(0), _nReject(0),
                        _coordSystem(static_cast(-1)) {
                        _setWcslibParams();
                        _initWcs();    
                    }
                    
                    
                    ///Create a Wcs from a fits header. Don't call this directly. Use makeWcs() instead, which will figure
                    ///out which (if any) sub-class of Wcs is appropriate
                    Wcs::Wcs(CONST_PTR(lsst::daf::base::PropertySet) const& fitsMetadata):
                        daf::base::Citizen(typeid(this)),
                        _wcsInfo(NULL), 
                        _nWcsInfo(0), 
                        _relax(0), 
                        _wcsfixCtrl(0), 
                        _wcshdrCtrl(0),
                        _nReject(0),
                        _coordSystem(static_cast(-1))
                    {
                        _setWcslibParams();
                    
                        initWcsLibFromFits(fitsMetadata);
                        _initWcs();
                    }
                    
                    /*
                     * Set some internal variables that we need to refer to
                     */
                    void Wcs::_initWcs()
                    {
                        if (_wcsInfo) {
                            _coordSystem = afwCoord::makeCoordEnum(_wcsInfo->radesys);
                    
                            // tell WCSlib that values have been updated
                            _wcsInfo->flag = 0;
                            // and then tell it to do its internal magic.
                            int status = wcsset(_wcsInfo);
                            if (status != 0) {
    
    127 45d55dec - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    127 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Failed to setup wcs structure with wcsset. Status %d: %s") % status % wcs_errmsg[status] ).str()); } } } ///\brief Create a Wcs object with some known information. /// ///\param crval The sky position of the reference point ///\param crpix The pixel position corresponding to crval in LSST units ///\param CD Matrix describing transformations from pixel to sky positions ///\param ctype1 Projection system used (see description of Wcs) ///\param ctype2 Projection system used (see description of Wcs) ///\param equinox Equinox of coordinate system, eg 2000 (Julian) or 1950 (Besselian) ///\param raDecSys System used to describe right ascension or declination, e.g FK4, FK5 or ICRS ///\param cunits1 Units of sky position. One of deg, arcmin or arcsec ///\param cunits2 Units of sky position. One of deg, arcmin or arcsec /// ///\note LSST units are zero indexed while FITs units are 1 indexed. So a value of crpix stored in a fits ///header of 127,127 corresponds to a pixel position in LSST units of 128, 128 Wcs::Wcs(GeomPoint const & crval, GeomPoint const & crpix, Eigen::Matrix2d const & CD, std::string const & ctype1, std::string const & ctype2, double equinox, std::string const & raDecSys, std::string const & cunits1, std::string const & cunits2 ): daf::base::Citizen(typeid(this)), _wcsInfo(NULL), _nWcsInfo(0), _relax(0), _wcsfixCtrl(0), _wcshdrCtrl(0), _nReject(0), _coordSystem(static_cast(-1)) { _setWcslibParams(); initWcsLib(crval, crpix, CD, ctype1, ctype2, equinox, raDecSys, cunits1, cunits2); _initWcs(); } ///Parse a fits header, extract the relevant metadata and create a Wcs object void Wcs::initWcsLibFromFits(CONST_PTR(lsst::daf::base::PropertySet) const& header){ /// Access control for the input header /// /// We want to hack up the input, and in order to do so we need to do a deep copy on it. /// We only want to do that copy once, and would like to avoid doing it altogether. class HeaderAccess { public: /// Return a readable version of the metadata CONST_PTR(lsst::daf::base::PropertySet) const& toRead() { return _constHeader; } /// Return a writable version of the metadata PTR(lsst::daf::base::PropertySet) const& toWrite() { if (!_hackHeader) { _hackHeader = _constHeader->deepCopy(); _constHeader = _hackHeader; } return _hackHeader; } /// Ctor HeaderAccess(CONST_PTR(lsst::daf::base::PropertySet) const& header) : _constHeader(header), _hackHeader() {} private: CONST_PTR(lsst::daf::base::PropertySet) _constHeader; PTR(lsst::daf::base::PropertySet) _hackHeader; }; HeaderAccess access(header); // Some headers (e.g. SDSS ones from FNAL) have EQUINOX as a string. Fix this, // as wcslib 4.4.4 refuses to handle it { std::string const& key = "EQUINOX"; if (access.toRead()->exists(key) && access.toRead()->typeOf(key) == typeid(std::string)) { double equinox = ::atof(access.toRead()->getAsString(key).c_str()); access.toWrite()->set(key, equinox); } } //Check header isn't empty int nCards = lsst::afw::formatters::countFitsHeaderCards(access.toRead()); if (nCards <= 0) { string msg = "Could not parse FITS WCS: no header cards found";
    215 054f091f - throw LSST_EXCEPT(except::InvalidParameterException, msg);
    ? ^^^^^^ ^
    215 21597d88 + throw LSST_EXCEPT(except::InvalidParameterError, msg);
    ? ^^ ^ } // Scamp produces PVi_xx header cards that are inconsistent with WCS Paper 2 // and cause WCSLib to choke. Aggressively, rename all PV keywords to X_PV for (int j=1; j<3; j++) { for (int i=0; i<=99; i++) { std::string key = (boost::format("PV%i_%i") % j % i).str(); if (!access.toRead()->exists(key)) { break; } double val = access.toRead()->getAsDouble(key); access.toWrite()->remove(key); access.toWrite()->add("X_"+key, val); } } //While the standard does not insist on CRVAL and CRPIX being present, it //is almost certain their absence indicates a problem. //Check for CRPIX if( !access.toRead()->exists("CRPIX1") && !access.toRead()->exists("CRPIX1a")) { string msg = "Neither CRPIX1 not CRPIX1a found";
    237 edce4473 - throw LSST_EXCEPT(except::InvalidParameterException, msg);
    ? ^^^^^^ ^
    237 21597d88 + throw LSST_EXCEPT(except::InvalidParameterError, msg);
    ? ^^ ^ } if( !access.toRead()->exists("CRPIX2") && !access.toRead()->exists("CRPIX2a")) { string msg = "Neither CRPIX2 not CRPIX2a found";
    242 084233ba - throw LSST_EXCEPT(except::InvalidParameterException, msg);
    ? ^^^^^^ ^
    242 21597d88 + throw LSST_EXCEPT(except::InvalidParameterError, msg);
    ? ^^ ^ } //And the same for CRVAL if( !access.toRead()->exists("CRVAL1") && !access.toRead()->exists("CRVAL1a")) { string msg = "Neither CRVAL1 not CRVAL1a found";
    248 084233ba - throw LSST_EXCEPT(except::InvalidParameterException, msg);
    ? ^^^^^^ ^
    248 21597d88 + throw LSST_EXCEPT(except::InvalidParameterError, msg);
    ? ^^ ^ } if( !access.toRead()->exists("CRVAL2") && !access.toRead()->exists("CRVAL2a")) { string msg = "Neither CRVAL2 not CRVAL2a found";
    253 084233ba - throw LSST_EXCEPT(except::InvalidParameterException, msg);
    ? ^^^^^^ ^
    253 21597d88 + throw LSST_EXCEPT(except::InvalidParameterError, msg);
    ? ^^ ^ } /* * According to Greisen and Calabretta (A&A 395, 1061–1075 (2002)) it's illegal to mix PCi_j and CDi_j * headers; unfortunately Subaru puts both in its headers. It actually uses PC001002 instead of PC1_2 * (dating to a proposed FITS standard from 1996) and at least sometimes fails to include CDELT[12], * so the CD and PC matrices are inconsistent * * If we detect any part of a CD matrix, delete all PC matrices */ if(access.toRead()->exists("CD1_1") || access.toRead()->exists("CD1_2") || access.toRead()->exists("CD2_1") || access.toRead()->exists("CD2_2")) { for (int i = 1; i <= 2; ++i) { for (int j = 1; j <= 2; ++j) { std::string key = (boost::format("PC%i_%i") % j % i).str(); if (access.toRead()->exists(key)) { double const val = access.toRead()->getAsDouble(key); access.toWrite()->remove(key); access.toWrite()->add("X_" + key, val); } key = (boost::format("PC%03d%03d") % j % i).str(); if (access.toRead()->exists(key)) { double const val = access.toRead()->getAsDouble(key); access.toWrite()->remove(key); access.toWrite()->add("X_" + key, val); } } } } //Pass the header into wcslib's formatter to extract & setup the Wcs. First need //to convert to a C style string, so the compile doesn't complain about constness std::string metadataStr = lsst::afw::formatters::formatFitsProperties(access.toRead()); // We own the data, and wcslib is slack about constness, so no qualms with casting away const char *hdrString = const_cast(metadataStr.c_str()); //printf("wcspih string:\n%s\n", hdrString); nCards = lsst::afw::formatters::countFitsHeaderCards(access.toRead()); // we may have dropped some int pihStatus = wcspih(hdrString, nCards, _relax, _wcshdrCtrl, &_nReject, &_nWcsInfo, &_wcsInfo); if (pihStatus != 0) {
    295 054f091f - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    295 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Could not parse FITS WCS: wcspih status = %d (%s)") % pihStatus % wcs_errmsg[pihStatus]).str()); } //Run wcsfix on _wcsInfo to try and fix any problems it knows about. const int *naxes = NULL; // should be {NAXIS1, NAXIS2, ...} to check cylindrical projections int stats[NWCSFIX]; // status returns from wcsfix int fixStatus = wcsfix(_wcsfixCtrl, naxes, _wcsInfo, stats); if (fixStatus != 0) { std::stringstream errStream; errStream << "Could not parse FITS WCS: wcsfix failed " << std::endl; for (int ii = 0; ii < NWCSFIX; ++ii) { if (stats[ii] >= 0) { errStream << "\t" << ii << ": " << stats[ii] << " " << wcsfix_errmsg[stats[ii]] << std::endl; } else { errStream << "\t" << ii << ": " << stats[ii] << std::endl; } } } //The Wcs standard requires a default value for RADESYS if the keyword //doesn't exist in header, but wcslib doesn't set it. So we do so here. This code //conforms to Calabretta & Greisen 2002 \S 3.1 if (!(access.toRead()->exists("RADESYS") || access.toRead()->exists("RADESYSa"))) { // If RADECSYS exists, use that (counter to Calabretta & Greisen 2002 \S 3.1, but commonly used). // If equinox exist and < 1984, use FK4. If >= 1984, use FK5 if (access.toRead()->exists("RADECSYS")) { strncpy(_wcsInfo->radesys, access.toRead()->getAsString("RADECSYS").c_str(), STRLEN); } else if (access.toRead()->exists("EQUINOX") || access.toRead()->exists("EQUINOXa")) { std::string const EQUINOX = access.toRead()->exists("EQUINOX") ? "EQUINOX" : "EQUINOXa"; double const equinox = access.toRead()->getAsDouble(EQUINOX); if(equinox < 1984) { strncpy(_wcsInfo->radesys, "FK4", STRLEN); } else { strncpy(_wcsInfo->radesys, "FK5", STRLEN); } } else { //If Equinox doesn't exist, default to ICRS strncpy(_wcsInfo->radesys, "ICRS", STRLEN); } } // strip trailing whitespace { for(int i = strlen(_wcsInfo->radesys) - 1; i >= 0; i--) { if (isspace(_wcsInfo->radesys[i])) { _wcsInfo->radesys[i] = '\0'; } } } // // If there are no CDi_j cards in the header, set CDi_j from PCi_j // CDi_j == CDELTi*PCi_j // if ((_wcsInfo->altlin & 2) == 0) { // no CDi_j cards were found in the header double const *cdelt = _wcsInfo->cdelt; double const *pc = _wcsInfo->pc; double *cd = _wcsInfo->cd; cd[0] = cdelt[0]*pc[0]; // 1_1 cd[1] = cdelt[0]*pc[1]; // 1_2 cd[2] = cdelt[1]*pc[2]; // 2_1 cd[3] = cdelt[1]*pc[3]; // 2_2 } } ///\brief Manually initialise a wcs struct using values passed by the constructor ///\param crval The sky position of the reference point ///\param crpix The pixel position corresponding to crval in LSST units ///\param CD Matrix describing transformations from pixel to sky positions ///\param ctype1 Projection system used (see description of Wcs) ///\param ctype2 Projection system used (see description of Wcs) ///\param equinox Equinox of coordinate system, eg 2000 (Julian) or 1950 (Besselian) ///\param raDecSys System used to describe right ascension or declination, e.g FK4, FK5 or ICRS ///\param cunits1 Units of sky position. One of deg, arcmin or arcsec ///\param cunits2 Units of sky position. One of deg, arcmin or arcsec void Wcs::initWcsLib(GeomPoint const & crval, GeomPoint const & crpix, Eigen::Matrix2d const & CD, std::string const & ctype1, std::string const & ctype2, double equinox, std::string const & raDecSys, std::string const & cunits1, std::string const & cunits2) { //Check CD is a valid size if( (CD.rows() != 2) || (CD.cols() != 2) ) { string msg = "CD is not a 2x2 matrix";
    379 054f091f - throw LSST_EXCEPT(except::InvalidParameterException, msg);
    ? ^^^^^^ ^
    379 21597d88 + throw LSST_EXCEPT(except::InvalidParameterError, msg);
    ? ^^ ^ } //Check that cunits are legitimate values bool isValid = (cunits1 == "deg"); isValid |= (cunits1 == "arcmin"); isValid |= (cunits1 == "arcsec"); isValid |= (cunits1 == "mas"); if (!isValid) { string msg = "CUNITS1 must be one of {deg|arcmin|arcsec|mas}";
    390 054f091f - throw LSST_EXCEPT(except::InvalidParameterException, msg);
    ? ^^^^^^ ^
    390 21597d88 + throw LSST_EXCEPT(except::InvalidParameterError, msg);
    ? ^^ ^ } isValid = (cunits2 == "deg"); isValid |= (cunits2 == "arcmin"); isValid |= (cunits2 == "arcsec"); isValid |= (cunits2 == "mas"); if (!isValid) { string msg = "CUNITS2 must be one of {deg|arcmin|arcsec|mas}";
    400 054f091f - throw LSST_EXCEPT(except::InvalidParameterException, msg);
    ? ^^^^^^ ^
    400 21597d88 + throw LSST_EXCEPT(except::InvalidParameterError, msg);
    ? ^^ ^ } //Initialise the wcs struct _wcsInfo = static_cast(malloc(sizeof(struct wcsprm))); if (_wcsInfo == NULL) {
    406 054f091f - throw LSST_EXCEPT(except::MemoryException, "Cannot allocate WCS info");
    ? ^^^^^^ ^
    406 21597d88 + throw LSST_EXCEPT(except::MemoryError, "Cannot allocate WCS info");
    ? ^^ ^ } _wcsInfo->flag = -1; int status = wcsini(true, 2, _wcsInfo); //2 indicates a naxis==2, a two dimensional image if(status != 0) {
    412 054f091f - throw LSST_EXCEPT(except::MemoryException,
    ? ^^^^^^ ^
    412 21597d88 + throw LSST_EXCEPT(except::MemoryError,
    ? ^^ ^ (boost::format("Failed to allocate memory with wcsini. Status %d: %s") % status % wcs_errmsg[status] ).str()); } //Set crval, crpix and CD. Internally to the class, we use fits units for consistency with //wcslib. _wcsInfo->crval[0] = crval.getX(); _wcsInfo->crval[1] = crval.getY(); _wcsInfo->crpix[0] = crpix.getX() + lsstToFitsPixels; _wcsInfo->crpix[1] = crpix.getY() + lsstToFitsPixels; //Set the CD matrix for (int i=0; i<2; ++i) { for (int j=0; j<2; ++j) { _wcsInfo->cd[(2*i) + j] = CD(i,j); } } //Specify that we have a CD matrix, but no PC or CROTA _wcsInfo->altlin = 2; _wcsInfo->flag = 0; //values have been updated //This is a work around for what I think is a bug in wcslib. ->types is neither //initialised or set to NULL by default, so if I try to delete a Wcs object, //wcslib then attempts to free non-existent space, and the code can crash. _wcsInfo->types = NULL; //Set the coordinate system strncpy(_wcsInfo->ctype[0], ctype1.c_str(), STRLEN); strncpy(_wcsInfo->ctype[1], ctype2.c_str(), STRLEN); strncpy(_wcsInfo->radesys, raDecSys.c_str(), STRLEN); _wcsInfo->equinox = equinox; //Set the units strncpy(_wcsInfo->cunit[0], cunits1.c_str(), STRLEN); strncpy(_wcsInfo->cunit[1], cunits2.c_str(), STRLEN); _nWcsInfo = 1; //Specify that we have only one coordinate representation //Tell wcslib that we are need to set up internal values status=wcsset(_wcsInfo); if(status != 0) {
    455 054f091f - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    455 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Failed to setup wcs structure with wcsset. Status %d: %s") % status % wcs_errmsg[status] ).str()); } } ///Copy constructor Wcs::Wcs(afwImg::Wcs const & rhs) : daf::base::Citizen(typeid(this)), _wcsInfo(NULL), _nWcsInfo(rhs._nWcsInfo), _relax(rhs._relax), _wcsfixCtrl(rhs._wcsfixCtrl), _wcshdrCtrl(rhs._wcshdrCtrl), _nReject(rhs._nReject), _coordSystem(static_cast(-1)) { if (rhs._nWcsInfo > 0) { _wcsInfo = static_cast(calloc(rhs._nWcsInfo, sizeof(struct wcsprm))); if (_wcsInfo == NULL) {
    478 314d3560 - throw LSST_EXCEPT(lsst::pex::exceptions::MemoryException, "Cannot allocate WCS info");
    ? ^^^^^^ ^
    478 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::MemoryError, "Cannot allocate WCS info");
    ? ^^ ^ } _wcsInfo->flag = -1; int alloc = 1; //Unconditionally allocate memory when calling for (int i = 0; i != rhs._nWcsInfo; ++i) { int status = wcscopy(alloc, &rhs._wcsInfo[i], &_wcsInfo[i]); if (status != 0) { wcsvfree(&i, &_wcsInfo);
    487 fbec1ce1 - throw LSST_EXCEPT(lsst::pex::exceptions::MemoryException,
    ? ^^^^^^ ^
    487 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::MemoryError,
    ? ^^ ^ (boost::format("Could not copy WCS: wcscopy status = %d : %s") % status % wcs_errmsg[status]).str()); } } } _initWcs(); } bool Wcs::operator==(Wcs const & other) const { if (&other == this) return true; // We do a bidirectional test with a virtual member function in case one of us is a derived // class with members we don't know about here. // This is not the most efficient possible implementation, but I think it's the easiest one // with which to ensure correctness, and I think that's more important in this case. return this->_isSubset(other) && other._isSubset(*this); } // convenience functions and a macro for implementing isSubset namespace { inline bool compareArrays(double const * a, double const * b, int n) { for (int i = 0; i < n; ++i) if (a[i] != b[i]) return false; return true; } template inline bool compareStringArrays(T a, T b, int n) { for (int i = 0; i < n; ++i) if (strcmp(a[i], b[i]) != 0) return false; return true; } #define CHECK_NULLS(a, b) \ do { \ if ((a) == NULL) { \ if ((b) == NULL) return true; \ return false; \ } \ if ((b) == NULL) return false; \ } while (false) } // anonymous bool Wcs::_isSubset(Wcs const & rhs) const { CHECK_NULLS(_wcsInfo, rhs._wcsInfo); CHECK_NULLS(_wcsInfo->crval, rhs._wcsInfo->crval); CHECK_NULLS(_wcsInfo->cd, rhs._wcsInfo->cd); CHECK_NULLS(_wcsInfo->crpix, rhs._wcsInfo->crpix); CHECK_NULLS(_wcsInfo->cunit, rhs._wcsInfo->cunit); CHECK_NULLS(_wcsInfo->ctype, rhs._wcsInfo->ctype); return _nWcsInfo == rhs._nWcsInfo && _coordSystem == rhs._coordSystem && _wcsInfo->naxis == rhs._wcsInfo->naxis && _wcsInfo->equinox == rhs._wcsInfo->equinox && _wcsInfo->altlin == rhs._wcsInfo->altlin && compareArrays(_wcsInfo->crval, rhs._wcsInfo->crval, 2) && compareArrays(_wcsInfo->crpix, rhs._wcsInfo->crpix, 2) && compareArrays(_wcsInfo->cd, rhs._wcsInfo->cd, 4) && compareStringArrays(_wcsInfo->cunit, rhs._wcsInfo->cunit, 2) && compareStringArrays(_wcsInfo->ctype, rhs._wcsInfo->ctype, 2) && skyToPixel(_wcsInfo->crval[0] * afwGeom::degrees, _wcsInfo->crval[1] * afwGeom::degrees) == rhs.skyToPixel(_wcsInfo->crval[0] * afwGeom::degrees, _wcsInfo->crval[1] * afwGeom::degrees) && *pixelToSky(_wcsInfo->crpix[0], _wcsInfo->crpix[1]) == *rhs.pixelToSky(_wcsInfo->crpix[0], _wcsInfo->crpix[1]); } Wcs::~Wcs() { if (_wcsInfo != NULL) { wcsvfree(&_nWcsInfo, &_wcsInfo); } } Wcs::Ptr Wcs::clone(void) const { return Wcs::Ptr(new Wcs(*this)); } // // Accessors //
    570 054f091f - ///Return crval. Note that this need not be the centre of the image
    CoordPtr Wcs::getSkyOrigin() const { assert(_wcsInfo); return makeCorrectCoord(_wcsInfo->crval[0] * afwGeom::degrees, _wcsInfo->crval[1] * afwGeom::degrees); }
    576 d1fd26ed - ///Return crpix in the lsst convention. Note that this need not be the centre of the image
    GeomPoint Wcs::getPixelOrigin() const { assert(_wcsInfo); //Convert from fits units back to lsst units double p1 = _wcsInfo->crpix[0] + fitsToLsstPixels; double p2 = _wcsInfo->crpix[1] + fitsToLsstPixels; return afwGeom::Point2D(p1, p2); }
    585 93ddfb37 -
    586 b9072fa6 - ///Return the CD matrix
    Eigen::Matrix2d Wcs::getCDMatrix() const { assert(_wcsInfo); int const naxis = _wcsInfo->naxis; //If naxis != 2, I'm not sure if any of what follows is correct assert(naxis == 2); Eigen::Matrix2d C; for (int i=0; i< naxis; ++i){ for (int j=0; jcd[ (i*naxis) + j ]; } } return C; }
    604 6e0b6d05 - ///Flip CD matrix around the y-axis
    600 191ee518 +
    void Wcs::flipImage(int flipLR, int flipTB, afwGeom::Extent2I dimensions) const { assert(_wcsInfo); int const naxis = _wcsInfo->naxis; //If naxis != 2, I'm not sure if any of what follows is correct assert(naxis == 2); if (flipLR) { _wcsInfo->cd[0] = -_wcsInfo->cd[0]; _wcsInfo->cd[2] = -_wcsInfo->cd[2]; _wcsInfo->crpix[0] = -_wcsInfo->crpix[0] + dimensions.getX(); } if (flipTB) { _wcsInfo->cd[1] = -_wcsInfo->cd[1]; _wcsInfo->cd[3] = -_wcsInfo->cd[3]; _wcsInfo->crpix[1] = -_wcsInfo->crpix[1]+dimensions.getY(); } // tells libwcs to invalidate cached data, since transformation has been modified _wcsInfo->flag = 0; } void Wcs::rotateImageBy90(int nQuarter, afwGeom::Extent2I dimensions) const { assert(_wcsInfo); while (nQuarter < 0 ) { nQuarter += 4; } int const naxis = _wcsInfo->naxis; //If naxis != 2, I'm not sure if any of what follows is correct assert(naxis == 2); double a = _wcsInfo->cd[0]; double b = _wcsInfo->cd[1]; double c = _wcsInfo->cd[2]; double d = _wcsInfo->cd[3]; double crpx = _wcsInfo->crpix[0]; double crpy = _wcsInfo->crpix[1]; switch (nQuarter%4) { case 0: break; case 1: _wcsInfo->cd[0] = -b; _wcsInfo->cd[1] = a; _wcsInfo->cd[2] = -d; _wcsInfo->cd[3] = c; _wcsInfo->crpix[0] = -crpy + dimensions.getY(); _wcsInfo->crpix[1] = crpx; break; case 2: _wcsInfo->cd[0] = -a; _wcsInfo->cd[1] = -b; _wcsInfo->cd[2] = -c; _wcsInfo->cd[3] = -d; _wcsInfo->crpix[0] = -crpx + dimensions.getX(); _wcsInfo->crpix[1] = -crpy + dimensions.getY(); break; case 3: _wcsInfo->cd[0] = b; _wcsInfo->cd[1] = -a; _wcsInfo->cd[2] = d; _wcsInfo->cd[3] = -c; _wcsInfo->crpix[0] = crpy; _wcsInfo->crpix[1] = -crpx + dimensions.getX(); break; } // tells libwcs to invalidate cached data, since transformation has been modified _wcsInfo->flag = 0; }
    677 054f091f - ///Return the Wcs as a fits header
    673 191ee518 +
    PropertyList::Ptr Wcs::getFitsMetadata() const { return lsst::afw::formatters::WcsFormatter::generatePropertySet(*this); }
    682 93ddfb37 -
    683 1cead60f -
    684 98d95f8a -
    685 1cead60f - ///
    686 1cead60f - /// Returns the orientation of the Wcs
    687 1cead60f - ///
    688 1cead60f - /// The conventional sense for a Wcs image is to have North up and East to the left, or at least to be
    689 1cead60f - /// able to rotate the image to that orientation. It is possible to create a "flipped" Wcs, where East
    690 1cead60f - /// points right when the image is rotated such that North is up. Flipping a Wcs is akin to producing a mirror
    691 1cead60f - /// image. This function tests whether the image is flipped or not.
    692 1cead60f - ///
    693 1cead60f - /// It does so by calculating the determinant of the CD (i.e the rotation and scaling) matrix. If this
    694 1cead60f - /// determinant is positive, then the image can be rotated to a position where increasing the right ascension
    695 1cead60f - /// and declination increases the horizontal and vertical pixel position. In this case the image is flipped.
    bool Wcs::isFlipped() const {
    679 191ee518 + // We calculate the determinant of the CD (i.e the rotation and scaling)
    680 191ee518 + // matrix. If this determinant is positive, then the image can be rotated
    681 191ee518 + // to a position where increasing the right ascension and declination
    682 191ee518 + // increases the horizontal and vertical pixel position. In this case the
    683 191ee518 + // image is flipped.
    assert(_wcsInfo); double det = (_wcsInfo->cd[0] * _wcsInfo->cd[3]) - (_wcsInfo->cd[1] * _wcsInfo->cd[2]); if (det == 0) {
    701 2b49698a - throw(LSST_EXCEPT(except::RuntimeErrorException, "Wcs CD matrix is singular"));
    ? ---------
    688 21597d88 + throw(LSST_EXCEPT(except::RuntimeError, "Wcs CD matrix is singular"));
    } return (det > 0); } static double square(double x) { return x*x; }
    711 a3d887ee - ///Sky area covered by a pixel at position \c pix00. In units of square degrees.
    double Wcs::pixArea(GeomPoint pix00 ///< The pixel point where the area is desired ) const { // // Figure out the (0, 0), (0, 1), and (1, 0) ra/dec coordinates of the corners of a square drawn in pixel // It'd be better to centre the square at sky00, but that would involve another conversion between sky and // pixel coordinates so I didn't bother // const double side = 1; // length of the square's sides in pixels // Work in 3-space to avoid RA wrapping and pole issues. afwGeom::Point3D v0 = pixelToSky(pix00)->getVector(); // Step by "side" in x and y pixel directions... GeomPoint px(pix00); GeomPoint py(pix00); px.shift(afwGeom::Extent2D(side, 0)); py.shift(afwGeom::Extent2D(0, side)); // Push the points through the WCS, and find difference in 3-space. afwGeom::Extent3D dx = pixelToSky(px)->getVector() - v0; afwGeom::Extent3D dy = pixelToSky(py)->getVector() - v0; // Compute |cross product| = area of parallelogram with sides dx,dy // FIXME -- this is slightly incorrect -- it's making the small-angle // approximation, taking the distance *through* the unit sphere // rather than over its surface. // This is in units of ~radians^2 double area = sqrt(square(dx[1]*dy[2] - dx[2]*dy[1]) + square(dx[2]*dy[0] - dx[0]*dy[2]) + square(dx[0]*dy[1] - dx[1]*dy[0])); return area / square(side) * square(180. / afwGeom::PI); } afwGeom::Angle Wcs::pixelScale() const { return sqrt(pixArea(getPixelOrigin())) * afwGeom::degrees; } /* * Worker routine for skyToPixel */ GeomPoint Wcs::skyToPixelImpl(afwGeom::Angle sky1, // RA (or, more generally, longitude) afwGeom::Angle sky2 // Dec (or latitude) ) const { assert(_wcsInfo); double skyTmp[2]; double imgcrd[2]; double phi, theta; double pixTmp[2]; /* printf("_skyCoordsReversed: %c\n", (_skyCoordsReversed ? 'T' : 'F')); printf("wcsinfo.lat: %i, lng: %i\n", _wcsInfo->lat, _wcsInfo->lng); */ // WCSLib is smart enough to notice and handle crazy SDSS CTYPE1 = DEC--TAN, // by recording the indices of the long and lat coordinates. skyTmp[_wcsInfo->lng] = sky1.asDegrees(); skyTmp[_wcsInfo->lat] = sky2.asDegrees(); int stat[1]; int status = 0; status = wcss2p(_wcsInfo, 1, 2, skyTmp, &phi, &theta, imgcrd, pixTmp, stat); if (status == 9) {
    774 125affa8 - throw LSST_EXCEPT(except::DomainErrorException,
    ? ---------
    760 21597d88 + throw LSST_EXCEPT(except::DomainError,
    (boost::format("sky coordinates %s, %s degrees is not valid for this WCS") % sky1.asDegrees() % sky2.asDegrees() ).str() ); } if (status > 0) {
    781 586171f0 - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    767 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Error: wcslib returned a status code of %d at sky %s, %s deg: %s") % status % sky1.asDegrees() % sky2.asDegrees() % wcs_errmsg[status]).str()); } // wcslib assumes 1-indexed coords return afwGeom::Point2D(pixTmp[0] + lsst::afw::image::PixelZeroPos + fitsToLsstPixels, pixTmp[1] + lsst::afw::image::PixelZeroPos + fitsToLsstPixels); } GeomPoint Wcs::skyToPixel(lsst::afw::coord::Coord const & coord) const { afwCoord::Coord::Ptr sky = convertCoordToSky(coord); return skyToPixelImpl(sky->getLongitude(), sky->getLatitude()); } afwCoord::Coord::Ptr Wcs::convertCoordToSky(afwCoord::Coord const & coord) const { return coord.convert(_coordSystem); }
    801 b1f1b5c4 -
    802 1ce3688c - ///\brief Convert from sky coordinates (e.g ra/dec) to pixel positions.
    803 1ce3688c - ///
    804 f7c2b9d4 - ///Convert a sky position (e.g RA/Dec) to a pixel position. The exact meaning of sky1, sky2
    805 054f091f - ///and the return value depend on the properties of the wcs (i.e the values of CTYPE1 and
    806 f7c2b9d4 - ///CTYPE2), but the inputs are usually RA/Dec. The outputs are x and y pixel position.
    GeomPoint Wcs::skyToPixel(afwGeom::Angle sky1, afwGeom::Angle sky2) const { return skyToPixelImpl(sky1, sky2); } GeomPoint Wcs::skyToIntermediateWorldCoord(lsst::afw::coord::Coord const & coord) const { assert(_wcsInfo); afwCoord::Coord::Ptr sky = convertCoordToSky(coord); double skyTmp[2]; double imgcrd[2]; double phi, theta; double pixTmp[2]; /* printf("skyToIWC: _coordSystem = %i\n", (int)_coordSystem); printf("coord (%.3f, %.3f)\n", coord->getLongitude().asDegrees(), coord->getLatitude().asDegrees()); printf("->sky (%.3f, %.3f)\n", sky->getLongitude().asDegrees(), sky->getLatitude().asDegrees()); */ skyTmp[_wcsInfo->lng] = sky->getLongitude().asDegrees(); skyTmp[_wcsInfo->lat] = sky->getLatitude() .asDegrees(); //Estimate pixel coordinates int stat[1]; int status = 0; imgcrd[0] = imgcrd[1] = -1e6; /* printf(" skyTmp[] = (%.3f, %.3f)\n", skyTmp[0], skyTmp[1]); printf(" _wcsInfo->lng,lat = %i, %i\n", _wcsInfo->lng, _wcsInfo->lat); */ status = wcss2p(_wcsInfo, 1, 2, skyTmp, &phi, &theta, imgcrd, pixTmp, stat); if (status > 0) {
    840 d1fd26ed - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    820 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Error: wcslib returned a status code of %d at sky %s, %s deg: %s") % status % skyTmp[0] % skyTmp[1] % wcs_errmsg[status]).str()); } /* printf("->iwc (%.3f, %.3f)\n", imgcrd[0], imgcrd[1]); printf("-> pix (%.2f, %.2f)\n", pixTmp[0], pixTmp[1]); afwCoord::Coord::Ptr crval = getSkyOrigin(); printf("(crval is (%.3f, %.3f))\n", crval->getLongitude().asDegrees(), crval->getLatitude().asDegrees()); */ return GeomPoint(imgcrd[0], imgcrd[1]); } /* * Worker routine for pixelToSky */ void Wcs::pixelToSkyImpl(double pixel1, double pixel2, afwGeom::Angle skyTmp[2]) const { assert(_wcsInfo); // wcslib assumes 1-indexed coordinates double pixTmp[2] = { pixel1 - lsst::afw::image::PixelZeroPos + lsstToFitsPixels, pixel2 - lsst::afw::image::PixelZeroPos + lsstToFitsPixels}; double imgcrd[2]; double phi, theta; double sky[2]; int status = 0; status = wcsp2s(_wcsInfo, 1, 2, pixTmp, imgcrd, &phi, &theta, sky, &status); if (status > 0) {
    871 ead711a0 - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    851 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Error: wcslib returned a status code of %d at pixel %s, %s: %s") % status % pixel1 % pixel2 % wcs_errmsg[status]).str()); } // FIXME -- _wcsInfo.lat, _wcsInfo.lng ? skyTmp[0] = sky[0] * afwGeom::degrees; skyTmp[1] = sky[1] * afwGeom::degrees; }
    880 183a9410 - ///\brief Convert from pixel position to sky coordinates (e.g ra/dec)
    881 183a9410 - ///
    882 183a9410 - ///Convert a pixel position (e.g x,y) to a celestial coordinate (e.g ra/dec). The output coordinate
    883 183a9410 - ///system depends on the values of CTYPE used to construct the object. For ra/dec, the CTYPES should
    884 183a9410 - ///be RA--TAN and DEC-TAN.
    CoordPtr Wcs::pixelToSky(GeomPoint const & pixel) const { return pixelToSky(pixel.getX(), pixel.getY()); }
    889 1ce3688c - ///\brief Convert from pixel position to sky coordinates (e.g ra/dec)
    890 1ce3688c - ///
    891 054f091f - ///Convert a pixel position (e.g x,y) to a celestial coordinate (e.g ra/dec). The output coordinate
    892 b9072fa6 - ///system depends on the values of CTYPE used to construct the object. For ra/dec, the CTYPES should
    893 054f091f - ///be RA--TAN and DEC-TAN.
    CoordPtr Wcs::pixelToSky(double pixel1, double pixel2) const { assert(_wcsInfo); afwGeom::Angle skyTmp[2]; pixelToSkyImpl(pixel1, pixel2, skyTmp); return makeCorrectCoord(skyTmp[0], skyTmp[1]); }
    902 ead711a0 - ///\brief Convert from pixel position to sky coordinates (e.g ra/dec)
    903 ead711a0 - ///
    904 ead711a0 - ///Convert a pixel position (e.g x,y) to a celestial coordinate (e.g ra/dec)
    905 ead711a0 - ///
    906 ead711a0 - /// \note This routine is designed for the knowledgeable user in need of performance; it's safer to call
    907 ead711a0 - /// the version that returns a CoordPtr
    908 ead711a0 - ///
    void Wcs::pixelToSky(double pixel1, double pixel2, afwGeom::Angle& sky1, afwGeom::Angle& sky2) const { afwGeom::Angle skyTmp[2]; // HACK -- we shouldn't need to initialize these -- pixelToSkyImpl() sets them unless an // exception is thrown -- but be safe. skyTmp[0] = 0. * afwGeom::radians; skyTmp[1] = 0. * afwGeom::radians; pixelToSkyImpl(pixel1, pixel2, skyTmp); sky1 = skyTmp[0]; sky2 = skyTmp[1]; } ///\brief Given a sky position, use the values stored in ctype and radesys to return the correct ///sub-class of Coord CoordPtr Wcs::makeCorrectCoord(lsst::afw::geom::Angle sky0, lsst::afw::geom::Angle sky1) const { //Construct a coord object of the correct type int const ncompare = 4; // we only care about type's first 4 chars char *type = _wcsInfo->ctype[0]; char *radesys = _wcsInfo->radesys; double equinox = _wcsInfo->equinox; if (strncmp(type, "RA--", ncompare) == 0) { // Our default. If it's often something else, consider ; // using an tr1::unordered_map if(strcmp(radesys, "ICRS") == 0) { return afwCoord::makeCoord(afwCoord::ICRS, sky0, sky1); } if(strcmp(radesys, "FK5") == 0) { return afwCoord::makeCoord(afwCoord::FK5, sky0, sky1, equinox); } else {
    938 183a9410 - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    901 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Can't create Coord object: Unrecognised radesys %s") % radesys).str()); } } else if (strncmp(type, "GLON", ncompare) == 0) { return afwCoord::makeCoord(afwCoord::GALACTIC, sky0, sky1); } else if (strncmp(type, "ELON", ncompare) == 0) { return afwCoord::makeCoord(afwCoord::ECLIPTIC, sky0, sky1, equinox); } else if (strncmp(type, "DEC-", ncompare) == 0) { //check for the case where the ctypes are swapped. Note how sky0 and sky1 are swapped as well //Our default if(strcmp(radesys, "ICRS") == 0) { return afwCoord::makeCoord(afwCoord::ICRS, sky1, sky0); } if(strcmp(radesys, "FK5") == 0) { return afwCoord::makeCoord(afwCoord::FK5, sky1, sky0, equinox); } else {
    957 183a9410 - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    920 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Can't create Coord object: Unrecognised radesys %s") % radesys).str()); } } else if (strncmp(type, "GLAT", ncompare) == 0) { return afwCoord::makeCoord(afwCoord::GALACTIC, sky1, sky0); } else if (strncmp(type, "ELAT", ncompare) == 0) { return afwCoord::makeCoord(afwCoord::ECLIPTIC, sky1, sky0, equinox); } else { //Give up in disgust
    967 183a9410 - throw LSST_EXCEPT(except::RuntimeErrorException,
    ? ---------
    930 21597d88 + throw LSST_EXCEPT(except::RuntimeError,
    (boost::format("Can't create Coord object: Unrecognised sys %s") % type).str()); } //Can't get here assert(0); } lsst::afw::geom::AffineTransform Wcs::linearizePixelToSky( lsst::afw::coord::Coord const & coord, lsst::afw::geom::AngleUnit skyUnit ) const { return linearizePixelToSkyInternal(skyToPixel(coord), coord, skyUnit); } lsst::afw::geom::AffineTransform Wcs::linearizePixelToSky( GeomPoint const & pix, lsst::afw::geom::AngleUnit skyUnit ) const { return linearizePixelToSkyInternal(pix, *pixelToSky(pix), skyUnit); } /* * Implementation for the overloaded public linearizePixelToSky methods, requiring both a pixel coordinate * and the corresponding sky coordinate. */ lsst::afw::geom::AffineTransform Wcs::linearizePixelToSkyInternal( GeomPoint const & pix00, lsst::afw::coord::Coord const & coord, lsst::afw::geom::AngleUnit skyUnit ) const { // // Figure out the (0, 0), (0, 1), and (1, 0) ra/dec coordinates of the corners of a square drawn in pixel // It'd be better to centre the square at sky00, but that would involve another conversion between sky and // pixel coordinates so I didn't bother // const double side = 10; // length of the square's sides in pixels GeomPoint const sky00 = coord.getPosition(skyUnit); typedef std::pair AngleAngle; AngleAngle const dsky10 = coord.getTangentPlaneOffset(*pixelToSky(pix00 + afwGeom::Extent2D(side, 0))); AngleAngle const dsky01 = coord.getTangentPlaneOffset(*pixelToSky(pix00 + afwGeom::Extent2D(0, side))); Eigen::Matrix2d m; m(0, 0) = dsky10.first.asAngularUnits(skyUnit)/side; m(0, 1) = dsky01.first.asAngularUnits(skyUnit)/side; m(1, 0) = dsky10.second.asAngularUnits(skyUnit)/side; m(1, 1) = dsky01.second.asAngularUnits(skyUnit)/side; Eigen::Vector2d sky00v; sky00v << sky00.getX(), sky00.getY(); Eigen::Vector2d pix00v; pix00v << pix00.getX(), pix00.getY(); //return lsst::afw::geom::AffineTransform(m, lsst::afw::geom::Extent2D(sky00v - m * pix00v)); return lsst::afw::geom::AffineTransform(m, (sky00v - m * pix00v)); } lsst::afw::geom::AffineTransform Wcs::linearizeSkyToPixel( lsst::afw::coord::Coord const & coord, lsst::afw::geom::AngleUnit skyUnit ) const { return linearizeSkyToPixelInternal(skyToPixel(coord), coord, skyUnit); } lsst::afw::geom::AffineTransform Wcs::linearizeSkyToPixel( GeomPoint const & pix, lsst::afw::geom::AngleUnit skyUnit ) const { return linearizeSkyToPixelInternal(pix, *pixelToSky(pix), skyUnit); } /** * Implementation for the overloaded public linearizeSkyToPixel methods, requiring both a pixel coordinate * and the corresponding sky coordinate. */ lsst::afw::geom::AffineTransform Wcs::linearizeSkyToPixelInternal( GeomPoint const & pix00, lsst::afw::coord::Coord const & coord, lsst::afw::geom::AngleUnit skyUnit ) const { lsst::afw::geom::AffineTransform inverse = linearizePixelToSkyInternal(pix00, coord, skyUnit); return inverse.invert(); }
    1051 e8b0ec03 -
    1052 f547f918 -
    1053 98d95f8a - /**
    1054 98d95f8a - * Return the linear part of the Wcs, the CD matrix in FITS speak, as an AffineTransform
    1055 98d95f8a - *
    1056 98d95f8a - * \sa
    1057 98d95f8a - */
    lsst::afw::geom::LinearTransform Wcs::getLinearTransform() const { return lsst::afw::geom::LinearTransform(getCDMatrix()); } // -------- table-based persistence ------------------------------------------------------------------------- namespace lsst { namespace afw { namespace image { class WcsFactory : public table::io::PersistableFactory { public: explicit WcsFactory(std::string const & name) : table::io::PersistableFactory(name) {} virtual PTR(table::io::Persistable) read( InputArchive const & archive, CatalogVector const & catalogs ) const; }; namespace { // Read-only singleton struct containing the schema and keys that a simple Wcs is mapped // to in record persistence. struct WcsPersistenceHelper : private boost::noncopyable { table::Schema schema; table::Key< table::Point > crval; table::Key< table::Point > crpix; table::Key< table::Array > cd; table::Key ctype1; table::Key ctype2; table::Key equinox; table::Key radesys; table::Key cunit1; table::Key cunit2; static WcsPersistenceHelper const & get() { static WcsPersistenceHelper instance; return instance; }; private: WcsPersistenceHelper() : schema(), crval(schema.addField< table::Point >("crval", "celestial reference point")), crpix(schema.addField< table::Point >("crpix", "pixel reference point")), cd(schema.addField< table::Array >( "cd", "linear transform matrix, ordered (1_1, 2_1, 1_2, 2_2)", 4)), ctype1(schema.addField< std::string >("ctype1", "coordinate type", 72)), ctype2(schema.addField< std::string >("ctype2", "coordinate type", 72)), equinox(schema.addField< double >("equinox", "equinox of coordinates")), radesys(schema.addField< std::string >("radesys", "coordinate system for equinox", 72)), cunit1(schema.addField< std::string >("cunit1", "coordinate units", 72)), cunit2(schema.addField< std::string >("cunit2", "coordinate units", 72)) { schema.getCitizen().markPersistent(); } }; std::string getWcsPersistenceName() { return "Wcs"; } WcsFactory registration(getWcsPersistenceName()); } // anonymous std::string Wcs::getPersistenceName() const { return getWcsPersistenceName(); } std::string Wcs::getPythonModule() const { return "lsst.afw.image"; } void Wcs::write(OutputArchiveHandle & handle) const { WcsPersistenceHelper const & keys = WcsPersistenceHelper::get(); afw::table::BaseCatalog catalog = handle.makeCatalog(keys.schema); PTR(afw::table::BaseRecord) record = catalog.addNew(); record->set(keys.crval, getSkyOrigin()->getPosition(afw::geom::degrees)); record->set(keys.crpix, getPixelOrigin()); Eigen::Matrix2d cdIn = getCDMatrix(); Eigen::Map cdOut((*record)[keys.cd].getData()); cdOut = cdIn; record->set(keys.ctype1, std::string(_wcsInfo[0].ctype[0])); record->set(keys.ctype2, std::string(_wcsInfo[0].ctype[1])); record->set(keys.equinox, _wcsInfo[0].equinox); record->set(keys.radesys, std::string(_wcsInfo[0].radesys)); record->set(keys.cunit1, std::string(_wcsInfo[0].cunit[0])); record->set(keys.cunit2, std::string(_wcsInfo[0].cunit[1])); handle.saveCatalog(catalog); } bool Wcs::isPersistable() const { if (_wcsInfo[0].naxis != 2) return false; if (std::strcmp(_wcsInfo[0].cunit[0], "deg") != 0) return false; if (std::strcmp(_wcsInfo[0].cunit[1], "deg") != 0) return false; return true; } Wcs::Wcs(afw::table::BaseRecord const & record) : daf::base::Citizen(typeid(this)), _wcsInfo(NULL), _nWcsInfo(0), _relax(0), _wcsfixCtrl(0), _wcshdrCtrl(0), _nReject(0), _coordSystem(static_cast(-1)) { WcsPersistenceHelper const & keys = WcsPersistenceHelper::get(); if (!record.getSchema().contains(keys.schema)) { throw LSST_EXCEPT( afw::table::io::MalformedArchiveError, "Incorrect schema for Wcs persistence" ); } _setWcslibParams(); Eigen::Matrix2d cd = Eigen::Map(record[keys.cd].getData()); initWcsLib( record.get(keys.crval), record.get(keys.crpix), cd, record.get(keys.ctype1), record.get(keys.ctype2), record.get(keys.equinox), record.get(keys.radesys), record.get(keys.cunit1), record.get(keys.cunit2) ); _initWcs(); } PTR(table::io::Persistable) WcsFactory::read(InputArchive const & inputs, CatalogVector const & catalogs) const { WcsPersistenceHelper const & keys = WcsPersistenceHelper::get(); LSST_ARCHIVE_ASSERT(catalogs.size() >= 1u); LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys.schema); PTR(Wcs) result(new Wcs(catalogs.front().front())); return result; } }}} // namespace lsst::afw::image // ---------------------------------------------------------------------------------------------------------- // //Mutators // /// \brief Move the pixel reference position by (dx, dy) ///Used when persisting and retrieving sub-images. The lsst convention is that Wcs returns pixel position ///(which is based on position in the parent image), but the fits convention is to return pixel index ///(which is bases on position in the sub-image). In order that the fits files we create make sense ///to other fits viewers, we change to the fits convention when writing out images. void Wcs::shiftReferencePixel(double dx, double dy) { assert(_wcsInfo); _wcsInfo->crpix[0] += dx; _wcsInfo->crpix[1] += dy; // tells libwcs to invalidate cached data, since transformation has been modified _wcsInfo->flag = 0; } /************************************************************************************************************/ /* * Now WCSA, pixel coordinates, but allowing for X0 and Y0 */ namespace lsst { namespace afw { namespace image { namespace detail { /** * Define a trivial WCS that maps the lower left corner (LLC) pixel of an image to a given value */ lsst::daf::base::PropertyList::Ptr createTrivialWcsAsPropertySet(std::string const& wcsName, ///< Name of desired WCS int const x0, ///< Column coordinate of LLC pixel int const y0 ///< Row coordinate of LLC pixel ) { lsst::daf::base::PropertyList::Ptr wcsMetaData(new lsst::daf::base::PropertyList); wcsMetaData->set("CRVAL1" + wcsName, x0, "Column pixel of Reference Pixel"); wcsMetaData->set("CRVAL2" + wcsName, y0, "Row pixel of Reference Pixel"); wcsMetaData->set("CRPIX1" + wcsName, 1, "Column Pixel Coordinate of Reference"); wcsMetaData->set("CRPIX2" + wcsName, 1, "Row Pixel Coordinate of Reference"); wcsMetaData->set("CTYPE1" + wcsName, "LINEAR", "Type of projection"); wcsMetaData->set("CTYPE2" + wcsName, "LINEAR", "Type of projection"); wcsMetaData->set("CUNIT1" + wcsName, "PIXEL", "Column unit"); wcsMetaData->set("CUNIT2" + wcsName, "PIXEL", "Row unit"); return wcsMetaData; } /** * Return a Point2I(x0, y0) given a PropertySet containing a suitable WCS (e.g. "A") * * The WCS must have CRPIX[12] == 1 and CRVAL[12] must be present. If this is true, the WCS * cards are removed from the metadata */ afwGeom::Point2I getImageXY0FromMetadata(std::string const& wcsName, ///< the WCS to search (E.g. "A") lsst::daf::base::PropertySet *metadata ///< the metadata, maybe containing the WCS ) { int x0 = 0; // Our value of X0 int y0 = 0; // Our value of Y0 try { // // Only use WCS if CRPIX[12] == 1 and CRVAL[12] is present // if (metadata->getAsDouble("CRPIX1" + wcsName) == 1 && metadata->getAsDouble("CRPIX2" + wcsName) == 1) { x0 = metadata->getAsInt("CRVAL1" + wcsName); y0 = metadata->getAsInt("CRVAL2" + wcsName); // // OK, we've got it. Remove it from the header // metadata->remove("CRVAL1" + wcsName); metadata->remove("CRVAL2" + wcsName); metadata->remove("CRPIX1" + wcsName); metadata->remove("CRPIX2" + wcsName); metadata->remove("CTYPE1" + wcsName); metadata->remove("CTYPE1" + wcsName); metadata->remove("CUNIT1" + wcsName); metadata->remove("CUNIT2" + wcsName); }
    1279 981cdb34 - } catch(lsst::pex::exceptions::NotFoundException &) {
    ? ^^^^^^ ^
    1235 21597d88 + } catch(lsst::pex::exceptions::NotFoundError &) {
    ? ^^ ^ ; // OK, not present } return afwGeom::Point2I(x0, y0); } /** * Strip keywords from the input metadata that are related to the generated Wcs * * It isn't entirely obvious that this is enough --- e.g. if the input metadata has deprecated * WCS keywords such as CDELT[12] they won't be stripped. Well, actually we catch CDELT[12], LTV[12], and * PC00[12]00[12] * but there may be others */ int stripWcsKeywords(PTR(lsst::daf::base::PropertySet) const& metadata, ///< Metadata to be stripped CONST_PTR(Wcs) const& wcs ///< A Wcs with (implied) keywords ) { PTR(lsst::daf::base::PropertySet) wcsMetadata = wcs->getFitsMetadata(); std::vector paramNames = wcsMetadata->paramNames(); paramNames.push_back("CDELT1"); paramNames.push_back("CDELT2"); paramNames.push_back("LTV1"); paramNames.push_back("LTV2"); paramNames.push_back("PC001001"); paramNames.push_back("PC001002"); paramNames.push_back("PC002001"); paramNames.push_back("PC002002"); for (std::vector::const_iterator ptr = paramNames.begin(); ptr != paramNames.end(); ++ptr) { metadata->remove(*ptr); } return 0; // would be ncard if remove returned a status } }}}} // ------------------------------------------------------------------------------------------------- // // XYTransformFromWcsPair XYTransformFromWcsPair::XYTransformFromWcsPair(CONST_PTR(Wcs) dst, CONST_PTR(Wcs) src)
    1326 d95640da - : XYTransform(false), _dst(dst), _src(src)
    ? -----
    1282 0a8d9c69 + : XYTransform(), _dst(dst), _src(src)
    { } PTR(afwGeom::XYTransform) XYTransformFromWcsPair::clone() const { return boost::make_shared(_dst->clone(), _src->clone()); } afwGeom::Point2D XYTransformFromWcsPair::forwardTransform(Point2D const &pixel) const { // // TODO there is an alternate version of pixelToSky() which is designated for the // "knowledgeable user in need of performance". This is probably better, but first I need // to understand exactly which checks are needed (e.g. I think we need to check by hand // that both Wcs's use the same celestial coordinate system) // PTR(afw::coord::Coord) x = _src->pixelToSky(pixel); return _dst->skyToPixel(*x); } afwGeom::Point2D XYTransformFromWcsPair::reverseTransform(Point2D const &pixel) const { PTR(afw::coord::Coord) x = _dst->pixelToSky(pixel); return _src->skyToPixel(*x); } PTR(afwGeom::XYTransform) XYTransformFromWcsPair::invert() const { // just swap src, dst return boost::make_shared (_src, _dst); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    a3d887ee

    commit a3d887ee809e3c15524a228c6aeed64f2bf26806
    Author: dstn 
    Date:   Tue Jul 27 19:41:51 2010 +0000
    
        add direct pixel scale functions
    

    054f091f

    commit 054f091f5cab6a42ea6677888c5f1a44ee35ab3a
    Author: fergal 
    Date:   Fri Feb 12 19:26:26 2010 +0000
    
        Changed Wcs to be a general base class, and TanWcs to extend that class for the case of TAN and TAN-SIP projections.
    

    f547f918

    commit f547f918696733cd212d56003c562714ded1b334
    Author: fergal 
    Date:   Wed Mar 10 16:55:19 2010 +0000
    
        TanWcs::getAffineTransform() moved to a virtual function of the base class. I intend to implement a special case for TanWcs later.
    

    e8b0ec03

    commit e8b0ec03aa0d945974517d5075eece12512c664b
    Author: jbosch 
    Date:   Mon Aug 30 23:46:35 2010 +0000
    
        afw/1130 - new API for Wcs linearization; implementation done, need to add tests
    

    981cdb34

    commit 981cdb34a94ca7bd5e1d880f79c4874a8454b896
    Author: fergal 
    Date:   Fri Feb 19 21:30:33 2010 +0000
    
        Code to allow Formatters to work. Constructors from fits headers made private, only accessed by friend function makeWcs in makeWcs.cc.
        
        This commit covers source files, previous was just for headers
    

    f7c2b9d4

    commit f7c2b9d48465198f07d72c168460fb4eac5aacac
    Author: dstn 
    Date:   Mon May 9 16:22:24 2011 +0000
    
        nearly all tests pass!
    

    98d95f8a

    commit 98d95f8a6fb59a1f1932b6fddf59d355a346f715
    Author: fergal 
    Date:   Wed Mar 24 18:28:49 2010 +0000
    
        Merged from trunk, and resolved conflicts.
    

    b9072fa6

    commit b9072fa68d5de7964f331cfa4f834b896ff9afea
    Author: fergal 
    Date:   Thu Feb 25 22:17:33 2010 +0000
    
        Documenting
    

    586171f0

    commit 586171f04fb83ecfe628f3e55ae2b96b99543e76
    Author: rhl 
    Date:   Tue Oct 5 21:43:39 2010 +0000
    
        Move decision about reversed CTYPEs into Wcs::_initWcs(); move guts of skyToPixel to skyToPixelImpl; make 2-doubles form of skyToPixel understand reversed CTYPEs (e.g. the SDSS ones)
    

    edce4473

    commit edce4473bf3091acfb1ffedd786c209049440af1
    Author: fergal 
    Date:   Thu Feb 25 22:50:27 2010 +0000
    
        Moved some tests of fits header validity to Wcs from TanWcs. That way they always get checked.
    

    314d3560

    commit 314d3560afb5af2eb48a0bb85a0c90b3eec3c8e1
    Author: fergal 
    Date:   Wed Feb 24 22:49:42 2010 +0000
    
        Copy constuctor checks nWcsInfo to make sure incoming Wcs is valid. This is easier to read than the pointer test previously used.
    

    084233ba

    commit 084233ba723fa9aa2410d09ecd9722725e2f9202
    Author: fergal 
    Date:   Mon Mar 1 22:08:25 2010 +0000
    
        Added lineariseAt() function
        
        Constructor from fits checks for existence of certain keywords.
    

    125affa8

    commit 125affa8a5a3bc28ad10684c1ed948b80a3b429a
    Author: Jim Bosch 
    Date:   Thu Feb 28 15:51:45 2013 +0900
    
        Make Wcs throw a more specific and appropriate exception when coordinates passed to skyToPixel are out-of-range for that Wcs.
    

    1cead60f

    commit 1cead60f1b0cba1f37d012dd026fbc7677f165ef
    Author: fergal 
    Date:   Fri Mar 13 21:36:52 2009 +0000
    
        Added isFlipped() method
    

    2b49698a

    commit 2b49698aac5268bff502c3c48061f1e547db9a29
    Author: dstn 
    Date:   Tue May 10 17:32:05 2011 +0000
    
        CRVAL is a Coord; pixel scale is an Angle; make SourceMatch use Angle also (mostly)
    

    b1f1b5c4

    commit b1f1b5c45bd7beb5931ed1c00a085f1de12c79e9
    Author: fergal 
    Date:   Tue Dec 9 22:54:15 2008 +0000
    
        Added interface and implementation for
        lsst::afw::image::PointD getRaDecCenter() const;
        lsst::afw::image::PointD getColRowCenter() const;
        boost::numeric::ublas::matrix getLinearTransformMatrix() const;
        
        These functions give GlobalAstrometrySolution something to get their
        teeth into and interact with.
    

    ead711a0

    commit ead711a0ef66cfe7110b1448a303cc694726999a
    Author: rhl 
    Date:   Sun Aug 29 01:45:58 2010 +0000
    
        The warp code doesn't need a Coord object, and creating one is slow.  Add a version of pixelToSky that returns an afwGeom::Point2D.  As part of this, move the guts of pixelToSky to a private virtual member pixelToSkyImpl
    

    183a9410

    commit 183a941094fd2336bcd7f81371bcc3989acfdef1
    Author: fergal 
    Date:   Wed Mar 24 17:43:15 2010 +0000
    
        Changed the API for Wcs and TanWcs to accept and return Coord objects, as appropriate. Also, complicated things are done to extract sky values from coords in the correct order for the given ctypes in _wcsInfo.
        
        See the private functions Wcs::convertCoordToSky() and Wcs::makeCorrectCoord() for the gory details.
    

    93ddfb37

    commit 93ddfb37821bb355b16536edd0f4f9a9d40a3b4a
    Author: rhl 
    Date:   Thu Jul 19 15:49:17 2007 +0000
    
        Merged revisions 1476-1500,1502-1732 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DC2/fw/tickets/64
        
        ........
          ------------------------------------------------------------------------
          r1476 | taxelrod | 2007-05-24 11:51:37 -0400 (Thu, 24 May 2007) | 1 line
        
          Created branch for Ticket 64
        ........
          ------------------------------------------------------------------------
          r1481 | taxelrod | 2007-05-24 19:51:30 -0400 (Thu, 24 May 2007) | 2 lines
        
          Initial changes to implement WCS class
        ........
          ------------------------------------------------------------------------
          r1482 | taxelrod | 2007-05-24 19:53:02 -0400 (Thu, 24 May 2007) | 2 lines
        
          Implementation of WCS class (partial)
        ........
          ------------------------------------------------------------------------
          r1485 | taxelrod | 2007-05-25 19:14:25 -0400 (Fri, 25 May 2007) | 6 lines
        
          Changed DataProperty::reprCfitsio() to use FITS "fixed format" for
          values - wcslib seems to expect this.
        
          Added WCS functionality - doesn't quite work properly yet.
        ........
          ------------------------------------------------------------------------
          r1495 | taxelrod | 2007-05-29 17:52:21 -0400 (Tue, 29 May 2007) | 7 lines
        
          Finished initial WCS class implementation.
          NOTES:
            1. Based on wcslib, which does NOT HANDLE TNX
            2. Requires wcslib include files to be moved from standard LSST distribution
               location.
        ........
          ------------------------------------------------------------------------
          r1723 | rhl | 2007-07-12 15:53:27 -0400 (Thu, 12 Jul 2007) | 1 line
        
          Link in wcslib (do we want to do this? Partially subverts eups)
        ........
          ------------------------------------------------------------------------
          r1724 | rhl | 2007-07-12 15:54:01 -0400 (Thu, 12 Jul 2007) | 1 line
        
          Export WCS
        ........
          ------------------------------------------------------------------------
          r1725 | rhl | 2007-07-12 15:54:32 -0400 (Thu, 12 Jul 2007) | 1 line
        
          Don't export _ctgread (needs wcstools, not wcslib)
        ........
          ------------------------------------------------------------------------
          r1726 | rhl | 2007-07-12 15:54:54 -0400 (Thu, 12 Jul 2007) | 1 line
        
          Initial more-or-less placeholder
        ........
          ------------------------------------------------------------------------
          r1727 | rhl | 2007-07-12 15:55:30 -0400 (Thu, 12 Jul 2007) | 1 line
        
          Remove as many headers as possible from WCS.h
        ........
          ------------------------------------------------------------------------
          r1728 | rhl | 2007-07-12 15:56:23 -0400 (Thu, 12 Jul 2007) | 1 line
        
          We are using wcslib, not wcstools
        ........
          ------------------------------------------------------------------------
          r1729 | rhl | 2007-07-12 16:54:33 -0400 (Thu, 12 Jul 2007) | 1 line
        
          Added versions of colRowToRaDec/raDecToColRow that return the desired Coord2D;  added const
        ........
          ------------------------------------------------------------------------
          r1731 | rhl | 2007-07-12 17:37:17 -0400 (Thu, 12 Jul 2007) | 1 line
        
          Came closer to code standards; added doxygen docs
        ........
    

    d1fd26ed

    commit d1fd26ed185d39524a37c5ab34802f36875b52d7
    Author: fergal 
    Date:   Wed Jun 16 16:02:20 2010 +0000
    
        Added skyToIntermediateCoords() and changed getPixelOrigin() to return origin in lsst coords instead of fits coords. In other words, if the value of crpix in the fits header is 127,127, the method returns 128,128.
    

    fbec1ce1

    commit fbec1ce178f0128de2b9c705be81bec6dee17f57
    Author: rhl 
    Date:   Thu Jun 3 01:13:46 2010 +0000
    
        I think you need to allocate space for all wscprm structs; #1305
    

    d95640da

    commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
    Author: Kendrick Smith 
    Date:   Tue Feb 19 23:44:14 2013 -0500
    
        move afw::image::XYTransform -> afw::geom::XYTransform
             afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
             afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
        
        wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom
    

    6e0b6d05

    commit 6e0b6d05c1302effb01b30ffeb28eb41a8372e34
    Author: Simon Krughoff 
    Date:   Fri Jan 20 19:50:44 2012 -0600
    
        Trying to deal with Wcs in the assembly process
    

    45d55dec

    commit 45d55dec567878fc637a7e5ad78900bf370cd0d7
    Author: dstn 
    Date:   Wed May 11 15:18:23 2011 +0000
    
        wcslib was uninitialized
    

    1ce3688c

    commit 1ce3688cefa13555723186b3f2d0fea596c61fcf
    Author: fergal 
    Date:   Fri Mar 12 15:13:38 2010 +0000
    
        Code cleanup, adding comments
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    191ee518

    commit 191ee518a0e63d5c563aa62bfdf673ff70c5a44d
    Author: John Swinbank 
    Date:   Fri Mar 20 11:27:35 2015 -0400
    
        Clean up documentation of Wcs.
        
        Remove duplication between Wcs.cc and Wcs.h (which results in duplicate text
        in Doxygen output).
        
        Correct contradictory/incorrect documentation (notably, repeated claims that
        pixelToSky converts *from* sky *to* pixel coordinates).
    

    0a8d9c69

    commit 0a8d9c69b9efa9a486595305a950ce02ab1c2ade
    Author: Russell Owen 
    Date:   Tue Feb 18 17:31:35 2014 -0800
    
        Removed inFpCoordinateSystem flag from XYTransform.
    

    Return to list

    tests/testTableArchiveImport.py

    Diff:

    1 96b804a8 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import unittest import lsst.utils.tests as utilsTests import lsst.afw.image as afwImage class ArchiveImportTestCase(unittest.TestCase): def testArchiveImports(self): # This file was saved with a Psf defined in testTableArchivesLib, so we'll only be able # to load it if the module-importer mechanism works. filename = "tests/data/archiveImportTest.fits" exposure = afwImage.ExposureF(filename) self.assert_(exposure.getPsf() is not None) def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ArchiveImportTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(exit=False): """Run the utilsTests""" utilsTests.run(suite(), exit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    96b804a8

    commit 96b804a8d909e5398156b9cb9876aee57f3bd662
    Author: Jim Bosch 
    Date:   Tue Mar 19 13:50:56 2013 -0400
    
        Move KernelPsf, DoubleGaussianPsf, WarpedPsf, and associated tests to meas_algorithms.
        
        We now use DummyPsf from testTableArchivesLib instead for Exposure and
        ExposureTable tests (which works better anyway), and this will let us use
        shape and aperture algorithms in meas_algorithms in the implementation.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    tests/mask.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Masks Run with: python Mask.py or python >>> import Mask; Mask.run() """
    35 f8edfe90 - import os
    import os.path import sys import unittest import numpy
    42 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests import lsst.pex.exceptions as pexExcept import lsst.daf.base import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom
    47 f8edfe90 - import eups
    import lsst.afw.display.ds9 as ds9
    49 f8edfe90 +
    50 4bae7ca1 + numpy.random.seed(1)
    try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def showMaskDict(d=None, msg=None): if not d: d = afwImage.MaskU(0,0) if not msg: msg = "default" try: d = d.getMaskPlaneDict() except AttributeError: pass if msg: print "%-15s" % msg, print sorted([(d[p], p) for p in d]) class MaskTestCase(unittest.TestCase): """A test case for Mask""" def setUp(self): self.Mask = afwImage.MaskU self.Mask.clearMaskPlaneDict() # reset so tests will be deterministic for p in ("BAD", "SAT", "INTRP", "CR", "EDGE"): self.Mask.addMaskPlane(p) self.BAD = self.Mask.getPlaneBitMask("BAD") self.CR = self.Mask.getPlaneBitMask("CR") self.EDGE = self.Mask.getPlaneBitMask("EDGE") self.val1 = self.BAD | self.CR self.val2 = self.val1 | self.EDGE self.mask1 = afwImage.MaskU(100, 200) self.mask1.set(self.val1) self.mask2 = afwImage.MaskU(self.mask1.getDimensions()) self.mask2.set(self.val2)
    97 7cbb2bb9 + try:
    95 76505c6a - dataDir = os.path.join(eups.productDir("afwdata"), "data")
    ? ^ ^ ^^^^^ ^
    98 7cbb2bb9 + dataDir = os.path.join(lsst.utils.getPackageDir("afwdata"), "data")
    ? ++++ ^^^^^ ^^^ ^^^^^ ^^^^
    96 f8edfe90 - if dataDir:
    99 7cbb2bb9 + except Exception:
    100 7cbb2bb9 + self.maskFile = None
    101 7cbb2bb9 + else:
    if True: self.maskFile = os.path.join(dataDir, "small_MI.fits") else: self.maskFile = os.path.join(dataDir, "871034p_1_MI.fits")
    101 f8edfe90 - else:
    102 f8edfe90 - self.maskFile = None
    def tearDown(self): del self.mask1 del self.mask2 def testArrays(self): image1 = afwImage.MaskU(afwGeom.ExtentI(5,6)) # could use MaskU(5, 6) but check extent(5, 6) form too array1 = image1.getArray() self.assertEqual(array1.shape[0], image1.getHeight()) self.assertEqual(array1.shape[1], image1.getWidth()) image2 = afwImage.MaskU(array1, False) self.assertEqual(array1.shape[0], image2.getHeight()) self.assertEqual(array1.shape[1], image2.getWidth()) image3 = afwImage.makeMaskFromArray(array1) self.assertEqual(array1.shape[0], image2.getHeight()) self.assertEqual(array1.shape[1], image2.getWidth()) self.assertEqual(type(image3), afwImage.MaskU) array1[:,:] = numpy.random.uniform(low=0, high=10, size=array1.shape) for j in range(image1.getHeight()): for i in range(image1.getWidth()): self.assertEqual(image1.get(i, j), array1[j, i]) self.assertEqual(image2.get(i, j), array1[j, i]) def testInitializeMasks(self): val = 0x1234 msk = afwImage.MaskU(afwGeom.ExtentI(10, 10), val) self.assertEqual(msk.get(0, 0), val) def testSetGetMasks(self): self.assertEqual(self.mask1.get(0, 0), self.val1) def testOrMasks(self): self.mask2 |= self.mask1 self.mask1 |= self.val2 self.assertEqual(self.mask1.get(0, 0), self.val1 | self.val2) self.assertEqual(self.mask2.get(0, 0), self.val1 | self.val2) def testAndMasks(self): self.mask2 &= self.mask1 self.mask1 &= self.val2 self.assertEqual(self.mask1.get(0, 0), self.val1 & self.val2) self.assertEqual(self.mask1.get(0, 0), self.BAD | self.CR) self.assertEqual(self.mask2.get(0, 0), self.val1 & self.val2) def testXorMasks(self): self.mask2 ^= self.mask1 self.mask1 ^= self.val2 self.assertEqual(self.mask1.get(0, 0), self.val1 ^ self.val2) self.assertEqual(self.mask2.get(0, 0), self.val1 ^ self.val2) def testLogicalMasksMismatch(self): "Test logical operations on Masks of different sizes" i1 = afwImage.MaskU(afwGeom.ExtentI(100, 100)) i1.set(100) i2 = afwImage.MaskU(afwGeom.ExtentI(10, 10)) i2.set(10) def tst(i1, i2): i1 |= i2
    164 b3aef277 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst, i1, i2)
    ? ^^^ ^^^^^^ ------- ------ ---------
    167 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst, i1, i2)
    ? ^^ ^ def tst2(i1, i2): i1 &= i2
    167 a7aa0c91 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst2, i1, i2)
    ? ^^^ ^^^^^^ ------- ------ ---------
    170 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst2, i1, i2)
    ? ^^ ^ def tst2(i1, i2): i1 ^= i2
    170 0db2729c - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst2, i1, i2)
    ? ^^^ ^^^^^^ ------- ------ ---------
    173 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst2, i1, i2)
    ? ^^ ^ def testMaskPlanes(self): planes = self.Mask().getMaskPlaneDict() self.assertEqual(len(planes), self.Mask.getNumPlanesUsed()) for k in sorted(planes.keys()): self.assertEqual(planes[k], self.Mask.getMaskPlane(k)) def testCopyConstructors(self): dmask = afwImage.MaskU(self.mask1, True) # deep copy smask = afwImage.MaskU(self.mask1) # shallow copy self.mask1 |= 32767 # should only change dmask self.assertEqual(dmask.get(0, 0), self.val1) self.assertEqual(smask.get(0, 0), self.val1 | 32767) def testSubmasks(self): smask = afwImage.MaskU(self.mask1, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.ExtentI(3, 2)), afwImage.LOCAL) mask2 = afwImage.MaskU(smask.getDimensions()) mask2.set(666) smask <<= mask2 del smask del mask2 self.assertEqual(self.mask1.get(0, 0), self.val1) self.assertEqual(self.mask1.get(1, 1), 666) self.assertEqual(self.mask1.get(4, 1), self.val1) self.assertEqual(self.mask1.get(1, 2), 666) self.assertEqual(self.mask1.get(4, 2), self.val1) self.assertEqual(self.mask1.get(1, 3), self.val1) def testReadFits(self): if not self.maskFile: print >> sys.stderr, "Warning: afwdata is not set up; not running the FITS I/O tests" return nMaskPlanes0 = self.Mask.getNumPlanesUsed() mask = self.Mask(self.maskFile, 3) # will shift any unrecognised mask planes into unused slots self.assertEqual(mask.get(32, 1), 0) self.assertEqual(mask.get(50, 50), 0) self.assertEqual(mask.get(0, 0), (1<> sys.stderr, "Warning: afwdata is not set up; not running the FITS I/O tests" return hdu = 3 mask = afwImage.MaskU(self.maskFile, hdu, None, afwGeom.Box2I(), afwImage.LOCAL, True) if False: import lsst.afw.display.ds9 as ds9 ds9.mtv(mask) self.assertEqual(mask.get(32, 1), 0) self.assertEqual(mask.get(50, 50), 0) self.assertEqual(mask.get(0, 0), 1) def testWriteFits(self): if not self.maskFile: print >> sys.stderr, "Warning: afwdata is not set up; not running the FITS I/O tests" return nMaskPlanes0 = self.Mask.getNumPlanesUsed() mask = self.Mask(self.maskFile, 3) self.assertEqual(mask.get(32, 1), 0) self.assertEqual(mask.get(50, 50), 0) self.assertEqual(mask.get(0, 0), (1< 246 f8edfe90 - tmpFile = "foo.fits"
    249 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    247 f8edfe90 - mask.writeFits(tmpFile)
    250 c605dfcd + mask.writeFits(tmpFile)
    ? ++++
    248 f8edfe90 - #
    251 c605dfcd + #
    ? ++++
    249 f8edfe90 - # Read it back
    252 c605dfcd + # Read it back
    ? ++++
    250 f8edfe90 - #
    253 c605dfcd + #
    ? ++++
    251 0db2729c - md = lsst.daf.base.PropertySet()
    254 c605dfcd + md = lsst.daf.base.PropertySet()
    ? ++++
    252 0db2729c - rmask = self.Mask(tmpFile, 0, md)
    255 c605dfcd + rmask = self.Mask(tmpFile, 0, md)
    ? ++++
    253 4940d876 - os.remove(tmpFile)
    254 a7aa0c91 -
    256 c605dfcd +
    ? ++++
    255 a7aa0c91 - self.assertEqual(mask.get(0, 0), rmask.get(0, 0))
    257 c605dfcd + self.assertEqual(mask.get(0, 0), rmask.get(0, 0))
    ? ++++
    256 f8edfe90 - #
    258 c605dfcd + #
    ? ++++
    257 c727c044 - # Check that we wrote (and read) the metadata successfully
    259 c605dfcd + # Check that we wrote (and read) the metadata successfully
    ? ++++
    258 f8edfe90 - #
    260 c605dfcd + #
    ? ++++
    259 0db2729c - mp_ = "MP_" if True else self.Mask.maskPlanePrefix() # currently private
    261 c605dfcd + mp_ = "MP_" if True else self.Mask.maskPlanePrefix() # currently private
    ? ++++
    260 0db2729c - for (k, v) in self.Mask().getMaskPlaneDict().items():
    262 c605dfcd + for (k, v) in self.Mask().getMaskPlaneDict().items():
    ? ++++
    261 0db2729c - self.assertEqual(md.get(mp_ + k), v)
    263 c605dfcd + self.assertEqual(md.get(mp_ + k), v)
    ? ++++ def testReadWriteXY0(self): """Test that we read and write (X0, Y0) correctly""" mask = afwImage.MaskU(afwGeom.ExtentI(10, 20)) x0, y0 = 1, 2 mask.setXY0(x0, y0)
    269 4940d876 - tmpFile = "foo.fits"
    271 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    270 4940d876 - mask.writeFits(tmpFile)
    272 c605dfcd + mask.writeFits(tmpFile)
    ? ++++
    272 4940d876 - mask2 = mask.Factory(tmpFile)
    274 c605dfcd + mask2 = mask.Factory(tmpFile)
    ? ++++
    273 4940d876 - os.remove(tmpFile)
    275 4940d876 - self.assertEqual(mask2.getX0(), x0)
    276 c605dfcd + self.assertEqual(mask2.getX0(), x0)
    ? ++++
    276 4940d876 - self.assertEqual(mask2.getY0(), y0)
    277 c605dfcd + self.assertEqual(mask2.getY0(), y0)
    ? ++++ def testMaskInitialisation(self): dims = self.mask1.getDimensions() factory = self.mask1.Factory self.mask1.set(666) del self.mask1 # tempt C++ to reuse the memory self.mask1 = factory(dims) self.assertEqual(self.mask1.get(10, 10), 0) del self.mask1 self.mask1 = factory(afwGeom.ExtentI(20, 20)) self.assertEqual(self.mask1.get(10, 10), 0) def testBoundsChecking(self): """Check that pixel indexes are checked in python""" tsts = [] def tst(): self.mask1.get(-1, 0) tsts.append(tst) def tst(): self.mask1.get(0, -1) tsts.append(tst) def tst(): self.mask1.get(self.mask1.getWidth(), 0) tsts.append(tst) def tst(): self.mask1.get(0, self.mask1.getHeight()) tsts.append(tst) for tst in tsts:
    312 35b5e4e6 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst)
    ? ^^^ ^^^^^^ ------- ------ ---------
    313 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst)
    ? ^^ ^ def testCtorWithPlaneDefs(self): """Test that we can create a Mask with a given MaskPlaneDict""" FOO, val = "FOO", 2 mask = afwImage.MaskU(100, 200, {FOO : val} ) mpd = mask.getMaskPlaneDict() self.assertTrue(FOO in mpd.keys()) # n.b. there's a bug in swig 2.1.15; mpd[XXX] corrupts memory # if XXX isn't a valid key self.assertEqual(mpd[FOO], val) def testImageSlices(self): """Test image slicing, which generate sub-images using Box2I under the covers""" im = afwImage.MaskU(10, 20) im[-3:, -2:] = 0x4 im[4,10] = 0x2 sim = im[1:4, 6:10] sim[:] = 0x8 im[0:4, 0:4] = im[2:6, 8:12] if display: ds9.mtv(im) self.assertEqual(im.get(0, 6), 0) self.assertEqual(im.get(6, 17), 0) self.assertEqual(im.get(7, 18), 0x4) self.assertEqual(im.get(9, 19), 0x4) self.assertEqual(im.get(1, 6), 0x8) self.assertEqual(im.get(3, 9), 0x8) self.assertEqual(im.get(4, 10), 0x2) self.assertEqual(im.get(4, 9), 0) self.assertEqual(im.get(2, 2), 0x2) self.assertEqual(im.get(0, 0), 0x8) def testInterpret(self): """Interpretation of Mask values""" planes = self.Mask().getMaskPlaneDict() im = self.Mask(len(planes), 1) allBits = 0 for i, p in enumerate(planes): bitmask = self.Mask.getPlaneBitMask(p) allBits |= bitmask self.assertEqual(im.interpret(bitmask), p) im.getArray()[0,i] = bitmask self.assertEqual(im.getAsString(i,0), p) self.assertEqual(self.Mask.interpret(allBits), ",".join(planes.keys())) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class OldMaskTestCase(unittest.TestCase): """A test case for Mask (based on MaskU_1.cc); these are taken over from the DC2 fw tests and modified to run with the new (DC3) APIs""" def setUp(self): self.Mask = afwImage.MaskU # the class self.testMask = self.Mask(afwGeom.Extent2I(300, 400), 0) self.testMask.clearMaskPlaneDict() # reset so tests will be deterministic for p in ("CR", "BP"): self.Mask.addMaskPlane(p) self.region = afwGeom.Box2I(afwGeom.Point2I(100, 300), afwGeom.Extent2I(10, 40)) self.subTestMask = self.Mask(self.testMask, self.region, afwImage.LOCAL) if False: self.pixelList = afwImage.listPixelCoord() for x in range(0, 300): for y in range(300, 400, 20): self.pixelList.push_back(afwImage.PixelCoord(x, y)) def tearDown(self): del self.testMask del self.subTestMask del self.region def testPlaneAddition(self): """Test mask plane addition""" nplane = self.testMask.getNumPlanesUsed() for p in ("XCR", "XBP"): self.assertEqual(self.Mask.addMaskPlane(p), nplane, "Assigning plane %s" % (p)) nplane += 1 def pname(p): return "P%d" % p nextra = 8 for p in range(0, nextra): plane = self.Mask.addMaskPlane(pname(p)) for p in range(0, nextra): self.testMask.removeAndClearMaskPlane(pname(p)) self.assertEqual(nplane + nextra, self.Mask.getNumPlanesUsed(), "Adding and removing planes") for p in range(0, nextra): self.Mask.removeMaskPlane(pname(p)) self.assertEqual(nplane, self.testMask.getNumPlanesUsed(), "Adding and removing planes") def testMetadata(self): """Test mask plane metadata interchange with MaskPlaneDict""" # # Demonstrate that we can extract a MaskPlaneDict into metadata # metadata = lsst.daf.base.PropertySet() self.Mask.addMaskPlanesToMetadata(metadata) for (k, v) in self.Mask().getMaskPlaneDict().items(): self.assertEqual(metadata.getInt("MP_%s" % k), v) # # Now add another plane to metadata and make it appear in the mask Dict, albeit # in general at another location (hence the getNumPlanesUsed call) # metadata.addInt("MP_" + "Whatever", self.Mask.getNumPlanesUsed()) self.testMask.conformMaskPlanes(self.Mask.parseMaskPlaneMetadata(metadata)) for (k, v) in self.Mask().getMaskPlaneDict().items(): self.assertEqual(metadata.getInt("MP_%s" % k), v) def testPlaneOperations(self): """Test mask plane operations""" planes = self.Mask().getMaskPlaneDict() self.testMask.clearMaskPlane(planes['CR']) if False: for p in planes.keys(): self.testMask.setMaskPlaneValues(planes[p], self.pixelList) #printMaskPlane(self.testMask, planes['CR']) #print "\nClearing mask" self.testMask.clearMaskPlane(planes['CR']) #printMaskPlane(self.testMask, planes['CR']) def testPlaneRemoval(self): """Test mask plane removal""" def checkPlaneBP(): self.Mask.getMaskPlane("BP") testMask2 = self.Mask(self.testMask.getDimensions()) self.testMask = self.Mask(self.testMask.getDimensions()) self.testMask.removeAndClearMaskPlane("BP") d = testMask2.getMaskPlaneDict() checkPlaneBP() # still present in default mask self.assertTrue("BP" in testMask2.getMaskPlaneDict()) # should still be in testMask2 self.Mask.removeMaskPlane("BP") # remove from default mask too
    470 0db2729c - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException, checkPlaneBP)
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    471 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError, checkPlaneBP)
    ? ^^ ^ ^^ ^
    472 1805122f - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    473 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ lambda: self.Mask.removeMaskPlane("BP")) # Plane is already removed
    474 1805122f - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException,
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    475 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError,
    ? ^^ ^ ^^ ^ lambda: self.testMask.removeMaskPlane("RHL gets names right")) # self.Mask.clearMaskPlaneDict() p0 = self.Mask.addMaskPlane("P0") p1 = self.Mask.addMaskPlane("P1") p1 = self.Mask.addMaskPlane("P1") # a no-op -- readding a plane has no effect # # Check that removing default mask planes doesn't affect pre-existing planes # msk = self.Mask() nmask = len(msk.getMaskPlaneDict()) self.Mask.removeMaskPlane("P0") self.Mask.removeMaskPlane("P1") self.assertEqual(len(msk.getMaskPlaneDict()), nmask) del msk # # Check that removeAndClearMaskPlane can clear the default too # self.Mask.addMaskPlane("BP") self.testMask.removeAndClearMaskPlane("BP", True)
    496 3771b5eb - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException, checkPlaneBP)
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    497 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError, checkPlaneBP)
    ? ^^ ^ ^^ ^ def testInvalidPlaneOperations(self): """Test mask plane operations invalidated by Mask changes""" testMask3 = self.Mask(self.testMask.getDimensions()) name = "Great Timothy" self.Mask.addMaskPlane(name) testMask3.removeAndClearMaskPlane(name) self.Mask.getMaskPlane(name) # should be fine self.assertRaises(IndexError, lambda : testMask3.getMaskPlaneDict()[name]) def tst(): self.testMask |= testMask3
    513 3771b5eb - utilsTests.assertRaisesLsstCpp(self, pexExcept.RuntimeErrorException, tst)
    ? ^^^ ^^^^^^ ------- ------ ---------
    514 6fc1c3d1 + self.assertRaises(pexExcept.RuntimeError, tst)
    ? ^^ ^ self.Mask.addMaskPlane(name) # The dictionary should be back to the same state, so ... tst # ... assertion should not fail self.testMask.removeAndClearMaskPlane(name, True) self.Mask.addMaskPlane("Mario") # takes name's slot self.Mask.addMaskPlane(name)
    522 0db2729c - utilsTests.assertRaisesLsstCpp(self, pexExcept.RuntimeErrorException, tst)
    ? ^^^ ^^^^^^ ------- ------ ---------
    523 6fc1c3d1 + self.assertRaises(pexExcept.RuntimeError, tst)
    ? ^^ ^ def testInvalidPlaneOperations2(self): """Test mask plane operations invalidated by Mask changes""" testMask3 = self.Mask(self.testMask.getDimensions()) name = "Great Timothy" name2 = "Our Boss" self.Mask.addMaskPlane(name) self.Mask.addMaskPlane(name2) oldDict = testMask3.getMaskPlaneDict() # a description of the Mask's current dictionary for n in (name, name2): self.testMask.removeAndClearMaskPlane(n, True) self.Mask.addMaskPlane(name2) # added in opposite order to the planes in testMask3 self.Mask.addMaskPlane(name) self.assertNotEqual(self.testMask.getMaskPlaneDict()[name], oldDict[name]) def tst(): self.testMask |= testMask3 self.testMask.removeAndClearMaskPlane("BP")
    548 3771b5eb - utilsTests.assertRaisesLsstCpp(self, pexExcept.RuntimeErrorException, tst)
    ? ^^^ ^^^^^^ ------- ------ ---------
    549 6fc1c3d1 + self.assertRaises(pexExcept.RuntimeError, tst)
    ? ^^ ^ # # OK, that failed as it should. Fixup the dictionaries and try again # self.Mask.addMaskPlane("BP") testMask3.conformMaskPlanes(oldDict) # convert testMask3 from oldDict to current default self.testMask |= testMask3 # shouldn't throw def testConformMaskPlanes(self): """Test conformMaskPlanes() when the two planes are actually the same""" testMask3 = self.Mask(self.testMask.getDimensions()) name = "XXX" self.Mask.addMaskPlane(name) oldDict = testMask3.getMaskPlaneDict() testMask3.removeAndClearMaskPlane(name) # invalidates dictionary version testMask3.conformMaskPlanes(oldDict) self.testMask |= testMask3 def testConformMaskPlanes2(self): """Test conformMaskPlanes() when the two planes are different""" testMask3 = afwImage.MaskU(self.testMask.getDimensions()) name1 = "Great Timothy" name2 = "Our Boss" p1 = self.Mask.addMaskPlane(name1) p2 = self.Mask.addMaskPlane(name2) oldDict = self.testMask.getMaskPlaneDict() testMask3.setMaskPlaneValues(p1, 0, 5, 0) testMask3.setMaskPlaneValues(p2, 0, 5, 1) if display: im = afwImage.ImageF(testMask3.getDimensions()) ds9.mtv(im) # bug in ds9's Mask display; needs an Image first ds9.mtv(testMask3) self.assertEqual(testMask3.get(0, 0), testMask3.getPlaneBitMask(name1)) self.assertEqual(testMask3.get(0, 1), testMask3.getPlaneBitMask(name2)) self.testMask.removeAndClearMaskPlane(name1, True) self.testMask.removeAndClearMaskPlane(name2, True) self.Mask.addMaskPlane(name2) # added in opposite order to testMask3 self.Mask.addMaskPlane(name1) self.assertEqual(self.testMask.get(0, 0), 0) if display: ds9.mtv(im, frame=1) ds9.mtv(testMask3, frame=1) self.assertNotEqual(testMask3.get(0, 0), testMask3.getPlaneBitMask(name1)) self.assertNotEqual(testMask3.get(0, 1), testMask3.getPlaneBitMask(name2)) testMask3.conformMaskPlanes(oldDict) self.assertEqual(testMask3.get(0, 0), testMask3.getPlaneBitMask(name1)) self.assertEqual(testMask3.get(0, 1), testMask3.getPlaneBitMask(name2)) if display: ds9.mtv(im, frame=2) ds9.mtv(testMask3, frame=2) self.testMask |= testMask3 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= def printMaskPlane(mask, plane, xrange=range(250, 300, 10), yrange=range(300, 400, 20)): """Print parts of the specified plane of the mask""" if True: xrange = range(min(xrange), max(xrange), 25) yrange = range(min(yrange), max(yrange), 25) for x in xrange: for y in yrange: if False: # mask(x,y) confuses swig print x, y, mask(x, y), mask(x, y, plane) else: print x, y, mask(x, y, plane) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(OldMaskTestCase) # test suite from vw-based Masks suites += unittest.makeSuite(MaskTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    b3aef277

    commit b3aef277e273fdd2da5e145bf78da598ba6a3444
    Author: rhl 
    Date:   Tue Mar 17 14:49:25 2009 +0000
    
        Arithmetic ops of Images (and logicals on Masks) need to check image sizes; #711
    

    0db2729c

    commit 0db2729c943e400b3d741354fd8399f7fdde3431
    Author: Robert Lupton the Good 
    Date:   Thu Dec 22 15:06:34 2011 -0500
    
        Initial version that compiles with MaskDict implementation of private Mask dictionaries
    

    1805122f

    commit 1805122ff4ab1ee6379f9052d8941e99c02c9c41
    Author: Robert Lupton the Good 
    Date:   Wed Jan 4 18:03:29 2012 -0500
    
        Throw an exception if you try to remove a non-existent mask plane
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    4940d876

    commit 4940d876a0c927f4d36a74848ee3e542b9503fa6
    Author: rhl 
    Date:   Wed Mar 25 22:55:37 2009 +0000
    
        Save and restore Mask and Image (and thus MaskedImage and Exposure) (X0, Y0) when writing to FITS.  The information is written to an extra WCS, WCSA.  Switched WCSA and WCSB in ds9 display to be consistent with this
    

    c727c044

    commit c727c044d043f1d34d7af92167a6633bdb552b5c
    Author: rhl 
    Date:   Tue Nov 18 16:25:42 2008 +0000
    
        Change [Mm]etaData to [Mm]etadata as per #389
    

    76505c6a

    commit 76505c6a9851eb22e1080810712fbd4b07f2ef02
    Author: Paul Price 
    Date:   Fri Nov 18 17:15:21 2011 -0500
    
        Updating image directory.
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    35b5e4e6

    commit 35b5e4e6989c4fb4200064992a6d0c3e12576081
    Author: rhl 
    Date:   Sat Aug 28 12:08:21 2010 +0000
    
        Added bounds-checking pixel assessors (#1417/#1420)
    

    Commits in /Users/nate/repos_lsst/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    4bae7ca1

    commit 4bae7ca131d04a3f68e47748b0423617ffd33000
    Author: Paul Price 
    Date:   Wed Aug 6 16:40:49 2014 -0400
    
        tests: seed random number generator to make tests deterministic
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/image/ImagePca.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file
                     *
                     * @brief Utilities to support PCA analysis of a set of images
                     */
                    #include 
                    #include "boost/make_shared.hpp"
                    #include "lsst/utils/ieee.h"
                    
                    #include "Eigen/Core"
                    #include "Eigen/SVD"
                    #include "Eigen/Eigenvalues"
                    
                    #include "lsst/afw/image/ImagePca.h"
                    #include "lsst/afw/math/Statistics.h"
                    
                    namespace afwMath = lsst::afw::math;
                    
                    namespace lsst {
                    namespace afw {
                    namespace image {
                    
                    /// ctor
                    template 
                    ImagePca::ImagePca(bool constantWeight ///< Should all stars be weighted equally?
                                              ) :
                        _imageList(),
                        _fluxList(),
                        _dimensions(0,0),
                        _constantWeight(constantWeight),
                        _eigenValues(std::vector()),
                        _eigenImages(ImageList()) {
                    }
                    
                    /**
                     * Add an image to the set to be analyzed
                     *
    
    62 e56adc6b - * @throw lsst::pex::exceptions::LengthErrorException if all the images aren't the same size
    ? ---------
    62 21597d88 + * @throw lsst::pex::exceptions::LengthError if all the images aren't the same size
    */ template void ImagePca::addImage(typename ImageT::Ptr img, ///< Image to add to set double flux ///< Image's flux ) { if (_imageList.empty()) { _dimensions = img->getDimensions(); } else { if (getDimensions() != img->getDimensions()) { throw LSST_EXCEPT(
    73 3263f939 - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    73 21597d88 + lsst::pex::exceptions::LengthError,
    (boost::format("Dimension mismatch: saw %dx%d; expected %dx%d") % img->getWidth() % img->getHeight() % _dimensions.getX() % _dimensions.getY() ).str() ); } } if (flux == 0.0) {
    83 0391452c - throw LSST_EXCEPT(lsst::pex::exceptions::OutOfRangeException, "Flux may not be zero");
    ? ^^^^^^ ^
    83 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::OutOfRangeError, "Flux may not be zero");
    ? ^^ ^ } _imageList.push_back(img); _fluxList.push_back(flux); } /// Return the list of images being analyzed template typename ImagePca::ImageList ImagePca::getImageList() const { return _imageList; } /************************************************************************************************************/ /** * Return the mean of the images in ImagePca's list */ template typename ImageT::Ptr ImagePca::getMean() const { if (_imageList.empty()) {
    103 e56adc6b - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException, "You haven't provided any images");
    ? ---------
    103 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError, "You haven't provided any images");
    } typename ImageT::Ptr mean(new ImageT(getDimensions())); *mean = static_cast(0); for (typename ImageList::const_iterator ptr = _imageList.begin(), end = _imageList.end(); ptr != end; ++ptr) { *mean += **ptr; } *mean /= _imageList.size(); return mean; } /************************************************************************************************************/ /* * Analyze the images in an ImagePca, calculating the PCA decomposition (== Karhunen-Lo\`eve basis) * * The notation is that in chapter 7 of Gyula Szokoly's thesis at JHU */ namespace { template struct SortEvalueDecreasing : public std::binary_function const&, std::pair const&, bool> { bool operator()(std::pair const& a, std::pair const& b) { return a.first > b.first; // N.b. sort on greater } }; } template void ImagePca::analyze() { int const nImage = _imageList.size(); if (nImage == 0) {
    140 c345e316 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException, "No images provided for PCA analysis");
    ? ---------
    140 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError, "No images provided for PCA analysis");
    } /* * Eigen doesn't like 1x1 matrices, but we don't really need it to handle a single matrix... */ if (nImage == 1) { _eigenImages.clear(); _eigenImages.push_back(typename ImageT::Ptr(new ImageT(*_imageList[0], true))); _eigenValues.clear(); _eigenValues.push_back(1.0); return; } /* * Find the eigenvectors/values of the scalar product matrix, R' (Eq. 7.4) */ Eigen::MatrixXd R(nImage, nImage); // residuals' inner products double flux_bar = 0; // mean of flux for all regions for (int i = 0; i != nImage; ++i) { typename GetImage::type const& im_i = *GetImage::getImage(_imageList[i]); double const flux_i = getFlux(i); flux_bar += flux_i; for (int j = i; j != nImage; ++j) { typename GetImage::type const& im_j = *GetImage::getImage(_imageList[j]); double const flux_j = getFlux(j); double dot = innerProduct(im_i, im_j); if (_constantWeight) { dot /= flux_i*flux_j; } R(i, j) = R(j, i) = dot/nImage; } } flux_bar /= nImage; Eigen::SelfAdjointEigenSolver eVecValues(R); Eigen::MatrixXd const& Q = eVecValues.eigenvectors(); Eigen::VectorXd const& lambda = eVecValues.eigenvalues(); // // We need to sort the eigenValues, and remember the permutation we applied to the eigenImages // We'll use the vector lambdaAndIndex to achieve this // std::vector > lambdaAndIndex; // pairs (eValue, index) lambdaAndIndex.reserve(nImage); for (int i = 0; i != nImage; ++i) { lambdaAndIndex.push_back(std::make_pair(lambda(i), i)); } std::sort(lambdaAndIndex.begin(), lambdaAndIndex.end(), SortEvalueDecreasing()); // // Save the (sorted) eigen values // _eigenValues.clear(); _eigenValues.reserve(nImage); for (int i = 0; i != nImage; ++i) { _eigenValues.push_back(lambdaAndIndex[i].first); } // // Contruct the first ncomp eigenimages in basis // int ncomp = 100; // number of components to keep _eigenImages.clear(); _eigenImages.reserve(ncomp < nImage ? ncomp : nImage); for(int i = 0; i < ncomp; ++i) { if(i >= nImage) { continue; } int const ii = lambdaAndIndex[i].second; // the index after sorting (backwards) by eigenvalue typename ImageT::Ptr eImage(new ImageT(_dimensions)); *eImage = static_cast(0); for (int j = 0; j != nImage; ++j) { int const jj = lambdaAndIndex[j].second; // the index after sorting (backwards) by eigenvalue double const weight = Q(jj, ii)*(_constantWeight ? flux_bar/getFlux(jj) : 1); eImage->scaledPlus(weight, *_imageList[jj]); } _eigenImages.push_back(eImage); } } /************************************************************************************************************/ /* * */ namespace { /* * Fit a LinearCombinationKernel to an Image, allowing the coefficients of the components to vary * * return std::pair(best-fit kernel, std::pair(amp, chi^2)) */ template typename MaskedImageT::Image::Ptr fitEigenImagesToImage( typename ImagePca::ImageList const& eigenImages, // Eigen images int nEigen, // Number of eigen images to use MaskedImageT const& image // The image to be fit ) { typedef typename MaskedImageT::Image ImageT; if (nEigen == 0) {
    246 675dd594 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    246 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    "You must have at least one eigen image"); } else if (nEigen > static_cast(eigenImages.size())) {
    249 675dd594 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    249 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("You only have %d eigen images (you asked for %d)") % eigenImages.size() % nEigen).str()); } /* * Solve the linear problem image = sum x_i K_i + epsilon; we solve this for x_i by constructing the * normal equations, A x = b */ Eigen::MatrixXd A(nEigen, nEigen); Eigen::VectorXd b(nEigen); for (int i = 0; i != nEigen; ++i) { b(i) = innerProduct(*eigenImages[i]->getImage(), *image.getImage()); for (int j = i; j != nEigen; ++j) { A(i, j) = A(j, i) = innerProduct(*eigenImages[i]->getImage(), *eigenImages[j]->getImage()); } } Eigen::VectorXd x(nEigen); if (nEigen == 1) { x(0) = b(0)/A(0, 0); } else { x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b); } // // Accumulate the best-fit-image in bestFitImage // typename ImageT::Ptr bestFitImage = boost::make_shared(eigenImages[0]->getDimensions()); for (int i = 0; i != nEigen; ++i) { bestFitImage->scaledPlus(x[i], *eigenImages[i]->getImage()); } return bestFitImage; } /************************************************************************************************************/ template double do_updateBadPixels(detail::basic_tag const&, typename ImagePca::ImageList const&, std::vector const&, typename ImagePca::ImageList const&, unsigned long, int const) { return 0.0; } template double do_updateBadPixels( detail::MaskedImage_tag const&, typename ImagePca::ImageList const& imageList, std::vector const& fluxes, // fluxes of images typename ImagePca::ImageList const& eigenImages, // Eigen images unsigned long mask, ///< Mask defining bad pixels int const ncomp ///< Number of components to use in estimate ) { int const nImage = imageList.size(); if (nImage == 0) {
    310 675dd594 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    310 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    "Please provide at least one Image for me to update"); } geom::Extent2I dimensions = imageList[0]->getDimensions(); int const height = dimensions.getY(); double maxChange = 0.0; // maximum change to the input images if (ncomp == 0) { // use mean of good pixels typename ImageT::Image mean(dimensions); // desired mean image image::Image weight(mean.getDimensions()); // weight of each pixel for (int i = 0; i != nImage; ++i) { double const flux_i = fluxes[i]; for (int y = 0; y != height; ++y) { typename ImageT::const_x_iterator iptr = imageList[i]->row_begin(y); image::Image::x_iterator wptr = weight.row_begin(y); for (typename ImageT::Image::x_iterator mptr = mean.row_begin(y), end = mean.row_end(y); mptr != end; ++mptr, ++iptr, ++wptr) { if (!(iptr.mask() & mask) && iptr.variance() > 0.0) { typename ImageT::Image::Pixel value = iptr.image()/flux_i; float const var = iptr.variance()/(flux_i*flux_i); float const ivar = 1.0/var; if (lsst::utils::isfinite(value*ivar)) { *mptr += value*ivar; *wptr += ivar; } } } } } // // Calculate mean // for (int y = 0; y != height; ++y) { image::Image::x_iterator wptr = weight.row_begin(y); for (typename ImageT::Image::x_iterator mptr = mean.row_begin(y), end = mean.row_end(y); mptr != end; ++mptr, ++wptr) { if (*wptr == 0.0) { // oops, no good values ; } else { *mptr /= *wptr; } } } // // Replace bad values by mean // for (int i = 0; i != nImage; ++i) { double const flux_i = fluxes[i]; for (int y = 0; y != height; ++y) { typename ImageT::x_iterator iptr = imageList[i]->row_begin(y); for (typename ImageT::Image::x_iterator mptr = mean.row_begin(y), end = mean.row_end(y); mptr != end; ++mptr, ++iptr) { if ((iptr.mask() & mask)) { double const delta = ::fabs(flux_i*(*mptr) - iptr.image()); if (delta > maxChange) { maxChange = delta; } iptr.image() = flux_i*(*mptr); } } } } } else { if (ncomp > static_cast(eigenImages.size())) {
    379 675dd594 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    379 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("You only have %d eigen images (you asked for %d)") % eigenImages.size() % ncomp).str()); } for (int i = 0; i != nImage; ++i) { typename ImageT::Image::Ptr fitted = fitEigenImagesToImage(eigenImages, ncomp, *imageList[i]); for (int y = 0; y != height; ++y) { typename ImageT::x_iterator iptr = imageList[i]->row_begin(y); for (typename ImageT::Image::const_x_iterator fptr = fitted->row_begin(y), end = fitted->row_end(y); fptr != end; ++fptr, ++iptr) { if (iptr.mask() & mask) { double const delta = ::fabs(*fptr - iptr.image()); if (delta > maxChange) { maxChange = delta; } iptr.image() = *fptr; } } } } } return maxChange; } } /** * Update the bad pixels (i.e. those for which (value & mask) != 0) based on the current PCA decomposition; * if none is available, use the mean of the good pixels * * \return the maximum change made to any pixel * * N.b. the work is actually done in do_updateBadPixels as the code only makes sense and compiles when we are * doing a PCA on a set of MaskedImages */ template double ImagePca::updateBadPixels( unsigned long mask, ///< Mask defining bad pixels int const ncomp ///< Number of components to use in estimate ) { return do_updateBadPixels(typename ImageT::image_category(), _imageList, _fluxList, _eigenImages, mask, ncomp); } /*******************************************************************************************************/ namespace { template struct IsSame { IsSame(T const&, U const&) {} bool operator()() { return false; } }; template struct IsSame { IsSame(T const& im1, T const& im2) : _same(im1.row_begin(0) == im2.row_begin(0)) {} bool operator()() { return _same; } private: bool _same; }; // Test if two Images are identical; they need not be of the same type template bool imagesAreIdentical(Image1T const& im1, Image2T const& im2) { return IsSame(im1, im2)(); } } /** * Calculate the inner product of two %images * @return The inner product
    451 e56adc6b - * @throw lsst::pex::exceptions::LengthErrorException if all the images aren't the same size
    ? ---------
    451 21597d88 + * @throw lsst::pex::exceptions::LengthError if all the images aren't the same size
    */ template double innerProduct(Image1T const& lhs, ///< first image Image2T const& rhs, ///< Other image to dot with first int border ///< number of pixels to ignore around the edge ) { if (lhs.getWidth() <= 2*border || lhs.getHeight() <= 2*border) {
    459 74f2a138 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    459 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("All image pixels are in the border of width %d: %dx%d") % border % lhs.getWidth() % lhs.getHeight()).str()); } double sum = 0.0; // // Handle I.I specially for efficiency, and to avoid advancing the iterator twice // if (imagesAreIdentical(lhs, rhs)) { for (int y = border; y != lhs.getHeight() - border; ++y) { for (typename Image1T::const_x_iterator lptr = lhs.row_begin(y) + border, lend = lhs.row_end(y) - border; lptr != lend; ++lptr) { typename Image1T::Pixel val = *lptr; if (lsst::utils::isfinite(val)) { sum += val*val; } } } } else { if (lhs.getDimensions() != rhs.getDimensions()) {
    480 e56adc6b - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    480 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Dimension mismatch: %dx%d v. %dx%d") % lhs.getWidth() % lhs.getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } for (int y = border; y != lhs.getHeight() - border; ++y) { typename Image2T::const_x_iterator rptr = rhs.row_begin(y) + border; for (typename Image1T::const_x_iterator lptr = lhs.row_begin(y) + border, lend = lhs.row_end(y) - border; lptr != lend; ++lptr, ++rptr) { double const tmp = (*lptr)*(*rptr); if (lsst::utils::isfinite(tmp)) { sum += tmp; } } } } return sum; } /************************************************************************************************************/ // // Explicit instantiations // /// \cond #define INSTANTIATE(T) \ template class ImagePca >; \ template double innerProduct(Image const&, Image const&, int); \ template class ImagePca >; #define INSTANTIATE2(T, U) \ template double innerProduct(Image const&, Image const&, int); \ template double innerProduct(Image const&, Image const&, int); INSTANTIATE(boost::uint16_t) INSTANTIATE(boost::uint64_t) INSTANTIATE(int) INSTANTIATE(float) INSTANTIATE(double) INSTANTIATE2(float, double) // the two types must be different /// \endcond }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    c345e316

    commit c345e31611df4fc15f7c5cc4ecd15c5d8b6ef343
    Author: Paul Price 
    Date:   Fri Nov 16 15:54:01 2012 -0500
    
        Fix exception message that's annoyed me for ages.
    

    0391452c

    commit 0391452c28d0db8ab5e6b6bac1118d94f9fd7251
    Author: rhl 
    Date:   Thu Mar 5 22:04:21 2009 +0000
    
        Must specify (non-zero) flux with Images
    

    e56adc6b

    commit e56adc6b781a9b8ff238752892a331f94a4a6a35
    Author: rhl 
    Date:   Tue Mar 3 05:41:30 2009 +0000
    
        Initial support for PCA of images
    

    675dd594

    commit 675dd594e9b6b36cd77a3fa3f37cf99afbe33400
    Author: rhl 
    Date:   Fri Aug 20 16:59:47 2010 +0000
    
        Add ability to build an ImagePca from MaskedImages.  In this case, the method updateBadPixels can be used to clean the input images (iterating this method implements gappy PCA; cf meas::algorithms::createKernelFromPsfCandidates)
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    74f2a138

    commit 74f2a138f1ecc71f1f690c3e7b85dd3400546db8
    Author: rhl 
    Date:   Wed Apr 28 22:34:58 2010 +0000
    
        Allow innerProduct to work with images of different types
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/math/Statistics.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * @file
                     *
                     * @brief Support statistical operations on images
                     *
                     * @author Steve Bickerton
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    #include "boost/shared_ptr.hpp"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/math/Statistics.h"
                    #include "lsst/utils/ieee.h"
                    #include "lsst/afw/geom/Angle.h"
                    
                    using namespace std;
                    namespace afwImage = lsst::afw::image;
                    namespace afwMath = lsst::afw::math;
                    namespace afwGeom = lsst::afw::geom;
                    namespace pexExceptions = lsst::pex::exceptions;
                    
                    namespace {
                        double const NaN = std::numeric_limits::quiet_NaN();
                        double const MAX_DOUBLE = std::numeric_limits::max();
                        double const IQ_TO_STDEV = 0.741301109252802;   // 1 sigma in units of iqrange (assume Gaussian)
                    
                        /**
                         * @brief A boolean functor which always returns true (for templated conditionals)
                         */
                        class AlwaysTrue {
                        public:
                            template
                            bool operator()(T) const {
                                return true;
                            }
                            template
                            bool operator()(Ta, Tb) const {
                                return true;
                            }
                            template
                            bool operator()(Ta, Tb, Tc) const {
                                return true;
                            }
                        };
                    
                        /**
                         * @brief A boolean functor which always returns false (for templated conditionals)
                         */
                        class AlwaysFalse {
                        public:
                            template
                            bool operator()(T) const {
                                return false;
                            }
                            template
                            bool operator()(Ta, Tb) const {
                                return false;
                            }
                            template
                            bool operator()(Ta, Tb, Tc) const {
                                return false;
                            }
                        };
                    
                        /**
    
    94 f2c3ad9b - * @brief A boolean functor to check for NaN (for templated conditionals)
    94 6e8b043b + * @brief A boolean functor to check for NaN or infinity (for templated conditionals)
    ? ++++++++++++ */ class CheckFinite { public: template bool operator()(T val) const {
    100 f2c3ad9b - return !lsst::utils::isnan(static_cast(val));
    ? - ^^
    100 6e8b043b + return lsst::utils::isfinite(static_cast(val));
    ? ++ ^^^ } }; /** * @brief A boolean functor to test val < min (for templated conditionals) */ class CheckValueLtMin { public: template bool operator()(Tval val, Tmin min) const { return (static_cast(val) < min); } }; /** * @brief A boolean functor to test val > max (for templated conditionals) */ class CheckValueGtMax { public: template bool operator()(Tval val, Tmax max) const { return (static_cast(val) > max); } }; /** * @brief A boolean functor to test |val| < cliplimit (for templated conditionals) */ class CheckClipRange { public: template bool operator()(Tval val, Tcen center, Tmax cliplimit) const { Tmax tmp = fabs(val - center); return (tmp <= cliplimit); } }; // define some abbreviated typenames for the test templates typedef CheckFinite ChkFin; typedef CheckValueLtMin ChkMin; typedef CheckValueGtMax ChkMax; typedef CheckClipRange ChkClip; typedef AlwaysTrue AlwaysT; typedef AlwaysFalse AlwaysF; // Return the variance of a variance, assuming a Gaussian // There is apparently an attempt to correct for bias in the factor (n - 1)/n. RHL inline double varianceError(double const variance, int const n) { return 2*(n - 1)*variance*variance/static_cast(n*n); } /*********************************************************************************************************/ // return type for processPixels typedef boost::tuple StandardReturn; /* * Functions which convert the booleans into calls to the proper templated types, one type per * recursion level */ /* * This function handles the inner summation loop, with tests templated * * The idea here is to allow different conditionals in the inner loop, but avoid repeating code. * Each test is actually a functor which is handled through a template. If the * user requests a test (eg check for NaNs), the function is instantiated with the appropriate functor. * Otherwise, an 'AlwaysTrue' or 'AlwaysFalse' object is passed in. The compiler then compiles-out * a test which is always false, or removes the conditional for a test which is always true. */ template StandardReturn processPixels(ImageT const &img, MaskT const &msk, VarianceT const &var, WeightT const &weights, int const, int const nCrude, int const stride, double const meanCrude, double const cliplimit, bool const weightsAreMultiplicative, int const andMask,
    194 6eed36a1 - bool const calcErrorFromInputVariance,
    ? -
    194 692d7033 + bool const calcErrorFromInputVariance
    195 6eed36a1 - std::vector const & maskPropagationThresholds
    ) { int n = 0; double sumw = 0.0; // sum(weight) (N.b. weight will be 1.0 if !useWeights) double sumw2 = 0.0; // sum(weight^2) double sumx = 0; // sum(data*weight) double sumx2 = 0; // sum(data*weight^2) #if 1 double sumvw2 = 0.0; // sum(variance*weight^2) #endif double min = (nCrude) ? meanCrude : MAX_DOUBLE; double max = (nCrude) ? meanCrude : -MAX_DOUBLE; afwImage::MaskPixel allPixelOrMask = 0x0;
    210 6eed36a1 -
    211 6eed36a1 - std::vector rejectedWeightsByBit(maskPropagationThresholds.size(), 0.0);
    for (int iY = 0; iY < img.getHeight(); iY += stride) { typename MaskT::x_iterator mptr = msk.row_begin(iY); typename VarianceT::x_iterator vptr = var.row_begin(iY); typename WeightT::x_iterator wptr = weights.row_begin(iY); for (typename ImageT::x_iterator ptr = img.row_begin(iY), end = ptr + img.getWidth(); ptr != end; ++ptr, ++mptr, ++vptr, ++wptr) { if (IsFinite()(*ptr) && !(*mptr & andMask) && InClipRange()(*ptr, meanCrude, cliplimit) ) { // clip double const delta = (*ptr - meanCrude); if (useWeights) { double weight = *wptr; if (weightsAreMultiplicative) { ; } else { if (*wptr <= 0) { continue; } weight = 1/weight; } sumw += weight; sumw2 += weight*weight; sumx += weight*delta; sumx2 += weight*delta*delta; if (calcErrorFromInputVariance) { double const var = *vptr; sumvw2 += var*weight*weight; } } else { sumx += delta; sumx2 += delta*delta; if (calcErrorFromInputVariance) { double const var = *vptr; sumvw2 += var; } } allPixelOrMask |= *mptr; if (HasValueLtMin()(*ptr, min)) { min = *ptr; } if (HasValueGtMax()(*ptr, max)) { max = *ptr; } n++;
    262 6eed36a1 - } else { // pixel has been clipped, rejected, etc.
    263 6eed36a1 - for (int bit = 0, nBits=maskPropagationThresholds.size(); bit < nBits; ++bit) {
    264 6eed36a1 - lsst::afw::image::MaskPixel mask = 1 << bit;
    265 6eed36a1 - if (*mptr & mask) {
    266 6eed36a1 - double weight = 1.0;
    267 6eed36a1 - if (useWeights) {
    268 6eed36a1 - weight = *wptr;
    269 6eed36a1 - if (!weightsAreMultiplicative) {
    270 6eed36a1 - if (*wptr <= 0) {
    271 6eed36a1 - continue;
    272 6eed36a1 - }
    273 6eed36a1 - weight = 1.0 / weight;
    274 6eed36a1 - }
    275 6eed36a1 - }
    276 6eed36a1 - rejectedWeightsByBit[bit] += weight;
    277 6eed36a1 - }
    278 6eed36a1 - }
    } } } if (n == 0) { min = NaN; max = NaN; } // estimate of population mean and variance. double mean, variance; if (!useWeights) { sumw = sumw2 = n; }
    292 692d7033 -
    293 6eed36a1 - for (int bit = 0, nBits=maskPropagationThresholds.size(); bit < nBits; ++bit) {
    294 6eed36a1 - double hypotheticalTotalWeight = sumw + rejectedWeightsByBit[bit];
    295 6eed36a1 - rejectedWeightsByBit[bit] /= hypotheticalTotalWeight;
    296 6eed36a1 - if (rejectedWeightsByBit[bit] > maskPropagationThresholds[bit]) {
    297 6eed36a1 - allPixelOrMask |= (1 << bit);
    298 6eed36a1 - }
    299 6eed36a1 - }
    300 6eed36a1 -
    // N.b. if sumw == 0 or sumw*sumw == sumw2 (e.g. n == 1) we'll get NaNs // N.b. the estimator of the variance assumes that the sample points all have the same variance; // otherwise, what is it that we're estimating? mean = sumx/sumw; variance = sumx2/sumw - ::pow(mean, 2); // biased estimator variance *= sumw*sumw/(sumw*sumw - sumw2); // debias double meanVar; // (standard error of mean)^2 if (calcErrorFromInputVariance) { meanVar = sumvw2/(sumw*sumw); } else { meanVar = variance*sumw2/(sumw*sumw); } double varVar = varianceError(variance, n); // error in variance; incorrect if useWeights is true sumx += sumw*meanCrude; mean += meanCrude; return StandardReturn(n, sumx, afwMath::Statistics::Value(mean, meanVar), afwMath::Statistics::Value(variance, varVar), min, max, allPixelOrMask); } template StandardReturn processPixels(ImageT const &img, MaskT const &msk, VarianceT const &var, WeightT const &weights, int const flags, int const nCrude, int const stride, double const meanCrude, double const cliplimit, bool const weightsAreMultiplicative, int const andMask, bool const calcErrorFromInputVariance,
    344 6eed36a1 - bool doGetWeighted,
    ? -
    315 b136e57d + bool doGetWeighted
    345 6eed36a1 - std::vector const & maskPropagationThresholds
    ) { if (doGetWeighted) { return processPixels( img, msk, var, weights, flags, nCrude, 1, meanCrude, cliplimit, weightsAreMultiplicative, andMask,
    352 6eed36a1 - calcErrorFromInputVariance, maskPropagationThresholds);
    ? ---------------------------
    322 692d7033 + calcErrorFromInputVariance);
    } else { return processPixels( img, msk, var, weights, flags, nCrude, 1, meanCrude, cliplimit, weightsAreMultiplicative, andMask,
    357 6eed36a1 - calcErrorFromInputVariance, maskPropagationThresholds);
    ? ---------------------------
    327 692d7033 + calcErrorFromInputVariance);
    } } template StandardReturn processPixels(ImageT const &img, MaskT const &msk, VarianceT const &var, WeightT const &weights, int const flags, int const nCrude, int const stride, double const meanCrude, double const cliplimit, bool const weightsAreMultiplicative, int const andMask, bool const calcErrorFromInputVariance, bool doCheckFinite,
    380 6eed36a1 - bool doGetWeighted,
    ? -
    350 b136e57d + bool doGetWeighted
    381 6eed36a1 - std::vector const & maskPropagationThresholds
    ) { if (doCheckFinite) { return processPixels( img, msk, var, weights, flags, nCrude, 1, meanCrude, cliplimit, weightsAreMultiplicative, andMask, calcErrorFromInputVariance,
    389 6eed36a1 - doGetWeighted, maskPropagationThresholds);
    ? ---------------------------
    358 b136e57d + doGetWeighted);
    } else { return processPixels( img, msk, var, weights, flags, nCrude, 1, meanCrude, cliplimit, weightsAreMultiplicative, andMask, calcErrorFromInputVariance,
    395 6eed36a1 - doGetWeighted, maskPropagationThresholds);
    ? ---------------------------
    364 b136e57d + doGetWeighted);
    396 ba95a979 - }
    397 161df91c - }
    365 ba95a979 + }
    ? ++++
    366 161df91c + }
    399 f2c3ad9b - /* =========================================================================
    368 89372b8c + /** =========================================================================
    ? + * @brief Compute the standard stats: mean, variance, min, max * * @param img an afw::Image to compute the stats over * @param flags an integer (bit field indicating which statistics are to be computed * * @note An overloaded version below is used to get clipped versions */ template StandardReturn getStandard(ImageT const &img, // image MaskT const &msk, // mask VarianceT const &var, // variance WeightT const &weights, // weights to apply to each pixel int const flags, // what to measure bool const weightsAreMultiplicative, // weights are multiplicative (not inverse) int const andMask, // mask of bad pixels bool const calcErrorFromInputVariance, // estimate errors from variance bool doCheckFinite, // check for NaN/Inf
    417 6eed36a1 - bool doGetWeighted, // use the weights
    ? ^
    386 692d7033 + bool doGetWeighted // use the weights
    ? ^
    418 6eed36a1 - std::vector const & maskPropagationThresholds
    ) { // ===================================================== // a crude estimate of the mean, used for numerical stability of variance int nCrude = 0; double meanCrude = 0.0; // for small numbers of values, use a small stride int const nPix = img.getWidth()*img.getHeight(); int strideCrude; if (nPix < 100) { strideCrude = 2; } else { strideCrude = 10; } double cliplimit = -1; // unused StandardReturn values = processPixels( img, msk, var, weights, flags, nCrude, strideCrude, meanCrude, cliplimit, weightsAreMultiplicative, andMask, calcErrorFromInputVariance,
    441 6eed36a1 - doCheckFinite, doGetWeighted,
    ? ^
    409 3a0c19cc + doCheckFinite, doGetWeighted);
    ? ^^
    442 6eed36a1 - maskPropagationThresholds);
    nCrude = values.get<0>(); double sumCrude = values.get<1>(); meanCrude = 0.0; if (nCrude > 0) { meanCrude = sumCrude/nCrude; } // ======================================================= // Estimate the full precision variance using that crude mean // - get the min and max as well if (flags & (afwMath::MIN | afwMath::MAX)) { return processPixels( img, msk, var, weights, flags, nCrude, 1, meanCrude, cliplimit, weightsAreMultiplicative, andMask, calcErrorFromInputVariance,
    461 6eed36a1 - true, doGetWeighted, maskPropagationThresholds);
    ? ---------------------------
    428 3a0c19cc + true, doGetWeighted);
    } else { return processPixels( img, msk, var, weights, flags, nCrude, 1, meanCrude, cliplimit, weightsAreMultiplicative, andMask, calcErrorFromInputVariance,
    468 6eed36a1 - doCheckFinite, doGetWeighted, maskPropagationThresholds);
    ? ---------------------------
    435 3a0c19cc + doCheckFinite, doGetWeighted);
    469 3a0c19cc - }
    470 161df91c - }
    436 3a0c19cc + }
    ? ++++
    437 161df91c + }
    472 f2c3ad9b - /* ==========================================================
    439 89372b8c + /** ==========================================================
    ? + * * @brief A routine to get standard stats: mean, variance, min, max with * clipping on std::pair = center, cliplimit */ template StandardReturn getStandard(ImageT const &img, // image MaskT const &msk, // mask VarianceT const &var, // variance WeightT const &weights, // weights to apply to each pixel int const flags, // what to measure std::pair const clipinfo, // the center and cliplimit for the // first clip iteration bool const weightsAreMultiplicative, // weights are multiplicative (not inverse) int const andMask, // mask of bad pixels bool const calcErrorFromInputVariance, // estimate errors from variance bool doCheckFinite, // check for NaN/Inf
    489 6eed36a1 - bool doGetWeighted, // use the weights,
    ? ^ -
    456 692d7033 + bool doGetWeighted // use the weights
    ? ^
    490 6eed36a1 - std::vector const & maskPropagationThresholds
    ) { double const center = clipinfo.first; double const cliplimit = clipinfo.second; if (lsst::utils::isnan(center) || lsst::utils::isnan(cliplimit)) { return StandardReturn(0, NaN, afwMath::Statistics::Value(NaN, NaN), afwMath::Statistics::Value(NaN, NaN), NaN, NaN, ~0x0); } // ======================================================= // Estimate the full precision variance using that crude mean int const stride = 1; int nCrude = 0; if (flags & (afwMath::MIN | afwMath::MAX)) { return processPixels( img, msk, var, weights, flags, nCrude, stride, center, cliplimit, weightsAreMultiplicative, andMask, calcErrorFromInputVariance,
    513 6eed36a1 - true, doGetWeighted, maskPropagationThresholds);
    ? ---------------------------
    479 3a0c19cc + true, doGetWeighted);
    } else { // fast loop ... just the mean & variance return processPixels( img, msk, var, weights, flags, nCrude, stride, center, cliplimit, weightsAreMultiplicative, andMask, calcErrorFromInputVariance,
    520 6eed36a1 - doCheckFinite, doGetWeighted, maskPropagationThresholds);
    ? ---------------------------
    486 3a0c19cc + doCheckFinite, doGetWeighted);
    521 f2c3ad9b - }
    522 161df91c - }
    487 f2c3ad9b + }
    ? ++++
    488 161df91c + }
    524 f2c3ad9b - /* percentile()
    490 89372b8c + /** percentile()
    ? + * * @brief A wrapper using the nth_element() built-in to compute percentiles for an image * * @param img an afw::Image * @param quartile the desired percentile. * */ template double percentile(std::vector &img, double const fraction) { assert (fraction >= 0.0 && fraction <= 1.0); int const n = img.size(); if (n > 1) { double const idx = fraction*(n - 1); // interpolate linearly between the adjacent values // For efficiency: // - if we're asked for a fraction > 0.5, // we'll do the second partial sort on shorter (upper) portion // - otherwise, the shorter portion will be the lower one, we'll partial-sort that. int const q1 = static_cast(idx); int const q2 = q1 + 1; typename std::vector::iterator mid1 = img.begin() + q1; typename std::vector::iterator mid2 = img.begin() + q2; if (fraction > 0.5) { std::nth_element(img.begin(), mid1, img.end()); std::nth_element(mid1, mid2, img.end()); } else { std::nth_element(img.begin(), mid2, img.end()); std::nth_element(img.begin(), mid1, mid2); } double val1 = static_cast(*mid1); double val2 = static_cast(*mid2); double w1 = (static_cast(q2) - idx); double w2 = (idx - static_cast(q1)); return w1*val1 + w2*val2; } else if (n == 1) { return img[0]; } else { return NaN; } }
    577 f2c3ad9b - /* medianAndQuartiles()
    543 89372b8c + /** medianAndQuartiles()
    ? + * * @brief A wrapper using the nth_element() built-in to compute median and Quartiles for an image * * @param img an afw::Image * @param quartile the desired percentile. * */ typedef boost::tuple MedianQuartileReturn; template MedianQuartileReturn medianAndQuartiles(std::vector &img) { int const n = img.size(); if (n > 1) { double const idx50 = 0.50*(n - 1); double const idx25 = 0.25*(n - 1); double const idx75 = 0.75*(n - 1); // For efficiency: // - partition at 50th, then partition the two half further to get 25th and 75th // - to get the adjacent points (for interpolation), partition between 25/50, 50/75, 75/end // these should be much smaller partitions int const q50a = static_cast(idx50); int const q50b = q50a + 1; int const q25a = static_cast(idx25); int const q25b = q25a + 1; int const q75a = static_cast(idx75); int const q75b = q75a + 1; typename std::vector::iterator mid50a = img.begin() + q50a; typename std::vector::iterator mid50b = img.begin() + q50b; typename std::vector::iterator mid25a = img.begin() + q25a; typename std::vector::iterator mid25b = img.begin() + q25b; typename std::vector::iterator mid75a = img.begin() + q75a; typename std::vector::iterator mid75b = img.begin() + q75b; // get the 50th percentile, then get the 25th and 75th on the smaller partitions std::nth_element(img.begin(), mid50a, img.end()); std::nth_element(mid50a, mid75a, img.end()); std::nth_element(img.begin(), mid25a, mid50a); // and the adjacent points for each ... use the smallest segments available. std::nth_element(mid50a, mid50b, mid75a); std::nth_element(mid25a, mid25b, mid50a); std::nth_element(mid75a, mid75b, img.end()); // interpolate linearly between the adjacent values double val50a = static_cast(*mid50a); double val50b = static_cast(*mid50b); double w50a = (static_cast(q50b) - idx50); double w50b = (idx50 - static_cast(q50a)); double median = w50a*val50a + w50b*val50b; double val25a = static_cast(*mid25a); double val25b = static_cast(*mid25b); double w25a = (static_cast(q25b) - idx25); double w25b = (idx25 - static_cast(q25a)); double q1 = w25a*val25a + w25b*val25b; double val75a = static_cast(*mid75a); double val75b = static_cast(*mid75b); double w75a = (static_cast(q75b) - idx75); double w75b = (idx75 - static_cast(q75a)); double q3 = w75a*val75a + w75b*val75b; return MedianQuartileReturn(median, q1, q3); } else if (n == 1) { return MedianQuartileReturn(img[0], img[0], img[0]); } else { return MedianQuartileReturn(NaN, NaN, NaN); } } /*********************************************************************************************************/ /** * A function to copy an image into a vector * * This is used for percentile and iq_range as these must reorder the values. * Because it loops over the pixels, it's been templated over the NaN test to avoid * code repetition of the loops. */ template boost::shared_ptr > makeVectorCopy(ImageT const &img, MaskT const &msk, VarianceT const &, int const andMask ) { // Note need to keep track of allPixelOrMask here ... processPixels() does that // and it always gets called boost::shared_ptr > imgcp(new std::vector(0)); for (int i_y = 0; i_y < img.getHeight(); ++i_y) { typename MaskT::x_iterator mptr = msk.row_begin(i_y); for (typename ImageT::x_iterator ptr = img.row_begin(i_y), end = img.row_end(i_y); ptr != end; ++ptr) { if (IsFinite()(*ptr) && !(*mptr & andMask)) { imgcp->push_back(*ptr); } ++mptr; } } return imgcp; } }
    688 161df91c -
    689 6eed36a1 -
    690 6eed36a1 -
    691 6eed36a1 - double afwMath::StatisticsControl::getMaskPropagationThreshold(int bit) const {
    692 6eed36a1 - int oldSize = _maskPropagationThresholds.size();
    693 6eed36a1 - if (oldSize < bit) {
    694 6eed36a1 - return 1.0;
    695 6eed36a1 - }
    696 6eed36a1 - return _maskPropagationThresholds[bit];
    697 6eed36a1 - }
    698 6eed36a1 -
    699 6eed36a1 - void afwMath::StatisticsControl::setMaskPropagationThreshold(int bit, double threshold) {
    700 6eed36a1 - int oldSize = _maskPropagationThresholds.size();
    701 6eed36a1 - if (oldSize <= bit) {
    702 6eed36a1 - int newSize = bit + 1;
    703 6eed36a1 - _maskPropagationThresholds.resize(newSize);
    704 6eed36a1 - for (int i = oldSize; i < bit; ++i) {
    705 6eed36a1 - _maskPropagationThresholds[i] = 1.0;
    706 6eed36a1 - }
    707 6eed36a1 - }
    708 6eed36a1 - _maskPropagationThresholds[bit] = threshold;
    709 6eed36a1 - }
    710 6eed36a1 -
    /** * @brief Conversion function to switch a string to a Property (see Statistics.h) */ afwMath::Property afwMath::stringToStatisticsProperty(std::string const property) { static std::map statisticsProperty; if (statisticsProperty.size() == 0) { statisticsProperty["NOTHING"] = NOTHING; statisticsProperty["ERRORS"] = ERRORS; statisticsProperty["NPOINT"] = NPOINT; statisticsProperty["MEAN"] = MEAN; statisticsProperty["STDEV"] = STDEV; statisticsProperty["VARIANCE"] = VARIANCE; statisticsProperty["MEDIAN"] = MEDIAN; statisticsProperty["IQRANGE"] = IQRANGE; statisticsProperty["MEANCLIP"] = MEANCLIP; statisticsProperty["STDEVCLIP"] = STDEVCLIP; statisticsProperty["VARIANCECLIP"] = VARIANCECLIP; statisticsProperty["MIN"] = MIN; statisticsProperty["MAX"] = MAX; statisticsProperty["SUM"] = SUM; statisticsProperty["MEANSQUARE"] = MEANSQUARE; statisticsProperty["ORMASK"] = ORMASK; } return statisticsProperty[property]; } /** * @brief Constructor for Statistics object * * @note Most of the actual work is done in this constructor; the results * are retrieved using \c getValue etc. * */ template afwMath::Statistics::Statistics( ImageT const &img, ///< Image whose properties we want MaskT const &msk, ///< Mask to control which pixels are included VarianceT const &var, ///< Variances corresponding to values in Image int const flags, ///< Describe what we want to calculate afwMath::StatisticsControl const& sctrl ///< Control how things are calculated ) : _flags(flags), _mean(NaN, NaN), _variance(NaN, NaN), _min(NaN), _max(NaN), _sum(NaN), _meanclip(NaN, NaN), _varianceclip(NaN, NaN), _median(NaN, NaN), _iqrange(NaN), _sctrl(sctrl), _weightsAreMultiplicative(false) { doStatistics(img, msk, var, var, _flags, _sctrl); } namespace { template bool isEmpty(T const& t) { return t.empty(); } template bool isEmpty(afwImage::Image const& im) { return (im.getWidth() == 0 && im.getHeight() == 0); } } template afwMath::Statistics::Statistics( ImageT const &img, ///< Image whose properties we want MaskT const &msk, ///< Mask to control which pixels are included VarianceT const &var, ///< Variances corresponding to values in Image WeightT const &weights, ///< Weights to use corresponding to values in Image int const flags, ///< Describe what we want to calculate afwMath::StatisticsControl const& sctrl ///< Control how things are calculated ) : _flags(flags), _mean(NaN, NaN), _variance(NaN, NaN), _min(NaN), _max(NaN), _sum(NaN), _meanclip(NaN, NaN), _varianceclip(NaN, NaN), _median(NaN, NaN), _iqrange(NaN), _sctrl(sctrl), _weightsAreMultiplicative(true) { if (!isEmpty(weights)) { if (_sctrl.getWeightedIsSet() && !_sctrl.getWeighted()) {
    783 31ba7f7c - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    726 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "You must use the weights if you provide them"); } _sctrl.setWeighted(true); } doStatistics(img, msk, var, weights, _flags, _sctrl); } template void afwMath::Statistics::doStatistics( ImageT const &img, ///< Image whose properties we want MaskT const &msk, ///< Mask to control which pixels are included VarianceT const &var, ///< Variances corresponding to values in Image WeightT const &weights, ///< Weights to use corresponding to values in Image int const flags, ///< Describe what we want to calculate afwMath::StatisticsControl const& sctrl ///< Control how things are calculated ) { _n = img.getWidth()*img.getHeight(); if (_n == 0) {
    804 5a9fbeb0 - throw LSST_EXCEPT(pexExceptions::InvalidParameterException, "Image contains no pixels");
    ? ^^^^^^ ^
    747 21597d88 + throw LSST_EXCEPT(pexExceptions::InvalidParameterError, "Image contains no pixels");
    ? ^^ ^ } // Check that an int's large enough to hold the number of pixels assert(img.getWidth()*static_cast(img.getHeight()) < std::numeric_limits::max()); // get the standard statistics StandardReturn standard = getStandard(img, msk, var, weights, flags, _weightsAreMultiplicative, _sctrl.getAndMask(), _sctrl.getCalcErrorFromInputVariance(),
    815 6eed36a1 - _sctrl.getNanSafe(), _sctrl.getWeighted(),
    ? ^
    758 692d7033 + _sctrl.getNanSafe(), _sctrl.getWeighted());
    ? ^^
    816 6eed36a1 - _sctrl._maskPropagationThresholds);
    _n = standard.get<0>(); _sum = standard.get<1>(); _mean = standard.get<2>(); _variance = standard.get<3>(); _min = standard.get<4>(); _max = standard.get<5>(); _allPixelOrMask = standard.get<6>(); // ========================================================== // now only calculate it if it's specifically requested - these all cost more! // copy the image for any routines that will use median or quantiles if (flags & (MEDIAN | IQRANGE | MEANCLIP | STDEVCLIP | VARIANCECLIP)) { // make a vector copy of the image to get the median and quartiles (will move values) boost::shared_ptr > imgcp; if (_sctrl.getNanSafe()) { imgcp = makeVectorCopy(img, msk, var, _sctrl.getAndMask()); } else { imgcp = makeVectorCopy(img, msk, var, _sctrl.getAndMask()); } // if we *only* want the median, just use percentile(), otherwise use medianAndQuartiles() if ( (flags & (MEDIAN)) && !(flags & (IQRANGE | MEANCLIP | STDEVCLIP | VARIANCECLIP)) ) { _median = Value(percentile(*imgcp, 0.5), NaN); } else { MedianQuartileReturn mq = medianAndQuartiles(*imgcp); _median = Value(mq.get<0>(), NaN); _iqrange = mq.get<2>() - mq.get<1>(); } if (flags & (MEANCLIP | STDEVCLIP | VARIANCECLIP)) { for (int i_i = 0; i_i < _sctrl.getNumIter(); ++i_i) { double const center = ((i_i > 0) ? _meanclip : _median).first; double const hwidth = (i_i > 0 && _n > 1) ? _sctrl.getNumSigmaClip()*std::sqrt(_varianceclip.first) : _sctrl.getNumSigmaClip()*IQ_TO_STDEV*_iqrange; std::pair const clipinfo(center, hwidth); StandardReturn clipped = getStandard(img, msk, var, weights, flags, clipinfo, _weightsAreMultiplicative, _sctrl.getAndMask(), _sctrl.getCalcErrorFromInputVariance(),
    862 6eed36a1 - _sctrl.getNanSafe(), _sctrl.getWeighted(),
    ? ^
    804 692d7033 + _sctrl.getNanSafe(), _sctrl.getWeighted());
    ? ^^
    863 6eed36a1 - _sctrl._maskPropagationThresholds);
    int const nClip = clipped.get<0>(); _meanclip = clipped.get<2>(); // clipped mean double const varClip = clipped.get<3>().first; // clipped variance _varianceclip = Value(varClip, varianceError(varClip, nClip)); // ... ignore other values } } } } /************************************************************************************************************/
    877 e90ee178 - /* @brief Return the value and error in the specified statistic (e.g. MEAN)
    818 89372b8c + /** @brief Return the value and error in the specified statistic (e.g. MEAN)
    ? + *
    879 deba9f65 - * @param prop the property (see Statistics.h header) to retrieve.
    880 deba9f65 - * If NOTHING (default) and you only asked for one
    881 a716b827 - * property (and maybe its error), that property is returned
    882 e90ee178 - *
    883 e90ee178 - * @note Only quantities requested in the constructor may be retrieved
    820 89372b8c + * @note Only quantities requested in the constructor may be retrieved; in particular
    ? +++++++++++++++
    821 89372b8c + * errors may not be available if you didn't specify ERROR in the constructor
    * * @sa getValue and getError * * @todo uncertainties on MEANCLIP,STDEVCLIP are sketchy. _n != _nClip * */ std::pair afwMath::Statistics::getResult(
    891 104206ec - afwMath::Property const iProp ///< Desired property
    829 89372b8c + afwMath::Property const iProp ///< the afw::math::Property to retrieve.
    830 89372b8c + ///< If NOTHING (default) and you only asked for one
    831 89372b8c + ///< property (and maybe its error) in the constructor,
    832 89372b8c + ///< that property is returned
    ) const { // if iProp == NOTHING try to return their heart's delight, as specified in the constructor afwMath::Property const prop = static_cast(((iProp == NOTHING) ? _flags : iProp) & ~ERRORS); if (!(prop & _flags)) { // we didn't calculate it
    899 5a9fbeb0 - throw LSST_EXCEPT(pexExceptions::InvalidParameterException,
    ? ^^^^^^ ^
    840 21597d88 + throw LSST_EXCEPT(pexExceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("You didn't ask me to calculate %d") % prop).str()); } Value ret(NaN, NaN); switch (prop) { case NPOINT: ret.first = static_cast(_n); if (_flags & ERRORS) { ret.second = 0; } break; case SUM: ret.first = static_cast(_sum); if (_flags & ERRORS) { ret.second = 0; } break; // == means == case MEAN: ret.first = _mean.first; if (_flags & ERRORS) { ret.second = ::sqrt(_mean.second); } break; case MEANCLIP: ret.first = _meanclip.first; if ( _flags & ERRORS ) { ret.second = ::sqrt(_meanclip.second); } break; // == stdevs & variances == case VARIANCE: ret.first = _variance.first; if (_flags & ERRORS) { ret.second = ::sqrt(_variance.second); } break; case STDEV: ret.first = sqrt(_variance.first); if (_flags & ERRORS) { ret.second = 0.5*::sqrt(_variance.second)/ret.first; } break; case VARIANCECLIP: ret.first = _varianceclip.first; if (_flags & ERRORS) { ret.second = ret.second; } break; case STDEVCLIP: ret.first = sqrt(_varianceclip.first); if (_flags & ERRORS) { ret.second = 0.5*::sqrt(_varianceclip.second)/ret.first; } break; case MEANSQUARE: ret.first = (_n - 1)/static_cast(_n)*_variance.first + ::pow(_mean.first, 2); if (_flags & ERRORS) { ret.second = ::sqrt(2*::pow(ret.first/_n, 2)); // assumes Gaussian } break; // == other stats == case MIN: ret.first = _min; if ( _flags & ERRORS ) { ret.second = 0; } break; case MAX: ret.first = _max; if ( _flags & ERRORS ) { ret.second = 0; } break; case MEDIAN: ret.first = _median.first; if ( _flags & ERRORS ) { ret.second = sqrt(afwGeom::HALFPI*_variance.first/_n); // assumes Gaussian } break; case IQRANGE: ret.first = _iqrange; if ( _flags & ERRORS ) { ret.second = NaN; // we're not estimating this properly } break; // no-op to satisfy the compiler case ERRORS: break; // default: redundant as 'ret' is initialized to NaN, NaN default: // we must have set prop to _flags assert (iProp == 0);
    1000 a716b827 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    941 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "getValue() may only be called without a parameter" " if you asked for only one statistic"); } return ret; }
    1007 e90ee178 - /* @brief Return the value of the desired property (if specified in the constructor)
    948 89372b8c + /** @brief Return the value of the desired property (if specified in the constructor)
    ? +
    1008 e90ee178 - * @param prop - the property (see Statistics.h) to retrieve
    */
    1010 42774995 - double afwMath::Statistics::getValue(afwMath::Property const prop ///< Desired property
    950 89372b8c + double afwMath::Statistics::getValue(
    951 89372b8c + afwMath::Property const prop ///< the afw::math::Property to retrieve.
    952 89372b8c + ///< If NOTHING (default) and you only asked for one
    953 89372b8c + ///< property in the constructor, that property is returned
    ) const { return getResult(prop).first; }
    1016 e90ee178 - /* @brief Return the error in the desired property (if specified in the constructor)
    959 89372b8c + /** @brief Return the error in the desired property (if specified in the constructor)
    ? +
    1017 e90ee178 - * @param prop - the property (see Statistics.h) to retrieve
    */
    1019 42774995 - double afwMath::Statistics::getError(afwMath::Property const prop ///< Desired property
    961 89372b8c + double afwMath::Statistics::getError(
    962 89372b8c + afwMath::Property const prop ///< the afw::math::Property to retrieve.
    963 89372b8c + ///< If NOTHING (default) and you only asked for one
    964 89372b8c + ///< property in the constructor, that property's error is returned
    965 89372b8c + ///< \note You may have needed to specify ERROR to the ctor
    ) const { return getResult(prop).second; } /************************************************************************************************/ /** * Specialisation for Masks; just calculate the "Sum" as the bitwise OR of all pixels */ namespace lsst { namespace afw { namespace math { template<> Statistics::Statistics( afwImage::Mask const& msk, ///< Mask whose properties we want afwImage::Mask const&, ///< A mask to control which pixels afwImage::Mask const&, ///< A variance int const flags, ///< Describe what we want to calculate StatisticsControl const& sctrl ///< Control how things are calculated ) : _flags(flags), _mean(NaN, NaN), _variance(NaN, NaN), _min(NaN), _max(NaN), _meanclip(NaN, NaN), _varianceclip(NaN, NaN), _median(NaN, NaN), _iqrange(NaN), _sctrl(sctrl) { if ((flags & ~(NPOINT | SUM)) != 0x0) {
    1048 5a9fbeb0 - throw LSST_EXCEPT(pexExceptions::InvalidParameterException, "Statistics only supports NPOINT and SUM");
    ? ^^^^^^ ^
    994 21597d88 + throw LSST_EXCEPT(pexExceptions::InvalidParameterError, "Statistics only supports NPOINT and SUM");
    ? ^^ ^ } typedef afwImage::Mask Mask; _n = msk.getWidth()*msk.getHeight(); if (_n == 0) {
    1055 5a9fbeb0 - throw LSST_EXCEPT(pexExceptions::InvalidParameterException, "Image contains no pixels");
    ? ^^^^^^ ^
    1001 21597d88 + throw LSST_EXCEPT(pexExceptions::InvalidParameterError, "Image contains no pixels");
    ? ^^ ^ } // Check that an int's large enough to hold the number of pixels assert(msk.getWidth()*static_cast(msk.getHeight()) < std::numeric_limits::max()); afwImage::MaskPixel sum = 0x0; for (int y = 0; y != msk.getHeight(); ++y) { for (Mask::x_iterator ptr = msk.row_begin(y), end = msk.row_end(y); ptr != end; ++ptr) { sum |= (*ptr)[0]; } } _sum = sum; }
    1070 8acbc5a5 - /*
    1016 89372b8c + /**
    ? + * @brief Specialization to handle Masks * @note Although short, the definition can't be in the header as it must * follow the specialization definition * (g++ complained when this was in the header.) * */ Statistics makeStatistics( afwImage::Mask const &msk, ///< Image (or MaskedImage) whose properties we want int const flags, ///< Describe what we want to calculate StatisticsControl const& sctrl ///< Control how things are calculated ) { return Statistics(msk, msk, msk, flags, sctrl); } }}} /****************************************************************************************************/ /* * Explicit instantiations * * explicit Statistics(MaskedImage const& img, int const flags, * StatisticsControl const& sctrl=StatisticsControl()); */ /// \cond // #define STAT afwMath::Statistics typedef afwImage::VariancePixel VPixel; #define INSTANTIATE_MASKEDIMAGE_STATISTICS(TYPE) \ template STAT::Statistics(afwImage::Image const &img, \ afwImage::Mask const &msk, \ afwImage::Image const &var, \ int const flags, StatisticsControl const& sctrl); \ template STAT::Statistics(afwImage::Image const &img, \ afwImage::Mask const &msk, \ afwImage::Image const &var, \ afwImage::Image const &weights, \ int const flags, StatisticsControl const& sctrl); \ template STAT::Statistics(afwImage::Image const &img, \ afwImage::Mask const &msk, \ afwImage::Image const &var, \ afwMath::ImageImposter const &weights, \ int const flags, StatisticsControl const& sctrl) #define INSTANTIATE_MASKEDIMAGE_STATISTICS_NO_MASK(TYPE) \ template STAT::Statistics(afwImage::Image const &img, \ afwMath::MaskImposter const &msk, \ afwImage::Image const &var, \ int const flags, StatisticsControl const& sctrl); \ template STAT::Statistics(afwImage::Image const &img, \ afwMath::MaskImposter const &msk, \ afwImage::Image const &var, \ afwImage::Image const &weights, \ int const flags, StatisticsControl const& sctrl) #define INSTANTIATE_MASKEDIMAGE_STATISTICS_NO_VAR(TYPE) \ template STAT::Statistics(afwImage::Image const &img, \ afwImage::Mask const &msk, \ afwMath::MaskImposter const &var, \ int const flags, StatisticsControl const& sctrl); \ template STAT::Statistics(afwImage::Image const &img, \ afwImage::Mask const &msk, \ afwMath::MaskImposter const &var, \ afwImage::Image const &weights, \ int const flags, StatisticsControl const& sctrl); \ template STAT::Statistics(afwImage::Image const &img, \ afwImage::Mask const &msk, \ afwMath::MaskImposter const &var, \ afwMath::ImageImposter const &weights, \ int const flags, StatisticsControl const& sctrl) #define INSTANTIATE_REGULARIMAGE_STATISTICS(TYPE) \ template STAT::Statistics(afwImage::Image const &img, \ afwMath::MaskImposter const &msk, \ afwMath::MaskImposter const &var, \ int const flags, StatisticsControl const& sctrl) #define INSTANTIATE_VECTOR_STATISTICS(TYPE) \ template STAT::Statistics(afwMath::ImageImposter const &img, \ afwMath::MaskImposter const &msk, \ afwMath::MaskImposter const &var, \ int const flags, StatisticsControl const& sctrl); \ template STAT::Statistics(afwMath::ImageImposter const &img, \ afwMath::MaskImposter const &msk, \ afwMath::MaskImposter const &var, \ afwMath::ImageImposter const &weights, \ int const flags, StatisticsControl const& sctrl) #define INSTANTIATE_IMAGE_STATISTICS(T) \ INSTANTIATE_MASKEDIMAGE_STATISTICS(T); \ INSTANTIATE_MASKEDIMAGE_STATISTICS_NO_VAR(T); \ INSTANTIATE_MASKEDIMAGE_STATISTICS_NO_MASK(T); \ INSTANTIATE_REGULARIMAGE_STATISTICS(T); \ INSTANTIATE_VECTOR_STATISTICS(T) INSTANTIATE_IMAGE_STATISTICS(double); INSTANTIATE_IMAGE_STATISTICS(float); INSTANTIATE_IMAGE_STATISTICS(int); INSTANTIATE_IMAGE_STATISTICS(boost::uint16_t); INSTANTIATE_IMAGE_STATISTICS(boost::uint64_t); /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    692d7033

    commit 692d7033961737213ef3e446c22a4ef84621bcec
    Author: rhl 
    Date:   Fri Sep 30 08:03:43 2011 +0000
    
        Implement estimating values from input variances; neither correct nor complete
    

    3a0c19cc

    commit 3a0c19cc3d1f6fa8e9ebe45144eb9cd532d10eb7
    Author: rhl 
    Date:   Sun Oct 2 04:07:22 2011 +0000
    
        Redo the book-keeping for errors, allowing us to calculate them where they are calculated
    

    a716b827

    commit a716b8278e46b783bd31b9781f12a51761041a1e
    Author: rhl 
    Date:   Wed Mar 4 17:58:23 2009 +0000
    
        Add footprintToBBoxList (#681).  As part of writing its test, make Statistics understand unsigned short images, and allow getValue() to return single requested statistic
    

    31ba7f7c

    commit 31ba7f7c2885d932ca272d76bf823a92a079a41c
    Author: rhl 
    Date:   Sat Oct 1 06:53:50 2011 +0000
    
        I think that the structural cleanup is done.  Still need to implement propagating outputs from the input variances
    

    104206ec

    commit 104206ec4d94a67908ef6fe3a1a88b02e368ce95
    Author: rhl 
    Date:   Sun Oct 2 05:29:58 2011 +0000
    
        Implemented setCalcErrorFromInputVariance for means
    

    8acbc5a5

    commit 8acbc5a5dfb64c6f72914898d8492b8e91fe25c0
    Author: bick 
    Date:   Fri Sep 25 15:23:14 2009 +0000
    
        #749 Added front end makeStatistics() for Mask specialization.
    

    6eed36a1

    commit 6eed36a1b6376390c028ec0a15a8d35d040b951c
    Author: Jim Bosch 
    Date:   Thu May 1 12:58:41 2014 -0400
    
        Propagate rejected pixel mask planes when the amount of rejection crosses a threshold.
    

    f2c3ad9b

    commit f2c3ad9bb81065355034b750d9343235258bb9a5
    Author: rhl 
    Date:   Thu Sep 29 07:49:21 2011 +0000
    
        Yet more cleanup
    

    deba9f65

    commit deba9f65dce346ed369d95c80ccf31f0bd724c9d
    Author: bick 
    Date:   Wed Oct 7 16:21:45 2009 +0000
    
        on afw/trunk.  Cleaned-up some parasoft errors in Interpolate, Statistics, Background, and Integrate
    

    5a9fbeb0

    commit 5a9fbeb0f7afaf1794ce1cbf1679e480a6dce384
    Author: Robert Lupton the Good 
    Date:   Mon Mar 5 13:20:32 2012 -0500
    
        Add some logging (requires pex_logging 928cd9088;#1967)
    

    161df91c

    commit 161df91c604021bc8e693c19ffd39c9891cadd79
    Author: bick 
    Date:   Wed Nov 4 17:27:10 2009 +0000
    
        #1006 Changes are in.  still need tests and some comments.
    

    e90ee178

    commit e90ee178099b7a6a6aab693786e857b1406dae61
    Merge: 0693901 149144c
    Author: bick 
    Date:   Tue Jan 27 01:03:45 2009 +0000
    
        Check in of documentation changes to Statistics, Interpolate, and Background.
    

    42774995

    commit 427749956a5938212953b3d01bbb62e177a0e467
    Author: bick 
    Date:   Tue Jan 12 00:23:45 2010 +0000
    
        Fixed isnan() test for clipped stats in Statistics. Ticket #1125
    

    ba95a979

    commit ba95a97914fc2df3601f64159849cdfeb2804d6b
    Author: rhl 
    Date:   Thu Sep 29 05:08:11 2011 +0000
    
        Remove _sumImage from Statistics, and do the test for boolean options via recursive function calls.  More cleanup to follow...
    

    Commits in /Users/nate/repos_lsst/afw/

    692d7033

    commit 692d7033961737213ef3e446c22a4ef84621bcec
    Author: rhl 
    Date:   Fri Sep 30 08:03:43 2011 +0000
    
        Implement estimating values from input variances; neither correct nor complete
    

    3a0c19cc

    commit 3a0c19cc3d1f6fa8e9ebe45144eb9cd532d10eb7
    Author: rhl 
    Date:   Sun Oct 2 04:07:22 2011 +0000
    
        Redo the book-keeping for errors, allowing us to calculate them where they are calculated
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    161df91c

    commit 161df91c604021bc8e693c19ffd39c9891cadd79
    Author: bick 
    Date:   Wed Nov 4 17:27:10 2009 +0000
    
        #1006 Changes are in.  still need tests and some comments.
    

    b136e57d

    commit b136e57d282924d6cdf9296384618801eeea0436
    Author: rhl 
    Date:   Fri Sep 30 05:43:07 2011 +0000
    
        Yet more cleanup
    

    89372b8c

    commit 89372b8c30dc02f74200c6bff3c80d1a1d9020b4
    Author: Robert Lupton the Good 
    Date:   Thu Jul 17 22:48:09 2014 -0400
    
        Fixed doxygen comments
        
        Need /** to introduce comments that doxy will parse
    

    6e8b043b

    commit 6e8b043b597d4cf3616ba44da677a86e82961f5e
    Author: John Swinbank 
    Date:   Mon Apr 6 11:37:03 2015 -0400
    
        CheckFinite should check for Inf (as well as NaN).
        
        Addresses DM-2488.
    

    f2c3ad9b

    commit f2c3ad9bb81065355034b750d9343235258bb9a5
    Author: rhl 
    Date:   Thu Sep 29 07:49:21 2011 +0000
    
        Yet more cleanup
    

    ba95a979

    commit ba95a97914fc2df3601f64159849cdfeb2804d6b
    Author: rhl 
    Date:   Thu Sep 29 05:08:11 2011 +0000
    
        Remove _sumImage from Statistics, and do the test for boolean options via recursive function calls.  More cleanup to follow...
    

    Return to list

    python/lsst/afw/coord/coordLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define coordLib_DOCSTRING
                    "
                    Python interface to lsst::afw::coord
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.coord", docstring=coordLib_DOCSTRING) coordLib
                    
                    %include "lsst/p_lsstSwig.i"
                    
                    %lsst_exceptions();
    
    37 853c5734 + %initializeNumPy(afw_coord)
    %include "std_pair.i" %template(pairSS) std::pair; %{ #include "boost/shared_ptr.hpp" #include "lsst/afw/geom.h" %} %template(pairAngleAngle) std::pair; %import "lsst/daf/base/baseLib.i" %import "lsst/afw/geom/geomLib.i" %include "observatory.i" %include "coord.i"

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    853c5734

    commit 853c5734ee13f55fd35e9e18ed5ac69a0073b97f
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:18:28 2015 -0400
    
        Utilize new numeric scalar typemaps and NumPy import macro.
    

    Return to list

    tests/testLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define testLib_DOCSTRING
                    "
                    Various swigged-up C++ classes for testing
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="testLib", docstring=testLib_DOCSTRING) testLib
                    
                    %pythonnondynamic;
                    %naturalvar;  // use const reference typemaps
                    
                    %include "lsst/p_lsstSwig.i"
                    
                    %lsst_exceptions()
                    
                    %{
                    #include "lsst/pex/logging.h"
                    #include "lsst/pex/policy.h"
                    #include "lsst/afw/geom.h"
    
    45 4563d0f0 + #include "lsst/afw/cameraGeom.h"
    #include "lsst/afw/math.h"
    46 4563d0f0 - #include "lsst/afw/cameraGeom.h"
    #include "lsst/afw/image.h" #include "lsst/afw/math/SpatialCell.h" %} %import "lsst/afw/math/mathLib.i" %shared_ptr(TestCandidate); %shared_ptr(TestCandidateVisitor); %shared_ptr(TestMaskedImageCandidate); %inline %{ /* * Test class for SpatialCellCandidate */ class TestCandidate : public lsst::afw::math::SpatialCellCandidate { public: TestCandidate(float const xCenter, ///< The object's column-centre float const yCenter, ///< The object's row-centre float const flux ///< The object's flux ) : SpatialCellCandidate(xCenter, yCenter), _flux(flux) { } /// Return candidates rating virtual double getCandidateRating() const { return _flux; } virtual void setCandidateRating(double flux) { _flux = flux; } private: double _flux; }; /// A class to pass around to all our TestCandidates class TestCandidateVisitor : public lsst::afw::math::CandidateVisitor { public: TestCandidateVisitor() : lsst::afw::math::CandidateVisitor(), _n(0) {} // Called by SpatialCellSet::visitCandidates before visiting any Candidates void reset() { _n = 0; } // Called by SpatialCellSet::visitCandidates for each Candidate void processCandidate(lsst::afw::math::SpatialCellCandidate *candidate) { ++_n; } int getN() const { return _n; } private: int _n; // number of TestCandidates }; /************************************************************************************************************/ /* * Test class for SpatialCellMaskedImageCandidate */ class TestMaskedImageCandidate : public lsst::afw::math::SpatialCellMaskedImageCandidate { public: typedef lsst::afw::image::MaskedImage MaskedImageT; TestMaskedImageCandidate(float const xCenter, ///< The object's column-centre float const yCenter, ///< The object's row-centre float const flux ///< The object's flux ) : lsst::afw::math::SpatialCellMaskedImageCandidate(xCenter, yCenter), _flux(flux) { } /// Return candidates rating double getCandidateRating() const { return _flux; } /// Return the %image MaskedImageT::ConstPtr getMaskedImage() const { if (_image.get() == NULL) { _image = MaskedImageT::Ptr(new MaskedImageT(lsst::afw::geom::ExtentI(getWidth(), getHeight()))); *_image->getImage() = _flux; } return _image; } private: double _flux; }; %}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4563d0f0

    commit 4563d0f054173793ca51c25afdac392dc16bdb19
    Author: smm 
    Date:   Wed Nov 9 02:57:43 2011 +0000
    
        afw Winter2012b: upgrade to swig 2.x
    

    Commits in /Users/nate/repos_lsst/afw/

    4563d0f0

    commit 4563d0f054173793ca51c25afdac392dc16bdb19
    Author: smm 
    Date:   Wed Nov 9 02:57:43 2011 +0000
    
        afw Winter2012b: upgrade to swig 2.x
    

    Return to list

    include/lsst/afw/math/Interpolate.h

    Diff:

                    // -*- LSST-C++ -*-
                    #if !defined(LSST_AFW_MATH_INTERPOLATE_H)
                    #define LSST_AFW_MATH_INTERPOLATE_H
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include "lsst/base.h"
    
    27 b8578746 - #include "ndarray_fwd.h"
    namespace lsst { namespace afw { namespace math { /** * @brief Interpolate values for a set of x,y vector<>s * @ingroup afw * @author Steve Bickerton */ class Interpolate { public: enum Style { UNKNOWN = -1, CONSTANT = 0, LINEAR = 1, NATURAL_SPLINE = 2, CUBIC_SPLINE = 3, CUBIC_SPLINE_PERIODIC = 4, AKIMA_SPLINE = 5, AKIMA_SPLINE_PERIODIC = 6, NUM_STYLES }; friend PTR(Interpolate) makeInterpolate(std::vector const &x, std::vector const &y, Interpolate::Style const style); virtual ~Interpolate() {} virtual double interpolate(double const x) const = 0;
    57 177dba2f - #ifndef SWIG
    58 b8578746 - std::vector interpolate(std::vector const& x) const;
    59 177dba2f - #endif
    60 b8578746 - ndarray::Array interpolate(ndarray::Array const& x) const;
    protected: /** * Base class ctor */ Interpolate(std::vector const &x, ///< the ordinates of points std::vector const &y, ///< the values at x[] Interpolate::Style const style=UNKNOWN ///< desired interpolator ) : _x(x), _y(y), _style(style) {} Interpolate(std::pair, std::vector > const xy, Interpolate::Style const style=UNKNOWN); std::vector const _x; std::vector const _y; Interpolate::Style const _style; private: Interpolate(Interpolate const&); Interpolate& operator=(Interpolate const&); };
    80 177dba2f - #ifndef SWIG
    PTR(Interpolate) makeInterpolate(std::vector const &x, std::vector const &y, Interpolate::Style const style=Interpolate::AKIMA_SPLINE);
    77 a3b60c46 +
    83 177dba2f - #endif
    84 b8578746 - PTR(Interpolate) makeInterpolate(ndarray::Array const &x,
    85 b8578746 - ndarray::Array const &y,
    86 b8578746 - Interpolate::Style const style=Interpolate::AKIMA_SPLINE);
    Interpolate::Style stringToInterpStyle(std::string const &style); Interpolate::Style lookupMaxInterpStyle(int const n); int lookupMinInterpPoints(Interpolate::Style const style); }}} #endif // LSST_AFW_MATH_INTERPOLATE_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    177dba2f

    commit 177dba2f11d42e1b11e5ad0fe3f7cecbb67bdfa5
    Author: Paul Price 
    Date:   Wed Mar 5 22:22:11 2014 -0500
    
        Interpolate: deactivate std::vector in favour of ndarray for SWIG
        
        The ndarray::Array interface is MUCH faster (factor of 2) than std::vector
        for large vectors, since for std::vector SWIG has to convert every value
        in a list or tuple, but a numpy array converts wholesale into a
        ndarray::Array.
    

    b8578746

    commit b8578746d69920bc1e1089cca4b4acb230f0e8d5
    Author: Paul Price 
    Date:   Mon Feb 24 11:25:36 2014 -0500
    
        Interpolate: add support for ndarray
    

    Commits in /Users/nate/repos_lsst/afw/

    a3b60c46

    commit a3b60c462363a2a1a36752645f0674b484627369
    Author: bick 
    Date:   Sat Nov 7 20:38:04 2009 +0000
    
        #1017 Put enum into Interpolate class.
    

    Return to list

    tests/testSourceTable.py

    Diff:

    1 3e1f9e0b - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 3e1f9e0b -
    2 b80fe1d3 + from __future__ import absolute_import, division
    3 3e1f9e0b - #
    ? -
    3 f05aa3ed + #
    # LSST Data Management System
    5 3e1f9e0b - # Copyright 2008, 2009, 2010 LSST Corporation.
    ? ^^^^^^^^ ^
    5 f05aa3ed + # Copyright 2008-2014 LSST Corporation.
    ? ^ ^
    6 3e1f9e0b - #
    ? -
    6 f05aa3ed + #
    # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version.
    14 3e1f9e0b - #
    ? -
    14 f05aa3ed + #
    # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details.
    19 3e1f9e0b - #
    ? -
    19 f05aa3ed + #
    20 3e1f9e0b - # You should have received a copy of the LSST License Statement and
    ? -
    20 f05aa3ed + # You should have received a copy of the LSST License Statement and
    21 3e1f9e0b - # the GNU General Public License along with this program. If not,
    ? -
    21 f05aa3ed + # the GNU General Public License along with this program. If not,
    # see . # """ Tests for table.SourceTable Run with: ./testSourceTable.py or python >>> import testSourceTable; testSourceTable.run() """
    35 3e1f9e0b - import sys
    import os import unittest import numpy import tempfile import pickle
    40 a25b9eb2 + import math
    import lsst.utils.tests import lsst.pex.exceptions import lsst.afw.table import lsst.afw.geom import lsst.afw.coord import lsst.afw.image import lsst.afw.detection
    50 4bae7ca1 + numpy.random.seed(1)
    51 4bae7ca1 +
    try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def makeArray(size, dtype): return numpy.array(numpy.random.randn(*size), dtype=dtype) def makeCov(size, dtype): m = numpy.array(numpy.random.randn(size, size), dtype=dtype) return numpy.dot(m, m.transpose()) def makeWcs(): crval = lsst.afw.coord.Coord(lsst.afw.geom.Point2D(1.606631, 5.090329)) crpix = lsst.afw.geom.Point2D(2036., 2000.) return lsst.afw.image.makeWcs(crval, crpix, 5.399452e-5, -1.30770e-5, 1.30770e-5, 5.399452e-5)
    69 3e1f9e0b - class SourceTableTestCase(unittest.TestCase):
    ? ^ ^
    71 87181699 + class SourceTableTestCase(lsst.utils.tests.TestCase):
    ? +++++ ^ ^^^ + def fillRecord(self, record): record.set(self.fluxKey, numpy.random.randn()) record.set(self.fluxErrKey, numpy.random.randn())
    74 d4c421d8 - record.set(self.centroidKey, lsst.afw.geom.Point2D(*numpy.random.randn(2)))
    ? ---------- ------- ^^ ^ --
    76 a25b9eb2 + record.set(self.centroidKey.getX(), numpy.random.randn())
    ? ^ ^^^
    75 36b29961 - record.set(self.centroidErrKey, makeCov(2, numpy.float32))
    76 d4c421d8 - record.set(self.shapeKey, lsst.afw.geom.ellipses.Quadrupole(*numpy.random.randn(3)))
    77 36b29961 - record.set(self.shapeErrKey, makeCov(3, numpy.float32))
    77 a25b9eb2 + record.set(self.centroidKey.getY(), numpy.random.randn())
    78 a25b9eb2 + record.set(self.xErrKey, numpy.random.randn())
    79 a25b9eb2 + record.set(self.yErrKey, numpy.random.randn())
    80 a25b9eb2 + record.set(self.shapeKey.getIxx(), numpy.random.randn())
    81 a25b9eb2 + record.set(self.shapeKey.getIyy(), numpy.random.randn())
    82 a25b9eb2 + record.set(self.shapeKey.getIxy(), numpy.random.randn())
    83 a25b9eb2 + record.set(self.xxErrKey, numpy.random.randn())
    84 a25b9eb2 + record.set(self.yyErrKey, numpy.random.randn())
    85 a25b9eb2 + record.set(self.xyErrKey, numpy.random.randn())
    record.set(self.fluxFlagKey, numpy.random.randn() > 0) record.set(self.centroidFlagKey, numpy.random.randn() > 0) record.set(self.shapeFlagKey, numpy.random.randn() > 0) def setUp(self): self.schema = lsst.afw.table.SourceTable.makeMinimalSchema()
    84 57671a18 - self.fluxKey = self.schema.addField("a", type="D")
    92 a25b9eb2 + self.fluxKey = self.schema.addField("a_flux", type = "D")
    ? +++++ + +
    85 57671a18 - self.fluxErrKey = self.schema.addField("a.err", type="D")
    ? ^^^^
    93 a25b9eb2 + self.fluxErrKey = self.schema.addField("a_fluxSigma", type = "D")
    ? ^^^^^^^^^^ + +
    86 d4c421d8 - self.fluxFlagKey = self.schema.addField("a.flags", type="Flag")
    ? ^ -
    94 a25b9eb2 + self.fluxFlagKey = self.schema.addField("a_flag", type="Flag")
    ? ^
    95 a25b9eb2 +
    96 a25b9eb2 + # the meas field is added using a functor key, but the error is added
    97 a25b9eb2 + # as scalars, as we lack a ResultKey functor as exists in meas_base
    98 a25b9eb2 + self.centroidKey = lsst.afw.table.Point2DKey.addFields(self.schema,
    99 a25b9eb2 + "b", "", "pixels")
    87 57671a18 - self.centroidKey = self.schema.addField("b", type="PointD")
    ? ^^^^ ^^^ ^^^^^^
    100 a25b9eb2 + self.xErrKey = self.schema.addField("b_xSigma", type = "F")
    ? ^^ ^ +++++++ + + ^
    88 36b29961 - self.centroidErrKey = self.schema.addField("b.err", type="CovPointF")
    ? ^^^^^^^^ ^^^^ --------
    101 a25b9eb2 + self.yErrKey = self.schema.addField("b_ySigma", type = "F")
    ? ^ ^^^^^^^ + +
    89 d4c421d8 - self.centroidFlagKey = self.schema.addField("b.flags", type="Flag")
    ? ^ -
    102 a25b9eb2 + self.centroidFlagKey = self.schema.addField("b_flag", type="Flag")
    ? ^
    90 57671a18 - self.shapeKey = self.schema.addField("c", type="MomentsD")
    103 a25b9eb2 +
    104 a25b9eb2 + self.shapeKey = lsst.afw.table.QuadrupoleKey.addFields(self.schema,
    105 dce194d3 + "c", "", lsst.afw.table.PIXEL)
    91 36b29961 - self.shapeErrKey = self.schema.addField("c.err", type="CovMomentsF")
    ? ^^^^^ ^^^^ ----------
    106 a25b9eb2 + self.xxErrKey = self.schema.addField("c_xxSigma", type = "F")
    ? ^^ ^^^^^^^^ + +
    107 a25b9eb2 + self.xyErrKey = self.schema.addField("c_xySigma", type = "F")
    108 a25b9eb2 + self.yyErrKey = self.schema.addField("c_yySigma", type = "F")
    92 d4c421d8 - self.shapeFlagKey = self.schema.addField("c.flags", type="Flag")
    ? ^ -
    109 a25b9eb2 + self.shapeFlagKey = self.schema.addField("c_flag", type="Flag")
    ? ^
    110 a25b9eb2 +
    self.table = lsst.afw.table.SourceTable.make(self.schema) self.catalog = lsst.afw.table.SourceCatalog(self.table) self.record = self.catalog.addNew() self.fillRecord(self.record) self.record.setId(50) self.fillRecord(self.catalog.addNew()) self.fillRecord(self.catalog.addNew()) def tearDown(self): del self.schema del self.record del self.table del self.catalog def checkCanonical(self): self.assertEqual(self.table.getPsfFluxDefinition(), "a") self.assertEqual(self.record.get(self.fluxKey), self.record.getPsfFlux()) self.assertEqual(self.record.get(self.fluxFlagKey), self.record.getPsfFluxFlag()) self.assertEqual(self.table.getCentroidDefinition(), "b")
    112 3e1f9e0b - self.assertEqual(self.record.get(self.centroidKey), self.record.getCentroid())
    ? ----------------
    130 a25b9eb2 + self.assertEqual(self.centroidKey.get(self.record), self.record.getCentroid())
    ? ++++++++++++++++
    113 6581586d - self.assert_(numpy.all(self.record.get(self.centroidErrKey) == self.record.getCentroidErr()))
    131 a25b9eb2 + self.assertClose(math.fabs(self.record.get(self.xErrKey)),
    132 a25b9eb2 + math.sqrt(self.record.getCentroidErr()[0,0]), rtol=1e-6)
    133 a25b9eb2 + self.assertClose(math.fabs(self.record.get(self.yErrKey)),
    134 a25b9eb2 + math.sqrt(self.record.getCentroidErr()[1,1]), rtol=1e-6)
    self.assertEqual(self.table.getShapeDefinition(), "c")
    115 3e1f9e0b - self.assertEqual(self.record.get(self.shapeKey), self.record.getShape())
    ? ^ ^^^^ ^^^^ ^^^
    136 a25b9eb2 + self.assertEqual(self.shapeKey.get(self.record), self.record.getShape())
    ? ^^^^ ^^^ ^ ^^^^
    116 6581586d - self.assert_(numpy.all(self.record.get(self.shapeErrKey) == self.record.getShapeErr()))
    137 a25b9eb2 + self.assertClose(math.fabs(self.record.get(self.xxErrKey)),
    138 a25b9eb2 + math.sqrt(self.record.getShapeErr()[0,0]), rtol=1e-6)
    139 a25b9eb2 + self.assertClose(math.fabs(self.record.get(self.yyErrKey)),
    140 a25b9eb2 + math.sqrt(self.record.getShapeErr()[1,1]), rtol=1e-6)
    141 a25b9eb2 + self.assertClose(math.fabs(self.record.get(self.xyErrKey)),
    142 a25b9eb2 + math.sqrt(self.record.getShapeErr()[2,2]), rtol=1e-6)
    118 3e1f9e0b - def testCanonical1(self):
    119 6581586d - self.table.definePsfFlux(self.fluxKey, self.fluxErrKey, self.fluxFlagKey)
    120 6581586d - self.table.defineCentroid(self.centroidKey, self.centroidErrKey, self.centroidFlagKey)
    121 6581586d - self.table.defineShape(self.shapeKey, self.shapeErrKey, self.shapeFlagKey)
    122 3e1f9e0b - self.checkCanonical()
    144 5e98dbb9 + def testPersisted(self):
    145 5e98dbb9 + self.table.definePsfFlux("a")
    146 5e98dbb9 + self.table.defineCentroid("b")
    147 5e98dbb9 + self.table.defineShape("c")
    148 c605dfcd + with lsst.utils.tests.getTempFilePath(".fits") as filename:
    149 c605dfcd + self.catalog.writeFits(filename)
    150 c605dfcd + catalog = lsst.afw.table.SourceCatalog.readFits(filename)
    151 c605dfcd + table = catalog.getTable()
    152 c605dfcd + record = catalog[0]
    153 c605dfcd + # I'm using the keys from the non-persisted table. They should work at least in the
    154 c605dfcd + # current implementation
    155 c605dfcd + self.assertEqual(table.getPsfFluxDefinition(), "a")
    156 c605dfcd + self.assertEqual(record.get(self.fluxKey), record.getPsfFlux())
    157 c605dfcd + self.assertEqual(record.get(self.fluxFlagKey), record.getPsfFluxFlag())
    158 c605dfcd + self.assertEqual(table.getCentroidDefinition(), "b")
    159 c605dfcd + centroid = self.centroidKey.get(self.record)
    160 c605dfcd + self.assertEqual(centroid, record.getCentroid())
    161 c605dfcd + self.assertClose(math.fabs(self.record.get(self.xErrKey)),
    162 c605dfcd + math.sqrt(self.record.getCentroidErr()[0,0]), rtol=1e-6)
    163 c605dfcd + self.assertClose(math.fabs(self.record.get(self.yErrKey)),
    164 c605dfcd + math.sqrt(self.record.getCentroidErr()[1,1]), rtol=1e-6)
    165 c605dfcd + shape = self.shapeKey.get(self.record)
    166 c605dfcd + self.assertEqual(table.getShapeDefinition(), "c")
    167 c605dfcd + self.assertEqual(shape, record.getShape())
    168 c605dfcd + self.assertClose(math.fabs(self.record.get(self.xxErrKey)),
    169 c605dfcd + math.sqrt(self.record.getShapeErr()[0,0]), rtol=1e-6)
    170 c605dfcd + self.assertClose(math.fabs(self.record.get(self.yyErrKey)),
    171 c605dfcd + math.sqrt(self.record.getShapeErr()[1,1]), rtol=1e-6)
    172 c605dfcd + self.assertClose(math.fabs(self.record.get(self.xyErrKey)),
    173 c605dfcd + math.sqrt(self.record.getShapeErr()[2,2]), rtol=1e-6)
    def testCanonical2(self): self.table.definePsfFlux("a") self.table.defineCentroid("b") self.table.defineShape("c") self.checkCanonical()
    130 2063bd97 - def testTicket2165(self):
    131 2063bd97 - """Check that we can define the slots without all the keys."""
    132 2063bd97 - self.table.definePsfFlux(self.fluxKey)
    133 2063bd97 - self.assertEqual(self.table.getPsfFluxDefinition(), "a")
    134 2063bd97 - self.assertEqual(self.table.getPsfFluxKey(), self.fluxKey)
    135 2063bd97 - self.assertFalse(self.table.getPsfFluxFlagKey().isValid())
    136 2063bd97 - self.assertFalse(self.table.getPsfFluxErrKey().isValid())
    137 2063bd97 - self.table.defineCentroid(self.centroidKey, flag=self.centroidFlagKey)
    138 2063bd97 - self.assertEqual(self.table.getCentroidDefinition(), "b")
    139 2063bd97 - self.assertEqual(self.table.getCentroidKey(), self.centroidKey)
    140 2063bd97 - self.assertEqual(self.table.getCentroidFlagKey(), self.centroidFlagKey)
    141 2063bd97 - self.assertFalse(self.table.getCentroidErrKey().isValid())
    142 2063bd97 - schema2 = lsst.afw.table.SourceTable.makeMinimalSchema()
    143 2063bd97 - fluxKey2 = schema2.addField("a", type="D")
    144 2063bd97 - fluxFlagKey2 = schema2.addField("a.flags", type="Flag")
    145 2063bd97 - table2 = lsst.afw.table.SourceTable.make(schema2)
    146 2063bd97 - table2.definePsfFlux("a")
    147 2063bd97 - self.assertEqual(table2.getPsfFluxDefinition(), "a")
    148 2063bd97 - self.assertEqual(table2.getPsfFluxKey(), fluxKey2)
    149 2063bd97 - self.assertEqual(table2.getPsfFluxFlagKey(), fluxFlagKey2)
    150 2063bd97 - self.assertFalse(self.table.getPsfFluxErrKey().isValid())
    151 2063bd97 -
    def testPickle(self): p = pickle.dumps(self.catalog) new = pickle.loads(p) self.assertEqual(self.catalog.schema.getNames(), new.schema.getNames()) self.assertEqual(len(self.catalog), len(new)) for r1, r2 in zip(self.catalog, new):
    159 0323a937 - for field in ("a", "a.err", "id"): # Columns that are easy to test
    ? ^^^^
    188 a25b9eb2 + for field in ("a_flux", "a_fluxSigma", "id"): # Columns that are easy to test
    ? +++++ ^^^^^^^^^^ k1 = self.catalog.schema.find(field).getKey() k2 = new.schema.find(field).getKey() self.assertTrue(r1[k1] == r2[k2])
    164 2063bd97 -
    def testCoordUpdate(self):
    194 a25b9eb2 + self.table.defineCentroid("b")
    wcs = makeWcs()
    167 fa7147a0 - self.record.updateCoord(wcs, self.centroidKey)
    ? ------------------
    196 a25b9eb2 + self.record.updateCoord(wcs)
    coord1 = self.record.getCoord() coord2 = wcs.pixelToSky(self.record.get(self.centroidKey)) self.assertEqual(coord1, coord2) def testSorting(self): self.assertFalse(self.catalog.isSorted()) self.catalog.sort() self.assert_(self.catalog.isSorted()) r = self.catalog.find(2) self.assertEqual(r["id"], 2) r = self.catalog.find(500) self.assert_(r is None) def testConversion(self): catalog1 = self.catalog.cast(lsst.afw.table.SourceCatalog) catalog2 = self.catalog.cast(lsst.afw.table.SimpleCatalog) catalog3 = self.catalog.cast(lsst.afw.table.SourceCatalog, deep=True) catalog4 = self.catalog.cast(lsst.afw.table.SimpleCatalog, deep=True) self.assertEqual(self.catalog.table, catalog1.table) self.assertEqual(self.catalog.table, catalog2.table) self.assertNotEqual(self.catalog.table, catalog3.table) self.assertNotEqual(self.catalog.table, catalog3.table) for r, r1, r2, r3, r4 in zip(self.catalog, catalog1, catalog2, catalog3, catalog4): self.assertEqual(r, r1) self.assertEqual(r, r2) self.assertNotEqual(r, r3) self.assertNotEqual(r, r4) self.assertEqual(r.getId(), r3.getId()) self.assertEqual(r.getId(), r4.getId()) def testColumnView(self): cols1 = self.catalog.getColumnView() cols2 = self.catalog.columns self.assert_(cols1 is cols2) self.assert_(isinstance(cols1, lsst.afw.table.SourceColumnView)) self.table.definePsfFlux("a") self.table.defineCentroid("b") self.table.defineShape("c")
    206 d4c421d8 - self.assert_((cols2["a"] == cols2.getPsfFlux()).all())
    235 a25b9eb2 + self.assert_((cols2["a_flux"] == cols2.getPsfFlux()).all())
    ? +++++
    207 4ce9656b - self.assert_((cols2["a.err"] == cols2.getPsfFluxErr()).all())
    ? ^^^^
    236 a25b9eb2 + self.assert_((cols2["a_fluxSigma"] == cols2.getPsfFluxErr()).all())
    ? ^^^^^^^^^^
    208 d4c421d8 - self.assert_((cols2["b.x"] == cols2.getX()).all())
    ? ^
    237 a25b9eb2 + self.assert_((cols2["b_x"] == cols2.getX()).all())
    ? ^
    209 d4c421d8 - self.assert_((cols2["b.y"] == cols2.getY()).all())
    ? ^
    238 a25b9eb2 + self.assert_((cols2["b_y"] == cols2.getY()).all())
    ? ^
    210 d4c421d8 - self.assert_((cols2["c.xx"] == cols2.getIxx()).all())
    ? ^
    239 a25b9eb2 + self.assert_((cols2["c_xx"] == cols2.getIxx()).all())
    ? ^
    211 d4c421d8 - self.assert_((cols2["c.yy"] == cols2.getIyy()).all())
    ? ^
    240 a25b9eb2 + self.assert_((cols2["c_yy"] == cols2.getIyy()).all())
    ? ^
    212 d4c421d8 - self.assert_((cols2["c.xy"] == cols2.getIxy()).all())
    ? ^
    241 a25b9eb2 + self.assert_((cols2["c_xy"] == cols2.getIxy()).all())
    ? ^ def testForwarding(self): """Verify that Catalog forwards unknown methods to its table and/or columns.""" self.table.definePsfFlux("a") self.table.defineCentroid("b") self.table.defineShape("c")
    219 df04c833 - self.assert_((self.catalog.columns["a"] == self.catalog["a"]).all())
    248 a25b9eb2 + self.assert_((self.catalog.columns["a_flux"] == self.catalog["a_flux"]).all())
    ? +++++ +++++ self.assert_((self.catalog.columns[self.fluxKey] == self.catalog.get(self.fluxKey)).all()) self.assert_((self.catalog.columns.get(self.fluxKey) == self.catalog.getPsfFlux()).all()) self.assertEqual(self.fluxKey, self.catalog.getPsfFluxKey()) self.assertRaises(AttributeError, lambda c: c.foo(), self.catalog) def testBitsColumn(self): allBits = self.catalog.getBits()
    227 ecd0c5af - someBits = self.catalog.getBits(["a.flags", "c.flags"])
    ? ^ - ^ -
    256 a25b9eb2 + someBits = self.catalog.getBits(["a_flag", "c_flag"])
    ? ^ ^
    228 ecd0c5af - self.assertEqual(allBits.getMask("a.flags"), 0x1)
    ? ^ -
    257 a25b9eb2 + self.assertEqual(allBits.getMask("a_flag"), 0x1)
    ? ^
    229 ecd0c5af - self.assertEqual(allBits.getMask("b.flags"), 0x2)
    ? ^ -
    258 a25b9eb2 + self.assertEqual(allBits.getMask("b_flag"), 0x2)
    ? ^
    230 ecd0c5af - self.assertEqual(allBits.getMask("c.flags"), 0x4)
    ? ^ -
    259 a25b9eb2 + self.assertEqual(allBits.getMask("c_flag"), 0x4)
    ? ^ self.assertEqual(someBits.getMask(self.fluxFlagKey), 0x1) self.assertEqual(someBits.getMask(self.shapeFlagKey), 0x2)
    233 ecd0c5af - self.assert_(((allBits.array & 0x1 != 0) == self.catalog.columns["a.flags"]).all())
    ? ^ -
    262 a25b9eb2 + self.assert_(((allBits.array & 0x1 != 0) == self.catalog.columns["a_flag"]).all())
    ? ^
    234 ecd0c5af - self.assert_(((allBits.array & 0x2 != 0) == self.catalog.columns["b.flags"]).all())
    ? ^ -
    263 a25b9eb2 + self.assert_(((allBits.array & 0x2 != 0) == self.catalog.columns["b_flag"]).all())
    ? ^
    235 ecd0c5af - self.assert_(((allBits.array & 0x4 != 0) == self.catalog.columns["c.flags"]).all())
    ? ^ -
    264 a25b9eb2 + self.assert_(((allBits.array & 0x4 != 0) == self.catalog.columns["c_flag"]).all())
    ? ^
    236 ecd0c5af - self.assert_(((someBits.array & 0x1 != 0) == self.catalog.columns["a.flags"]).all())
    ? ^ -
    265 a25b9eb2 + self.assert_(((someBits.array & 0x1 != 0) == self.catalog.columns["a_flag"]).all())
    ? ^
    237 ecd0c5af - self.assert_(((someBits.array & 0x2 != 0) == self.catalog.columns["c.flags"]).all())
    ? ^ -
    266 a25b9eb2 + self.assert_(((someBits.array & 0x2 != 0) == self.catalog.columns["c_flag"]).all())
    ? ^ def testCast(self): baseCat = self.catalog.cast(lsst.afw.table.BaseCatalog) sourceCat = baseCat.cast(lsst.afw.table.SourceCatalog) def testFootprints(self): '''Test round-tripping Footprints (inc. HeavyFootprints) to FITS ''' src1 = self.catalog.addNew() src2 = self.catalog.addNew() src3 = self.catalog.addNew() self.fillRecord(src1) self.fillRecord(src2) self.fillRecord(src3) src2.setParent(src1.getId()) W,H = 100,100 mim = lsst.afw.image.MaskedImageF(W,H) im = mim.getImage() msk = mim.getMask() var = mim.getVariance() for y in range(H): for x in range(W): im.set (x, y, y * 1e6 + x * 1e3) msk.set(x, y, (y << 8) | x) var.set(x, y, y * 1e2 + x) circ = lsst.afw.detection.Footprint(lsst.afw.geom.Point2I(50,50), 20) heavy = lsst.afw.detection.makeHeavyFootprint(circ, mim) src2.setFootprint(heavy) for i,src in enumerate(self.catalog): if src != src2: src.setFootprint(lsst.afw.detection.Footprint(lsst.afw.geom.Point2I(50,50), 1+i*2)) # insert this HeavyFootprint into an otherwise blank image (for comparing the results) mim2 = lsst.afw.image.MaskedImageF(W,H) heavy.insert(mim2)
    305 c605dfcd + with lsst.utils.tests.getTempFilePath(".fits") as fn:
    276 4ac068ec - f,fn = tempfile.mkstemp(prefix='testHeavyFootprint-', suffix='.fits')
    277 4ac068ec - os.close(f)
    278 4ac068ec - self.catalog.writeFits(fn)
    306 c605dfcd + self.catalog.writeFits(fn)
    ? ++++
    280 4ac068ec - cat2 = lsst.afw.table.SourceCatalog.readFits(fn)
    308 c605dfcd + cat2 = lsst.afw.table.SourceCatalog.readFits(fn)
    ? ++++
    281 4ac068ec - r2 = cat2[-2]
    309 c605dfcd + r2 = cat2[-2]
    ? ++++
    282 4ac068ec - f2 = r2.getFootprint()
    310 c605dfcd + f2 = r2.getFootprint()
    ? ++++
    283 4ac068ec - self.assertTrue(f2.isHeavy())
    311 c605dfcd + self.assertTrue(f2.isHeavy())
    ? ++++
    284 4ac068ec - h2 = lsst.afw.detection.cast_HeavyFootprintF(f2)
    312 c605dfcd + h2 = lsst.afw.detection.cast_HeavyFootprintF(f2)
    ? ++++
    285 4ac068ec - mim3 = lsst.afw.image.MaskedImageF(W, H)
    313 c605dfcd + mim3 = lsst.afw.image.MaskedImageF(W, H)
    ? ++++
    286 4ac068ec - h2.insert(mim3)
    314 c605dfcd + h2.insert(mim3)
    ? ++++
    288 4ac068ec - self.assertFalse(cat2[-1].getFootprint().isHeavy())
    316 c605dfcd + self.assertFalse(cat2[-1].getFootprint().isHeavy())
    ? ++++
    289 4ac068ec - self.assertFalse(cat2[-3].getFootprint().isHeavy())
    317 c605dfcd + self.assertFalse(cat2[-3].getFootprint().isHeavy())
    ? ++++
    290 4ac068ec - self.assertFalse(cat2[0].getFootprint().isHeavy())
    318 c605dfcd + self.assertFalse(cat2[0].getFootprint().isHeavy())
    ? ++++
    291 4ac068ec - self.assertFalse(cat2[1].getFootprint().isHeavy())
    319 c605dfcd + self.assertFalse(cat2[1].getFootprint().isHeavy())
    ? ++++
    292 4ac068ec - self.assertFalse(cat2[2].getFootprint().isHeavy())
    320 c605dfcd + self.assertFalse(cat2[2].getFootprint().isHeavy())
    ? ++++
    294 4ac068ec - if False:
    322 c605dfcd + if False:
    ? ++++
    295 4ac068ec - # Write out before-n-after FITS images
    323 c605dfcd + # Write out before-n-after FITS images
    ? ++++
    296 4ac068ec - for MI in [mim, mim2, mim3]:
    324 c605dfcd + for MI in [mim, mim2, mim3]:
    ? ++++
    297 4ac068ec - f,fn2 = tempfile.mkstemp(prefix='testHeavyFootprint-', suffix='.fits')
    325 c605dfcd + f,fn2 = tempfile.mkstemp(prefix='testHeavyFootprint-', suffix='.fits')
    ? ++++
    298 4ac068ec - os.close(f)
    326 c605dfcd + os.close(f)
    ? ++++
    299 4ac068ec - MI.writeFits(fn2)
    327 c605dfcd + MI.writeFits(fn2)
    ? ++++
    300 4ac068ec - print 'wrote', fn2
    328 c605dfcd + print 'wrote', fn2
    ? ++++
    302 4ac068ec - self.assertTrue(all((mim2.getImage().getArray() == mim3.getImage().getArray()).ravel()))
    330 c605dfcd + self.assertTrue(all((mim2.getImage().getArray() == mim3.getImage().getArray()).ravel()))
    ? ++++
    303 4ac068ec - self.assertTrue(all((mim2.getMask().getArray() == mim3.getMask().getArray()).ravel()))
    331 c605dfcd + self.assertTrue(all((mim2.getMask().getArray() == mim3.getMask().getArray()).ravel()))
    ? ++++
    304 4ac068ec - self.assertTrue(all((mim2.getVariance().getArray() == mim3.getVariance().getArray()).ravel()))
    332 c605dfcd + self.assertTrue(all((mim2.getVariance().getArray() == mim3.getVariance().getArray()).ravel()))
    ? ++++
    306 4ac068ec - im3 = mim3.getImage()
    334 c605dfcd + im3 = mim3.getImage()
    ? ++++
    307 4ac068ec - ma3 = mim3.getMask()
    335 c605dfcd + ma3 = mim3.getMask()
    ? ++++
    308 4ac068ec - va3 = mim3.getVariance()
    336 c605dfcd + va3 = mim3.getVariance()
    ? ++++
    309 4ac068ec - for y in range(H):
    337 c605dfcd + for y in range(H):
    ? ++++
    310 4ac068ec - for x in range(W):
    338 c605dfcd + for x in range(W):
    ? ++++
    311 4ac068ec - if circ.contains(lsst.afw.geom.Point2I(x, y)):
    339 c605dfcd + if circ.contains(lsst.afw.geom.Point2I(x, y)):
    ? ++++
    312 4ac068ec - self.assertEqual(im.get(x, y), im3.get(x, y))
    340 c605dfcd + self.assertEqual(im.get(x, y), im3.get(x, y))
    ? ++++
    313 4ac068ec - self.assertEqual(msk.get(x, y), ma3.get(x, y))
    341 c605dfcd + self.assertEqual(msk.get(x, y), ma3.get(x, y))
    ? ++++
    314 4ac068ec - self.assertEqual(var.get(x, y), va3.get(x, y))
    342 c605dfcd + self.assertEqual(var.get(x, y), va3.get(x, y))
    ? ++++
    315 4ac068ec - else:
    343 c605dfcd + else:
    ? ++++
    316 4ac068ec - self.assertEqual(im3.get(x, y), 0.)
    344 c605dfcd + self.assertEqual(im3.get(x, y), 0.)
    ? ++++
    317 4ac068ec - self.assertEqual(ma3.get(x, y), 0.)
    345 c605dfcd + self.assertEqual(ma3.get(x, y), 0.)
    ? ++++
    318 4ac068ec - self.assertEqual(va3.get(x, y), 0.)
    346 c605dfcd + self.assertEqual(va3.get(x, y), 0.)
    ? ++++
    320 fbdf0845 - cat3 = lsst.afw.table.SourceCatalog.readFits(fn, 0, lsst.afw.table.SOURCE_IO_NO_HEAVY_FOOTPRINTS)
    348 c605dfcd + cat3 = lsst.afw.table.SourceCatalog.readFits(fn, 0, lsst.afw.table.SOURCE_IO_NO_HEAVY_FOOTPRINTS)
    ? ++++
    321 fbdf0845 - for src in cat3:
    349 c605dfcd + for src in cat3:
    ? ++++
    322 fbdf0845 - self.assertFalse(src.getFootprint().isHeavy())
    350 c605dfcd + self.assertFalse(src.getFootprint().isHeavy())
    ? ++++
    323 fbdf0845 - cat4 = lsst.afw.table.SourceCatalog.readFits(fn, 0, lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS)
    351 c605dfcd + cat4 = lsst.afw.table.SourceCatalog.readFits(fn, 0, lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS)
    ? ++++
    324 fbdf0845 - for src in cat4:
    352 c605dfcd + for src in cat4:
    ? ++++
    325 fbdf0845 - self.assertIsNone(src.getFootprint())
    353 c605dfcd + self.assertIsNone(src.getFootprint())
    ? ++++
    327 fbdf0845 - self.catalog.writeFits(fn, flags=lsst.afw.table.SOURCE_IO_NO_HEAVY_FOOTPRINTS)
    355 c605dfcd + self.catalog.writeFits(fn, flags=lsst.afw.table.SOURCE_IO_NO_HEAVY_FOOTPRINTS)
    ? ++++
    328 fbdf0845 - cat5 = lsst.afw.table.SourceCatalog.readFits(fn)
    356 c605dfcd + cat5 = lsst.afw.table.SourceCatalog.readFits(fn)
    ? ++++
    329 fbdf0845 - for src in cat5:
    357 c605dfcd + for src in cat5:
    ? ++++
    330 fbdf0845 - self.assertFalse(src.getFootprint().isHeavy())
    358 c605dfcd + self.assertFalse(src.getFootprint().isHeavy())
    ? ++++
    332 fbdf0845 - self.catalog.writeFits(fn, flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS)
    360 c605dfcd + self.catalog.writeFits(fn, flags=lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS)
    ? ++++
    333 fbdf0845 - cat6 = lsst.afw.table.SourceCatalog.readFits(fn)
    361 c605dfcd + cat6 = lsst.afw.table.SourceCatalog.readFits(fn)
    ? ++++
    334 fbdf0845 - for src in cat6:
    362 c605dfcd + for src in cat6:
    ? ++++
    335 fbdf0845 - self.assertIsNone(src.getFootprint())
    363 c605dfcd + self.assertIsNone(src.getFootprint())
    ? ++++ def testIdFactory(self): expId = int(1257198) reserved = 32 factory = lsst.afw.table.IdFactory.makeSource(expId, reserved) upper = expId id1 = factory() id2 = factory() self.assertEqual(id2 - id1, 1) factory.notify(0xFFFFFFFF)
    346 91a3a093 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, factory)
    ? ^^^^^^^^^^^^^^^ ------- ------ ---------
    374 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, factory)
    ? ++ ^
    375 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError, factory.notify, 0x1FFFFFFFF)
    347 91a3a093 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
    ? ^^^^^^^^^^^^^^^ ------- ------ ^^^^^^ ^
    376 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError,
    ? ++ ^ ^^ ^
    348 91a3a093 - factory.notify, 0x1FFFFFFFF)
    349 91a3a093 - lsst.utils.tests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException,
    lsst.afw.table.IdFactory.makeSource, 0x1FFFFFFFF, reserved) def testFamilies(self): self.catalog.sort() parents = self.catalog.getChildren(0) self.assertEqual(list(parents), list(self.catalog)) parentKey = lsst.afw.table.SourceTable.getParentKey() for parent in parents: self.assertEqual(parent.get(parentKey), 0) for i in range(10): child = self.catalog.addNew() self.fillRecord(child) child.set(parentKey, parent.getId()) for parent in parents: children, ids = self.catalog.getChildren(parent.getId(), [record.getId() for record in self.catalog]) self.assertEqual(len(children), 10) self.assertEqual(len(children), len(ids)) for child, id in zip(children, ids): self.assertEqual(child.getParent(), parent.getId()) self.assertEqual(child.getId(), id)
    398 75465627 +
    399 f05aa3ed + def testFitsReadBackwardsCompatibility(self):
    400 f05aa3ed + cat = lsst.afw.table.SourceCatalog.readFits("tests/data/slotsVersion0.fits")
    401 f05aa3ed + self.assertTrue(cat.getPsfFluxSlot().isValid())
    402 f05aa3ed + self.assertTrue(cat.getApFluxSlot().isValid())
    403 f05aa3ed + self.assertTrue(cat.getInstFluxSlot().isValid())
    404 f05aa3ed + self.assertTrue(cat.getModelFluxSlot().isValid())
    405 f05aa3ed + self.assertTrue(cat.getCentroidSlot().isValid())
    406 f05aa3ed + self.assertTrue(cat.getShapeSlot().isValid())
    407 f05aa3ed + self.assertEqual(cat.getPsfFluxSlot().getMeasKey(), cat.schema.find("flux").key)
    408 f05aa3ed + self.assertEqual(cat.getApFluxSlot().getMeasKey(), cat.schema.find("flux").key)
    409 f05aa3ed + self.assertEqual(cat.getInstFluxSlot().getMeasKey(), cat.schema.find("flux").key)
    410 f05aa3ed + self.assertEqual(cat.getModelFluxSlot().getMeasKey(), cat.schema.find("flux").key)
    411 f05aa3ed + self.assertEqual(cat.getCentroidSlot().getMeasKey().getX(), cat.schema.find("centroid.x").key)
    412 f05aa3ed + self.assertEqual(cat.getCentroidSlot().getMeasKey().getY(), cat.schema.find("centroid.y").key)
    413 f05aa3ed + self.assertEqual(cat.getShapeSlot().getMeasKey().getIxx(), cat.schema.find("shape.xx").key)
    414 f05aa3ed + self.assertEqual(cat.getShapeSlot().getMeasKey().getIyy(), cat.schema.find("shape.yy").key)
    415 f05aa3ed + self.assertEqual(cat.getShapeSlot().getMeasKey().getIxy(), cat.schema.find("shape.xy").key)
    416 f05aa3ed + self.assertEqual(cat.getPsfFluxSlot().getErrKey(), cat.schema.find("flux.err").key)
    417 f05aa3ed + self.assertEqual(cat.getApFluxSlot().getErrKey(), cat.schema.find("flux.err").key)
    418 f05aa3ed + self.assertEqual(cat.getInstFluxSlot().getErrKey(), cat.schema.find("flux.err").key)
    419 f05aa3ed + self.assertEqual(cat.getModelFluxSlot().getErrKey(), cat.schema.find("flux.err").key)
    420 f05aa3ed + self.assertEqual(cat.getCentroidSlot().getErrKey(),
    421 f05aa3ed + lsst.afw.table.makeCovarianceMatrixKey(cat.schema.find("centroid.err").key))
    422 f05aa3ed + self.assertEqual(cat.getShapeSlot().getErrKey(),
    423 f05aa3ed + lsst.afw.table.makeCovarianceMatrixKey(cat.schema.find("shape.err").key))
    424 f05aa3ed + self.assertEqual(cat.getPsfFluxSlot().getFlagKey(), cat.schema.find("flux.flags").key)
    425 f05aa3ed + self.assertEqual(cat.getApFluxSlot().getFlagKey(), cat.schema.find("flux.flags").key)
    426 f05aa3ed + self.assertEqual(cat.getInstFluxSlot().getFlagKey(), cat.schema.find("flux.flags").key)
    427 f05aa3ed + self.assertEqual(cat.getModelFluxSlot().getFlagKey(), cat.schema.find("flux.flags").key)
    428 f05aa3ed + self.assertEqual(cat.getCentroidSlot().getFlagKey(), cat.schema.find("centroid.flags").key)
    429 f05aa3ed + self.assertEqual(cat.getShapeSlot().getFlagKey(), cat.schema.find("shape.flags").key)
    430 f05aa3ed +
    431 abe8cdba + def testDM1083(self):
    432 abe8cdba + schema = lsst.afw.table.SourceTable.makeMinimalSchema()
    433 abe8cdba + st = lsst.afw.table.SourceTable.make(schema)
    434 abe8cdba + cat = lsst.afw.table.SourceCatalog(st)
    435 abe8cdba + tmp = lsst.afw.table.SourceCatalog(cat.getTable())
    436 abe8cdba + record = tmp.addNew()
    437 abe8cdba + cat.extend(tmp)
    438 abe8cdba + self.assertEqual(cat[0].getId(), record.getId())
    439 abe8cdba + # check that the same record is in both catalogs (not a copy)
    440 abe8cdba + record.setId(15)
    441 abe8cdba + self.assertEqual(cat[0].getId(), record.getId())
    442 abe8cdba +
    443 286e5d96 + def testSlotUndefine(self):
    444 286e5d96 + """Test that we can correctly define and undefine a slot after a SourceTable has been created"""
    445 286e5d96 + schema = lsst.afw.table.SourceTable.makeMinimalSchema()
    446 286e5d96 + key = schema.addField("a_flux", type=float, doc="flux field")
    447 286e5d96 + table = lsst.afw.table.SourceTable.make(schema)
    448 286e5d96 + table.definePsfFlux("a")
    449 286e5d96 + self.assertEqual(table.getPsfFluxKey(), key)
    450 286e5d96 + table.schema.getAliasMap().erase("slot_PsfFlux")
    451 286e5d96 + self.assertFalse(table.getPsfFluxKey().isValid())
    def testOldFootprintPersistence(self): """Test that we can still read SourceCatalogs with (Heavy)Footprints saved by an older version of the pipeline with a different format. """ filename = os.path.join("tests", "data", "old-footprint-persistence.fits") catalog1 = lsst.afw.table.SourceCatalog.readFits(filename) self.assertEqual(len(catalog1), 2) self.assertRaises(KeyError, catalog1.schema.find, "footprint") fp1 = catalog1[0].getFootprint() fp2 = catalog1[1].getFootprint() self.assertEqual(fp1.getArea(), 495) self.assertEqual(fp2.getArea(), 767) self.assertFalse(fp1.isHeavy()) self.assertTrue(fp2.isHeavy()) self.assertEqual(len(fp1.getSpans()), 29) self.assertEqual(len(fp2.getSpans()), 44) self.assertEqual(len(fp1.getPeaks()), 1) self.assertEqual(len(fp2.getPeaks()), 1) self.assertEqual(fp1.getBBox(), lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(129,2), lsst.afw.geom.Extent2I(25, 29))) self.assertEqual(fp2.getBBox(), lsst.afw.geom.Box2I(lsst.afw.geom.Point2I(1184,2), lsst.afw.geom.Extent2I(78, 38))) hfp = lsst.afw.detection.cast_HeavyFootprintF(fp2) self.assertEqual(len(hfp.getImageArray()), fp2.getArea()) self.assertEqual(len(hfp.getMaskArray()), fp2.getArea()) self.assertEqual(len(hfp.getVarianceArray()), fp2.getArea()) catalog2 = lsst.afw.table.SourceCatalog.readFits(filename, 0, lsst.afw.table.SOURCE_IO_NO_HEAVY_FOOTPRINTS) self.assertEqual(list(fp1.getSpans()), list(catalog2[0].getFootprint().getSpans())) self.assertEqual(list(fp2.getSpans()), list(catalog2[1].getFootprint().getSpans())) self.assertFalse(catalog2[1].getFootprint().isHeavy()) catalog3 = lsst.afw.table.SourceCatalog.readFits(filename, 0, lsst.afw.table.SOURCE_IO_NO_FOOTPRINTS) self.assertEqual(catalog3[0].getFootprint(), None) self.assertEqual(catalog3[1].getFootprint(), None) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" lsst.utils.tests.init() suites = [] suites += unittest.makeSuite(SourceTableTestCase) suites += unittest.makeSuite(lsst.utils.tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" lsst.utils.tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3e1f9e0b

    commit 3e1f9e0b78f337ea33e6fef04ba5e24c2eb5a47f
    Author: Jim Bosch 
    Date:   Wed Jan 11 16:58:43 2012 -0500
    
        added configurable canonical fields to SourceTable/SourceRecord, renamed Shape tag class to Moments to avoid collisions with long-standing measurement names.
    

    d4c421d8

    commit d4c421d80baa4ebae245366db4c6d7e7cde18ba6
    Author: Jim Bosch 
    Date:   Mon Mar 12 19:38:06 2012 -0400
    
        added slot accessors to ColumnView for Source
    

    fa7147a0

    commit fa7147a08f6477e6727aefc9e6e6b8840f1ad5b1
    Author: Jim Bosch 
    Date:   Sat Feb 25 12:42:14 2012 -0500
    
        added SourceRecord method to update coord field using centroid field and Wcs
    

    4ce9656b

    commit 4ce9656bc5d7ec5c4612f98f33ca2a5288e38383
    Author: Jim Bosch 
    Date:   Wed May 22 12:17:01 2013 -0400
    
        Add column getters for flux slot error fields (#2889).
    

    df04c833

    commit df04c833b934e9e16e2d4ff8c7decfeea2c4ae6a
    Author: Jim Bosch 
    Date:   Tue Mar 13 12:58:43 2012 -0400
    
        Catalog objects now forward attribute access to their tables and column views, and support direct access to column arrays through __getitem__ or get
    

    4ac068ec

    commit 4ac068ecd9edb486fc070411927521ec8c99ac97
    Author: Dustin Lang 
    Date:   Mon May 21 12:15:04 2012 -0400
    
        add test of round-tripping HeavyFootprits to FITS
    

    ecd0c5af

    commit ecd0c5af7cb5b6b33e0d963d6e12d711d4bed447
    Author: Jim Bosch 
    Date:   Tue Mar 13 20:31:29 2012 -0400
    
        added packed bit flag arrays to column views
    

    57671a18

    commit 57671a18736213d044e29c3cc8799bc7d5c37fce
    Author: Jim Bosch 
    Date:   Thu May 24 16:27:34 2012 -0400
    
        Replace afw::table scalar type strings (I4,I8,F4,F8) with notation used elsewhere (I,L,F,D).
    

    2063bd97

    commit 2063bd97bc6beceb2509ce1606c63c7d0d5e8d0c
    Author: Jim Bosch 
    Date:   Fri Jun 29 16:59:50 2012 -0400
    
        allow table slots to be partially defined (only measurement key is required)
    

    fbdf0845

    commit fbdf08458f287be72ad231a0e50fa3c519941fb6
    Author: Jim Bosch 
    Date:   Tue Jun 18 18:56:39 2013 -0600
    
        Use Catalog I/O flags to control writing of Source footprints
        
        This replaces the previous mechanism for controlling whether
        to write heavy footprints, which involved a SourceTable data
        member.
    

    36b29961

    commit 36b2996182c10928602622e87542fbf7d0d6a2ec
    Author: Jim Bosch 
    Date:   Wed Nov 21 17:09:31 2012 -0500
    
        Make all afw::table covariance matrices single-precision.
        
        It's a good idea in general (see #1998), and it also frees up space for other field types inside boost::variant's unfortunate 20-type limit (it'd be nice to get rid of that; maybe C++11 would help?)
        
        FITS reading is backwards compatible in that double-precision covariance fields previously saved to FITS will be read in as single precision.
    

    91a3a093

    commit 91a3a0935b9dff83459b73f19ab684f3265d2650
    Author: Jim Bosch 
    Date:   Sat Apr 28 18:05:27 2012 -0400
    
        added IdFactory for sources that includes the exposure ID in the upper bits
    

    0323a937

    commit 0323a93723fff8e9eca6b473dcfb57d828888c99
    Author: Paul Price 
    Date:   Tue Sep 25 14:20:53 2012 -0400
    
        Ticket 2344: Make lsst.afw.table.CatalogT picklable.
        
        To do so, we write the Catalog as FITS in memory.
        This involves activating (almost-)existing support for the MemFileManager.
    

    6581586d

    commit 6581586d25bea008aadd57a10968ca6c9fb72677
    Author: Jim Bosch 
    Date:   Mon Jan 30 01:09:10 2012 -0500
    
        fixed bug in schema key-based lookups, added flag fields to standard measurements
    

    Commits in /Users/nate/repos_lsst/afw/

    87181699

    commit 871816997c7c61b067d8731c362927ab95563f8a
    Author: Jim Bosch 
    Date:   Mon Aug 25 01:06:11 2014 -0400
    
        Clean up some tests and make sure they're executable
    

    5e98dbb9

    commit 5e98dbb9508b4a0a6b3578d6bf9572b8f6380c5c
    Author: Perry Gee 
    Date:   Fri Apr 25 19:33:24 2014 -0500
    
        New unit test for DM-433.
        Fix unit tests to work with new table versioning system.
        Note:  these old tests just setVersion(0) for now.
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    75465627

    commit 75465627ebc9c29eae47e080238369939e935025
    Author: Jim Bosch 
    Date:   Mon Nov 18 13:07:36 2013 -0500
    
        Add getChildren() method to SourceCatalog (in Python only) to extract deblend families (#3056)
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    4bae7ca1

    commit 4bae7ca131d04a3f68e47748b0423617ffd33000
    Author: Paul Price 
    Date:   Wed Aug 6 16:40:49 2014 -0400
    
        tests: seed random number generator to make tests deterministic
    

    dce194d3

    commit dce194d3b409b3718149c99ee1dbe5620ccee734
    Author: John Swinbank 
    Date:   Thu Apr 2 19:09:27 2015 -0400
    
        Extend QuadrupoleKey to celestial coords.
        
        We can thereby use the same underlying mechanism to describe quadrupoles in
        pixel and celestial coordinates. Internally, we continue to refer to "x" and
        "y", but use appropriate names and units when writing to a table.
    

    286e5d96

    commit 286e5d968cb1f06bac4ecca37622a78163c44e6a
    Author: Jim Bosch 
    Date:   Tue Jan 27 13:16:12 2015 -0500
    
        Correctly handle slots being undefined.
        
        Prior to this change, slots were only allowed to be undefined when the
        SourceTable is constructed, and removing slot aliases caused an exception
        to be thrown.  Now, removing a slot alias simply resets that slot.
    

    a25b9eb2

    commit a25b9eb2df1c00b862411068c0447f4391bb12f4
    Author: pgee 
    Date:   Wed Mar 4 17:06:38 2015 -0800
    
        DM-1076, remove need of unit tests to setVersion(0), and move tests to default version.
        
        Note that there are several version tests in the unit tests which should not be changed.
        Also needed to change Schema::getNames to use the '_' separator for version > 0.
        Also included responses to review comments
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    abe8cdba

    commit abe8cdba64c110a317f19412cd9f8ef835b3ebe5
    Author: Jim Bosch 
    Date:   Thu Jan 8 15:48:43 2015 -0500
    
        Add test case for DM-1083; looks like the bug has already been solved
        
        The problem reported on DM-1083 looks very similar to DM-1710 and
        DM-1514, and it's likely it was fixed with one of those, so I'm just adding
        the how-to-reproduce from DM-1083 as a unit test.
    

    f05aa3ed

    commit f05aa3ed81bf92c5bfe281d4ab725c89ecf180aa
    Author: Jim Bosch 
    Date:   Mon Aug 25 15:42:54 2014 -0400
    
        Test, fix backwards compatibility for old slot persistence
    

    Return to list

    tests/statisticsMasked.py

    Diff:

    1 823db3e8 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for statisticsMasked Run with: ./statisticsMasked.py or python >>> import statisticsMasked; statisticsMasked.run() """ import unittest import numpy import lsst.utils.tests as utilsTests import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.afw.math as afwMath #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class StatisticsTestCase(unittest.TestCase): """A test case to check that special values (NaN and Masks) are begin handled in Statistics""" def setUp(self): self.valL, self.valR = 10, 20 self.nRow, self.nCol = 100, 200 self.n = self.nRow*self.nCol self.bboxL = afwGeom.Box2I(afwGeom.Point2I(0, 0),
    56 c9c89e06 - afwGeom.Point2I(self.nRow/2 - 1, self.nCol - 1))
    57 b80fe1d3 + afwGeom.Point2I(self.nRow//2 - 1, self.nCol - 1))
    ? +
    57 c9c89e06 - self.bboxR = afwGeom.Box2I(afwGeom.Point2I(self.nRow/2, 0),
    58 b80fe1d3 + self.bboxR = afwGeom.Box2I(afwGeom.Point2I(self.nRow//2, 0),
    ? + afwGeom.Point2I(self.nRow - 1, self.nCol - 1)) # create masked images and set the left side to valL, and right to valR self.mimg = afwImage.MaskedImageF(afwGeom.Extent2I(self.nRow, self.nCol)) self.mimg.set(0.0, 0x0, 0.0) self.mimgL = afwImage.MaskedImageF(self.mimg, self.bboxL, afwImage.LOCAL) self.mimgL.set(self.valL, 0x0, self.valL) self.mimgR = afwImage.MaskedImageF(self.mimg, self.bboxR, afwImage.LOCAL) self.mimgR.set(self.valR, 0x0, self.valR) def tearDown(self): del self.mimg del self.mimgL del self.mimgR # Verify that NaN values are being ignored # (by default, StatisticsControl.useNanSafe = True) # We'll set the L and R sides of an image to two different values and verify mean and stdev # ... then set R-side to NaN and try again ... we should get mean,stdev for L-side def testNaN(self): # get the stats for the image with two values stats = afwMath.makeStatistics(self.mimg, afwMath.NPOINT | afwMath.MEAN | afwMath.STDEV) mean = 0.5*(self.valL + self.valR) nL, nR = self.mimgL.getWidth()*self.mimgL.getHeight(), self.mimgR.getWidth()*self.mimgR.getHeight() stdev = ((nL*(self.valL - mean)**2 + nR*(self.valR - mean)**2)/(nL + nR - 1))**0.5 self.assertEqual(stats.getValue(afwMath.NPOINT), self.n) self.assertEqual(stats.getValue(afwMath.MEAN), mean) self.assertEqual(stats.getValue(afwMath.STDEV), stdev) # set the right side to NaN and stats should be just for the left side self.mimgR.set(numpy.nan, 0x0, self.valR) statsNaN = afwMath.makeStatistics(self.mimg, afwMath.NPOINT | afwMath.MEAN | afwMath.STDEV) mean = self.valL stdev = 0.0 self.assertEqual(statsNaN.getValue(afwMath.NPOINT), nL) self.assertEqual(statsNaN.getValue(afwMath.MEAN), mean) self.assertEqual(statsNaN.getValue(afwMath.STDEV), stdev) # Verify that Masked pixels are being ignored according to the andMask # (by default, StatisticsControl.andMask = 0x0) # We'll set the L and R sides of an image to two different values and verify mean and stdev # ... then set R-side Mask and the andMask to 0x1 and try again ... we should get mean,stdev for L-side def testMasked(self): # get the stats for the image with two values self.mimgR.set(self.valR, 0x0, self.valR) stats = afwMath.makeStatistics(self.mimg, afwMath.NPOINT | afwMath.MEAN | afwMath.STDEV) mean = 0.5*(self.valL + self.valR) nL, nR = self.mimgL.getWidth()*self.mimgL.getHeight(), self.mimgR.getWidth()*self.mimgR.getHeight() stdev = ((nL*(self.valL - mean)**2 + nR*(self.valR - mean)**2)/(nL + nR - 1))**0.5 self.assertEqual(stats.getValue(afwMath.NPOINT), self.n) self.assertEqual(stats.getValue(afwMath.MEAN), mean) self.assertEqual(stats.getValue(afwMath.STDEV), stdev) # set the right side Mask and the StatisticsControl andMask to 0x1 # Stats should be just for the left side! maskBit = 0x1 self.mimgR.getMask().set(maskBit) sctrl = afwMath.StatisticsControl() sctrl.setAndMask(maskBit) statsNaN = afwMath.makeStatistics(self.mimg, afwMath.NPOINT | afwMath.MEAN | afwMath.STDEV, sctrl) mean = self.valL stdev = 0.0 self.assertEqual(statsNaN.getValue(afwMath.NPOINT), nL) self.assertEqual(statsNaN.getValue(afwMath.MEAN), mean) self.assertEqual(statsNaN.getValue(afwMath.STDEV), stdev) # Verify that pixels are being weighted according to the variance plane (1/var) # We'll set the L and R sides of an image to two different values and verify mean # ... then set R-side Variance to equal the Image value, and set 'weighted' and try again ... def testWeighted(self): self.mimgR.set(self.valR, 0x0, self.valR) sctrl = afwMath.StatisticsControl() sctrl.setWeighted(True) stats = afwMath.makeStatistics(self.mimg, afwMath.NPOINT | afwMath.MEAN | afwMath.STDEV, sctrl) nL, nR = self.mimgL.getWidth()*self.mimgL.getHeight(), self.mimgR.getWidth()*self.mimgR.getHeight() mean = 1.0*(nL + nR)/(nL/self.valL + nR/self.valR) # get the stats for the image with two values self.assertEqual(stats.getValue(afwMath.NPOINT), self.n) self.assertAlmostEqual(stats.getValue(afwMath.MEAN), mean, 10) def testWeightedSimple(self): mimg = afwImage.MaskedImageF(afwGeom.Extent2I(1, 2)) mimg.set(0, 0, (self.valR, 0x0, self.valR)) mimg.set(0, 1, (self.valL, 0x0, self.valL)) sctrl = afwMath.StatisticsControl() sctrl.setWeighted(True) stats = afwMath.makeStatistics(mimg, afwMath.NPOINT | afwMath.MEAN | afwMath.STDEV, sctrl) vsum = 2.0 vsum2 = self.valR + self.valL wsum = 1.0/self.valR + 1.0/self.valL wwsum = 1.0/self.valR**2 + 1.0/self.valL**2 mean = vsum/wsum variance = vsum2/wsum - mean**2 # biased variance n = 2 # original estimate; just a rewrite of the usual n/(n - 1) correction stddev = (1.0*(vsum2)/(wsum*(1.0-1.0/n)) - (vsum**2)/(wsum**2*(1.0-1.0/n)))**0.5 self.assertAlmostEqual(stddev, numpy.sqrt(variance*n/(n - 1))) # # The correct formula: stddev = numpy.sqrt(variance*wsum**2/(wsum**2 - wwsum)) # get the stats for the image with two values self.assertAlmostEqual(stats.getValue(afwMath.MEAN), mean, 10) self.assertAlmostEqual(stats.getValue(afwMath.STDEV), stddev, 10) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(StatisticsTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    823db3e8

    commit 823db3e850744057f4912c72b9e4c453a9b6e633
    Author: bick 
    Date:   Tue Sep 29 20:09:10 2009 +0000
    
        Added tests to verify overleaded factories, NaN being ignored, and Masked pixels being ignored.
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    include/lsst/afw/table/io/Writer.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_IO_Writer_h_INCLUDED
                    #define AFW_TABLE_IO_Writer_h_INCLUDED
                    
                    #include 
                    
                    #include "lsst/base.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/table/BaseTable.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    class BaseRecord;
                    
                    namespace io {
                    
                    /**
                     *  @brief Write a container of records to disk (or elsewhere).
                     *
                     *  An instance of Writer is associated with a particular file or storage location,
                     *  and can be invoked by calling write() with a container.
                     *
                     *  Writer contains driver code that should work for most input operations and record
                     *  containers, and delegates the real work to protected member functions.  Writer does
                     *  not specify how it will be constructed.
                     */
                    class Writer {
                    public:
                    
                        /**
                         *  @brief Write records in a container to disk (or elsewhere).
                         *
                         *  The given container must have a getTable() member function that returns a shared_ptr
                         *  to a table, and the iterators returned by begin() and end() must dereference to a type
                         *  convertible to BaseRecord const &.
                         */
                        template 
                        void write(ContainerT const & container) {
                            std::set tables;
                            for (typename ContainerT::const_iterator i = container.begin(); i != container.end(); ++i) {
                                if (i->getTable() != container.getTable()) tables.insert(i->getTable());
                            }
                            for (std::set::iterator j = tables.begin(); j != tables.end(); ++j) {
                                if (
                                    (**j).getSchema().compare(container.getTable()->getSchema(), Schema::IDENTICAL)
                                    != Schema::IDENTICAL
                                ) {
                                    throw LSST_EXCEPT(
    
    49 2f0fa9cd - pex::exceptions::LogicErrorException,
    ? ---------
    49 21597d88 + pex::exceptions::LogicError,
    "Cannot save Catalog with heterogenous schemas" ); } } _writeTable(container.getTable(), container.size()); for (typename ContainerT::const_iterator i = container.begin(); i != container.end(); ++i) { _writeRecord(*i); } _finish(); } virtual ~Writer() {} protected: /// @brief Write a table and its schema. virtual void _writeTable(CONST_PTR(BaseTable) const & table, std::size_t nRows) = 0; /// @brief Write an individual record. virtual void _writeRecord(BaseRecord const & record) = 0; /// @brief Finish writing a catalog. virtual void _finish() {} }; }}}} // namespace lsst::afw::table::io #endif // !AFW_TABLE_IO_Writer_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    2f0fa9cd

    commit 2f0fa9cdd45a5ee41f019fd7a2a7b4ca6ec79afb
    Author: Jim Bosch 
    Date:   Mon Jul 1 11:58:21 2013 -0600
    
        Don't require all records in a catalog to share a table (#2938)
        
        Now we just check for compatible schemas when writing to FITS.
        
        Also fixed up some documentation formatting while updating the
        docs to reflect the change in behavior
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/wcs1.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . #
    25 61855404 - import os
    26 c605dfcd + import os.path
    ? +++++ import math
    27 ad4a9b08 - import pdb # we may want to say pdb.set_trace()
    import unittest
    30 16c71f25 - import eups
    30 7cbb2bb9 + import lsst.utils
    import lsst.daf.base as dafBase import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.afw.coord as afwCoord import lsst.utils.tests as utilsTests import lsst.afw.display.ds9 as ds9
    37 92a588b5 - import lsst.pex.exceptions.exceptionsLib as exceptions
    import lsst import numpy try: type(verbose) except NameError: verbose = 0
    46 456d42a8 - dataDir = eups.productDir("afwdata")
    45 7cbb2bb9 + dataDir = lsst.utils.getPackageDir("afwdata")
    if not dataDir: raise RuntimeError("Must set up afwdata to run these tests") InputImagePath = os.path.join(dataDir, "871034p_1_MI") InputSmallImagePath = os.path.join(dataDir, "data", "small_img.fits") InputCorruptMaskedImageName = "small_MI_corrupt" currDir = os.path.abspath(os.path.dirname(__file__)) InputCorruptFilePath = os.path.join(currDir, "data", InputCorruptMaskedImageName) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class WcsTestCase(unittest.TestCase): def testCD_PC(self): """Test that we can read a FITS file with both CD and PC keys (like early Suprimecam files)""" md = dafBase.PropertyList() for k, v in ( ("EQUINOX", 2000.0), ("RADESYS", 'FK5'), ("CRPIX1" , 5353.0), ("CRPIX2" , -35.0), ("CD1_1" , 0.0), ("CD1_2" , -5.611E-05), ("CD2_1" , -5.611E-05), ("CD2_2" , -0.0), ("CRVAL1" , 4.5789875), ("CRVAL2" , 16.30004444), ("CUNIT1" , 'deg'), ("CUNIT2" , 'deg'), ("CTYPE1" , 'RA---TAN'), ("CTYPE2" , 'DEC--TAN'), ("CDELT1" , -5.611E-05), ("CDELT2" , 5.611E-05), ): md.set(k, v) wcs = afwImage.makeWcs(md) x, y = 1000, 2000 ra, dec = 4.459815023498577, 16.544199850984768 sky = wcs.pixelToSky(x, y) for i, v in enumerate([ra, dec]): self.assertEqual(sky[i].asDegrees(), v) for badPC in (False, True): if verbose: print "Checking PC coefficients: badPC =", badPC for k, v in ( ("PC001001", 0.0), ("PC001002", -1.0 if badPC else 1.0), ("PC002001", 1.0 if badPC else -1.0), ("PC002002", 0.0), ): md.set(k, v) # Check Greisen and Calabretta A&A 395 1061 (2002), Eq. 3 if not badPC: for i in (1, 2,): for j in (1, 2,): self.assertEqual(md.get("CD%d_%d" % (i, j)), md.get("CDELT%d" % i)*md.get("PC00%d00%d" % (i, j))) wcs = afwImage.makeWcs(md) sky = wcs.pixelToSky(x, y) for i, v in enumerate([ra, dec]): self.assertEqual(sky[i].asDegrees(), v) def testCast(self): # strangely, this overload of makeWcs returns a TAN WCS that's not a TanWcs wcs = afwImage.makeWcs(afwCoord.IcrsCoord(45.0*afwGeom.degrees, 45.0*afwGeom.degrees), afwGeom.Point2D(0.0, 0.0), 1.0, 0.0, 0.0, 1.0) # ...but if you round-trip it through a PropertySet, you get a TanWcs in a Wcs ptr, # which is what we want for this test. base = afwImage.makeWcs(wcs.getFitsMetadata()) self.assertEqual(type(base), afwImage.Wcs) derived = afwImage.TanWcs.cast(base) self.assertEqual(type(derived), afwImage.TanWcs) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class WCSRotateFlip(unittest.TestCase): """A test case for the methods to rotate and flip a wcs under similar operations to the image pixels""" def setUp(self): self.size = afwGeom.Extent2I(509, 2000) def tearDown(self): del self.size def makeWcs(self): crval = afwCoord.Coord(afwGeom.Point2D(1.606631, 5.090329)) crpix = afwGeom.Point2D(2036., 2000.) wcs = afwImage.makeWcs(crval, crpix, 5.399452e-5, -1.30770e-5, 1.30770e-5, 5.399452e-5) def testRotation(self): q1 = {0:afwGeom.Point2D(100., 1600.), 1:afwGeom.Point2D(self.size.getY() - 1600., 100.), 2:afwGeom.Point2D(self.size.getX() - 100., self.size.getY() - 1600.), 3:afwGeom.Point2D(1600., self.size.getX() - 100.)} wcs = self.makeWcs() pos0 = self.wcs.pixelToSky(q1[0]) for rot in (1,2,3): wcs = self.makeWcs() wcs.rotateImageBy90(rot, self.size) self.assertEqual(pos0, self.wcs.pixelToSky(q1[rot])) def testFlip(self): q1 = {'noFlip': afwGeom.Point2D(300., 900.), 'flipLR': afwGeom.Point2D(self.size.getX()-300., 900.), 'flipTB': afwGeom.Point2D(300., self.size.getY()-900.)} wcs = self.makeWcs() pos0 = self.wcs.pixelToSky(q1['noFlip']) wcs = self.makeWcs() wcs.flipImage(True, False, self.size) self.assertEqual(pos0, self.wcs.pixelToSky(q1['flipLR'])) wcs = self.makeWcs() wcs.flipImage(False, True, self.size) self.assertEqual(pos0, self.wcs.pixelToSky(q1['flipTB'])) class WCSTestCaseSDSS(unittest.TestCase): """A test case for WCS using a small (SDSS) image with a slightly weird WCS""" def setUp(self): self.im = afwImage.DecoratedImageD(InputSmallImagePath) self.wcs = afwImage.makeWcs(self.im.getMetadata()) if False: ds9.mtv(im, wcs=self.wcs) def tearDown(self): del self.wcs del self.im def testCrpix(self): metadata = self.im.getMetadata() crpix0 = metadata.getAsDouble("CRPIX1") crpix1 = metadata.getAsDouble("CRPIX2") lsstCrpix = self.wcs.getPixelOrigin() self.assertEqual(lsstCrpix[0], crpix0-1) self.assertEqual(lsstCrpix[1], crpix1-1) def testXyToRaDecArguments(self): """Check that conversion of xy to ra dec (and back again) works""" xy = afwGeom.Point2D(110, 123) raDec = self.wcs.pixelToSky(xy) xy2 = self.wcs.skyToPixel(raDec) self.assertAlmostEqual(xy.getX(), xy2.getX()) self.assertAlmostEqual(xy.getY(), xy2.getY()) raDec = afwCoord.makeCoord(afwCoord.ICRS, 245.167400 * afwGeom.degrees, +19.1976583 * afwGeom.degrees) xy = self.wcs.skyToPixel(raDec) raDec2 = self.wcs.pixelToSky(xy) self.assertAlmostEqual(raDec[0].asDegrees(), raDec2[0].asDegrees()) self.assertAlmostEqual(raDec[1].asDegrees(), raDec2[1].asDegrees()) def test_RaTan_DecTan(self): """Check the RA---TAN, DEC--TAN WCS conversion""" # values from wcstools xy2sky (v3.8.1). Confirmed by ds9 raDec0 = afwGeom.Point2D(245.15984167, +19.1960472) raDec = self.wcs.pixelToSky(0.0, 0.0).getPosition() self.assertAlmostEqual(raDec.getX(), raDec0.getX(), 5) self.assertAlmostEqual(raDec.getY(), raDec0.getY(), 5) def testIdentity(self): """Convert from ra, dec to col, row and back again""" raDec = afwCoord.makeCoord(afwCoord.ICRS, 244 * afwGeom.degrees, 20 * afwGeom.degrees) if verbose: print 'testIdentity' print 'wcs:' for x in self.wcs.getFitsMetadata().toList(): print ' ', x print 'raDec:', raDec print type(self.wcs) rowCol = self.wcs.skyToPixel(raDec) raDec2 = self.wcs.pixelToSky(rowCol) if verbose: print 'rowCol:', rowCol print 'raDec2:', raDec2 p1 = raDec.getPosition() p2 = raDec.getPosition() if verbose: print 'p1,p2', p1,p2 self.assertAlmostEqual(p1[0], p2[0]) self.assertAlmostEqual(p1[1], p2[1]) def testInvalidRaDec(self): """Test a conversion for an invalid position. Well, "test" isn't quite right as the result is invalid, but make sure that it still is""" raDec = afwCoord.makeCoord(afwCoord.ICRS, 1 * afwGeom.degrees, 2 * afwGeom.degrees)
    244 eb5313bd - self.assertRaises(lsst.pex.exceptions.exceptionsLib.LsstCppException, self.wcs.skyToPixel, raDec)
    ? ---------------------
    243 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.Exception, self.wcs.skyToPixel, raDec)
    def testCD(self): self.wcs.getCDMatrix() def testCreateCDMatrix(self): """Test that we make a correct CD matrix even if the header only has a PC matrix""" md = dafBase.PropertySet() md.set("NAXIS", 2) md.set("CTYPE1", "RA---TAN") md.set("CTYPE2", "DEC--TAN") md.set("CRPIX1", 0) md.set("CRPIX2", 0) md.set("CRVAL1", 0) md.set("CRVAL2", 0) md.set("RADECSYS", "FK5") md.set("EQUINOX", 2000.0) wcs = afwImage.makeWcs(md) self.assertTrue(numpy.all(wcs.getCDMatrix() == numpy.array([[1.0, 0.0], [0.0, 1.0]]))) md.set("PC1_1", 2) wcs = afwImage.makeWcs(md) self.assertTrue(numpy.all(wcs.getCDMatrix() == numpy.array([[2.0, 0.0], [0.0, 1.0]]))) def testStripKeywords(self): """Test that we can strip WCS keywords from metadata when constructing a Wcs""" metadata = self.im.getMetadata() self.wcs = afwImage.makeWcs(metadata) self.assertTrue(metadata.exists("CRPIX1")) strip = True self.wcs = afwImage.makeWcs(metadata, strip) self.assertFalse(metadata.exists("CRPIX1")) def testAffineTransform(self): a = self.wcs.getLinearTransform() l = self.wcs.getCDMatrix() #print print a[a.XX], a[a.XY], a[a.YX], a[a.YY] #print a, l def testXY0(self): """Test that XY0 values are handled correctly when building an exposure and also when reading the WCS header directly. #2205""" bbox = afwGeom.Box2I(afwGeom.Point2I(1000, 1000), afwGeom.Extent2I(10, 10)) def makeWcs(crPixPos, crValDeg, projection): ps = dafBase.PropertySet() ctypes = [("%-5s%3s" % (("RA", "DEC")[i], projection)).replace(" ", "-") for i in range(2)] for i in range(2): ip1 = i + 1 ps.add("CTYPE%1d" % (ip1,), ctypes[i]) ps.add("CRPIX%1d" % (ip1,), crPixPos[i]) ps.add("CRVAL%1d" % (ip1,), crValDeg[i]) ps.add("RADECSYS", "ICRS") ps.add("EQUINOX", 2000) ps.add("CD1_1", -0.001) ps.add("CD2_1", 0.0) ps.add("CD1_2", 0.0) ps.add("CD2_2", 0.001) return afwImage.makeWcs(ps) wcs = makeWcs( crPixPos = (100.0, 100.0), crValDeg = (10.0, 35.0), projection = "STG", # also fails for TAN ) exposure = afwImage.ExposureF(bbox, wcs) pixPos = afwGeom.Box2D(bbox).getMax() if verbose: print "XY0=", exposure.getXY0() print "pixPos=", pixPos skyPos = wcs.pixelToSky(pixPos)
    319 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    320 b31e0950 - tmpFile = "temp.fits"
    321 b31e0950 - try:
    exposure.writeFits(tmpFile) for useExposure in (False, True): if useExposure: unpExp = afwImage.ExposureF(tmpFile) unpWcs = unpExp.getWcs() else:
    328 b31e0950 - md = afwImage.readMetadata("temp.fits")
    ? - - ^^ ^^^
    326 c605dfcd + md = afwImage.readMetadata(tmpFile)
    ? ^ ^^ unpWcs = afwImage.makeWcs(md, False) unpPixPos = unpWcs.skyToPixel(skyPos) if verbose: print "useExposure=%s; unp pixPos=%s" % (useExposure, unpPixPos) for i in range(2): self.assertAlmostEqual(unpPixPos[i], 1009.5)
    337 b31e0950 - finally:
    338 b31e0950 - os.remove(tmpFile)
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class WCSTestCaseCFHT(unittest.TestCase): """A test case for WCS""" def setUp(self): path = InputImagePath + "_img.fits" self.metadata = afwImage.readMetadata(path) self.wcs = afwImage.makeWcs(self.metadata)
    349 9d527572 - if False:
    350 9d527572 - ds9.mtv(e)
    def tearDown(self): del self.wcs del self.metadata def test_RaTan_DecTan(self): """Check the RA---TAN, DEC--TAN WCS conversion""" raDec = self.wcs.pixelToSky(0.0, 0.0).getPosition() # position read off ds9 self.assertAlmostEqual(raDec[0], 17.87673, 5) # ra from ds9 self.assertAlmostEqual(raDec[1], 7.72231, 5) # dec from ds9 def testPlateScale(self): """Test that we can measure the area of a pixel""" p00 = afwGeom.Point2D(10, 10) p00 = afwGeom.Point2D(self.metadata.getAsDouble("CRPIX1"), self.metadata.getAsDouble("CRPIX2")) sky00 = self.wcs.pixelToSky(p00) cosdec = math.cos(sky00[1]) side = 1e-3 icrs = afwCoord.ICRS degrees = afwCoord.DEGREES sky10 = afwCoord.makeCoord(icrs, sky00 + afwGeom.Extent2D(side/cosdec, 0), degrees) sky01 = afwCoord.makeCoord(icrs, sky00 + afwGeom.Extent2D(0,side), degrees) p10 = self.wcs.skyToPixel(sky10) - p00 p01 = self.wcs.skyToPixel(sky01) - p00 area = side*side/abs(p10.getX()*p01.getY() - p01.getX()*p10.getY()) self.assertAlmostEqual(math.sqrt(self.wcs.pixArea(p00)), math.sqrt(area)) # # Now check that the area's the same as the CD matrix gives. # cd = [self.metadata.get("CD1_1"), self.metadata.get("CD1_2"), self.metadata.get("CD2_1"), self.metadata.get("CD2_2")] area = math.fabs(cd[0]*cd[3] - cd[1]*cd[2]) self.assertAlmostEqual(math.sqrt(self.wcs.pixArea(p00)), math.sqrt(area)) def testReadWcs(self): """Test reading a Wcs directly from a fits file""" meta = afwImage.readMetadata(InputImagePath + "_img.fits") wcs = afwImage.makeWcs(meta) sky0 = wcs.pixelToSky(0.0, 0.0).getPosition() sky1 = self.wcs.pixelToSky(0.0, 0.0).getPosition() self.assertEqual(sky0, sky1) def testShiftWcs(self): """Test shifting the reference pixel""" sky10_10 = self.wcs.pixelToSky(afwGeom.Point2D(10, 10)) self.wcs.shiftReferencePixel(-10, -10) sky00 = self.wcs.pixelToSky(afwGeom.Point2D(0, 0)) self.assertEqual((sky00[0], sky00[1]), (sky10_10[0], sky10_10[1])) def testCloneWcs(self): """Test Cloning a Wcs""" sky00 = self.wcs.pixelToSky(afwGeom.Point2D(0, 0)).getPosition() new = self.wcs.clone() self.wcs.pixelToSky(afwGeom.Point2D(10, 10)) # shouldn't affect new nsky00 = new.pixelToSky(afwGeom.Point2D(0, 0)).getPosition() self.assertEqual((sky00[0], sky00[1]), (nsky00[0], nsky00[1])) def testCD(self): cd = self.wcs.getCDMatrix() self.assertAlmostEqual(cd[0,0], self.metadata.getAsDouble("CD1_1")) self.assertAlmostEqual(cd[0,1], self.metadata.getAsDouble("CD1_2")) self.assertAlmostEqual(cd[1,0], self.metadata.getAsDouble("CD2_1")) self.assertAlmostEqual(cd[1,1], self.metadata.getAsDouble("CD2_2")) def testConstructor(self): copy = afwImage.Wcs(self.wcs.getSkyOrigin(), self.wcs.getPixelOrigin(), self.wcs.getCDMatrix()) def testAffineTransform(self): a = self.wcs.getLinearTransform() l = self.wcs.getCDMatrix() #print print a[a.XX], a[a.XY], a[a.YX], a[a.YY] sky00g = afwGeom.Point2D(10, 10) sky00i = afwGeom.Point2D(sky00g.getX(), sky00g.getY()) sky00c = afwCoord.makeCoord(afwCoord.ICRS, sky00i, afwCoord.DEGREES) a = self.wcs.linearizeSkyToPixel(sky00c) pix00i = self.wcs.skyToPixel(sky00c) pix00g = afwGeom.Point2D(pix00i.getX(), pix00i.getY()) sky00gApprox = a(pix00g); self.assertAlmostEqual(sky00g.getX(), sky00gApprox.getX()) self.assertAlmostEqual(sky00g.getY(), sky00gApprox.getY()) self.assertAlmostEqual(self.wcs.pixArea(sky00i), abs(a[a.XX]* a[a.YY] - a[a.XY]*a[a.YX])) a.invert() class TestWcsCompare(unittest.TestCase): def setUp(self): crval = afwGeom.Point2D(1.23, 5.67) crpix = afwGeom.Point2D(102., 201.) cd = numpy.array([[5.399452e-5, -1.30770e-5], [1.30770e-5, 5.399452e-5]], dtype=float) self.plainWcs = afwImage.Wcs(crval, crpix, cd) self.sipWcs = afwImage.TanWcs(crval, crpix, cd) self.distortedWcs = afwImage.TanWcs(crval, crpix, cd, cd, cd, cd, cd) def tearDown(self): del self.plainWcs del self.sipWcs del self.distortedWcs def testEqualityCompare(self): self.assertNotEqual(self.plainWcs, self.sipWcs) self.assertNotEqual(self.sipWcs, self.plainWcs) self.assertNotEqual(self.distortedWcs, self.sipWcs) self.assertNotEqual(self.sipWcs, self.distortedWcs) plainWcsCopy = self.plainWcs.clone() sipWcsCopy = self.sipWcs.clone() distortedWcsCopy = self.distortedWcs.clone() self.assertEqual(plainWcsCopy, self.plainWcs) self.assertEqual(sipWcsCopy, self.sipWcs) self.assertEqual(distortedWcsCopy, self.distortedWcs) self.assertEqual(self.plainWcs, plainWcsCopy) self.assertEqual(self.sipWcs, sipWcsCopy) self.assertEqual(self.distortedWcs, distortedWcsCopy) self.assertNotEqual(plainWcsCopy, sipWcsCopy) self.assertNotEqual(sipWcsCopy, plainWcsCopy) self.assertNotEqual(distortedWcsCopy, sipWcsCopy) self.assertNotEqual(sipWcsCopy, distortedWcsCopy) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(WcsTestCase) suites += unittest.makeSuite(WCSTestCaseSDSS) suites += unittest.makeSuite(TestWcsCompare) # suites += unittest.makeSuite(WCSTestCaseCFHT) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    16c71f25

    commit 16c71f25fe753a51fcb316c7d39b71af2955ec8b
    Author: rhl 
    Date:   Thu Dec 6 20:37:25 2007 +0000
    
        Use eups.productDir and provide a run() proc for interactive use
    

    eb5313bd

    commit eb5313bdf545c359af45c4a5bd18e0a7f3304cbc
    Author: fergal 
    Date:   Wed Feb 24 22:45:50 2010 +0000
    
        Updated calls to Wcs to new API
    

    92a588b5

    commit 92a588b51420a1363cc3987a249867ab7fce8f52
    Author: fergal 
    Date:   Fri Mar 6 21:25:05 2009 +0000
    
        Some of the sdss stuff was not testing for the right problems.
        
        Now test for exceptions being raised when invalid coordinates are
        submitted to raDecToXY() etc.
    

    61855404

    commit 618554041c03d30fe370e2c3e69c0fb394c93ccb
    Author: nms 
    Date:   Tue Oct 9 00:00:09 2007 +0000
    
        Merged Exposure class code (.cc/.h and exposure.i) to trunk (from Ticket 167).
        Merged modifications made in Ticket 167 to MaskedImage, Kernel, and WCS class code.
        Added and merged final modifications to Exposure, WCS and Kernel class test code
          (associated examples/*.cc & tests/*.py files)
        Deleted all test images from tests/data.
        Added small_MI_corrupt_img.fits to tests/data for temporary storage of a test file used
        in both the WCS and Exposure test suites.
    

    ad4a9b08

    commit ad4a9b08c6591e9890063580eccae794e67b4341
    Author: jbosch 
    Date:   Wed Jan 13 01:54:23 2010 +0000
    
        afw/#0
         - changes for #1130 (implemented directly in trunk)
         - adding temporary fix for #1131 (not yet done, but trunk builds better than it did before, and I have to go home now and work from there)
    

    456d42a8

    commit 456d42a80026bc8b0961131936d467cf68af2f68
    Author: rowen 
    Date:   Fri Mar 28 17:10:01 2008 +0000
    
        afw reorg:
        - Updated use of fwData -> afwdata
        - Fixed forward declarations of Formatter in image classes
    

    9d527572

    commit 9d52757265b2b7bf04c54274e1b9bbb61cb94181
    Author: rhl 
    Date:   Fri Feb 6 21:52:17 2009 +0000
    
        Fix #622 (I think)
    

    b31e0950

    commit b31e0950b2901d6a5fdfae08d27e6868803b4c9b
    Author: Robert Lupton the Good 
    Date:   Wed Jun 27 16:16:03 2012 -0400
    
        Added test case for #2205 from ticket
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    tests/statClipException1045.py

    Diff:

    1 22b8a447 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? + # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # # -*- lsst-python -*- """ Tests for ticket 1043 - Photometry fails when no PSF is provided """ import lsst.afw.math as afwMath import numpy as num import math import unittest import lsst.utils.tests as utilsTests import lsst.pex.exceptions as pexExcept # math.isnan() available in 2.6, but not 2.5.2 try: math.isnan(1) except AttributeError: math.isnan = lambda x: x != x class Ticket1045TestCase(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def testTicket1045(self): values = [1.08192, 1.08792, 1.08774, 1.09953, 1.1122, 1.09408, 0.879792, 1.12235, 1.10115, 1.08999] knownMean, knownStdev = num.mean(values), 0.069903889977279199 # this was reported to work dmean1 = afwMath.makeStatistics(values, afwMath.NPOINT | afwMath.MEAN | afwMath.STDEV) mean1 = dmean1.getValue(afwMath.MEAN) stdev1 = dmean1.getValue(afwMath.STDEV) self.assertAlmostEqual(mean1, knownMean, 8) self.assertAlmostEqual(stdev1, knownStdev, places=16) # this was reported to fail # (problem was due to error in median) knownMeanClip = 1.097431111111111 knownStdevClip = 0.012984991763998597 dmean2 = afwMath.makeStatistics(values, afwMath.NPOINT | afwMath.MEANCLIP | afwMath.STDEVCLIP) mean2 = dmean2.getValue(afwMath.MEANCLIP) stdev2 = dmean2.getValue(afwMath.STDEVCLIP) self.assertEqual(mean2, knownMeanClip) self.assertEqual(stdev2, knownStdevClip) # check the median, just for giggles knownMedian = num.median(values) stat = afwMath.makeStatistics(values, afwMath.MEDIAN) median = stat.getValue(afwMath.MEDIAN) self.assertEqual(median, knownMedian) # check the median with an odd number of values vals = values[1:] knownMedian = num.median(vals) stat = afwMath.makeStatistics(vals, afwMath.MEDIAN) median = stat.getValue(afwMath.MEDIAN) self.assertEqual(median, knownMedian) # check the median with only two values vals = values[0:2] knownMedian = num.median(vals) stat = afwMath.makeStatistics(vals, afwMath.MEDIAN) median = stat.getValue(afwMath.MEDIAN) self.assertEqual(median, knownMedian) # check the median with only 1 value vals = values[0:1] knownMedian = num.median(vals) stat = afwMath.makeStatistics(vals, afwMath.MEDIAN) median = stat.getValue(afwMath.MEDIAN) self.assertEqual(median, knownMedian) # check the median with no values vals = [] def tst(): stat = afwMath.makeStatistics(vals, afwMath.MEDIAN) median = stat.getValue(afwMath.MEDIAN) return median
    107 cf970e75 - utilsTests.assertRaisesLsstCpp(self, pexExcept.InvalidParameterException, tst)
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    107 6fc1c3d1 + self.assertRaises(pexExcept.InvalidParameterError, tst)
    ? ^^ ^ ^^ ^ def testUnexpectedNan1051(self): values = [7824.0, 7803.0, 7871.0, 7567.0, 7813.0, 7809.0, 8011.0, 7807.0] npValues = num.array(values) meanClip = afwMath.makeStatistics(values, afwMath.MEANCLIP).getValue() iKept = num.array([0, 1, 2, 4, 5, 7]) # note ... it will clip indices 3 and 6 knownMeanClip = num.mean(npValues[iKept]) self.assertEqual(meanClip, knownMeanClip) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(Ticket1045TestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    22b8a447

    commit 22b8a4477055cb71dbc986c122d4e1ceb1335842
    Author: bick 
    Date:   Tue Dec 1 20:55:02 2009 +0000
    
        #1045 Fixed problem with clipped stats, actually in percentile
    

    cf970e75

    commit cf970e750a7374e79c2d065c7fd9cc7e52402a59
    Author: bick 
    Date:   Tue Dec 1 21:40:48 2009 +0000
    
        merging additional fix and tests for #1045
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    src/gpu/detail/CudaSelectGpu.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008 - 2012 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * @file
                     *
                     * @brief Functions for simplifying selecting GPU device, implementation file
                     *
                     * @author Kresimir Cosic
                     *
                     * @ingroup afw
                     */
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/gpu/GpuExceptions.h"
                    #include "lsst/afw/gpu/detail/CudaSelectGpu.h"
                    #include "lsst/afw/gpu/detail/CudaQueryDevice.h"
                    
                    using namespace lsst::afw::gpu;
                    
                    #ifndef GPU_BUILD //if no GPU support, throw exceptions
                    
                    namespace lsst {
                    namespace afw {
                    namespace gpu {
                    namespace detail {
                    
                    
                    void SetCudaDevice(int devId) {
    
    51 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    51 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } void CudaReserveDevice() {
    55 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    55 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } void CudaThreadExit() {
    59 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    59 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } bool SelectPreferredCudaDevice() {
    64 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with gpu support");
    ? ---------
    64 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with gpu support");
    } void AutoSelectCudaDevice() {
    68 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with gpu support");
    ? ---------
    68 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with gpu support");
    } void VerifyCudaDevice() {
    72 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with gpu support");
    ? ---------
    72 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with gpu support");
    } bool TryToSelectCudaDevice(bool noExceptions, bool reselect) {
    76 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with gpu support");
    ? ---------
    76 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with gpu support");
    } int GetPrefferedCudaDevice() {
    80 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with gpu support");
    ? ---------
    80 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with gpu support");
    } } } } } #else #include #include #include #include namespace lsst { namespace afw { namespace gpu { namespace detail { //from CudaQueryDevice.cc void PrintCudaErrorInfo(cudaError_t cudaError, const char* errorStr); int GetPreferredCudaDevice() { const char *devStr = getenv("CUDA_DEVICE"); if (devStr == NULL) return -2; else return atoi(devStr); } bool SelectPreferredCudaDevice() { int devId = GetPreferredCudaDevice(); //printf("DEVICE ID %d\n", devId); if (devId >= 0) { cudaError_t err = cudaSetDevice(devId); if (err != cudaSuccess) { cudaGetLastError(); //clear error code char errorStr[1000]; sprintf(errorStr, "Error selecting device %d:\n %s\n", devId, cudaGetErrorString(err));
    124 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, errorStr);
    ? ---------
    124 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, errorStr);
    } return true; } if (devId != -2) return true; return false; } cudaDeviceProp GetDesiredDeviceProperties() { cudaDeviceProp prop; memset(&prop, 1, sizeof(prop)); //min sm 1.3 prop.major = 1; prop.minor = 3; prop.maxGridSize[0] = 128; prop.maxThreadsDim[0] = 256; prop.multiProcessorCount = 2; prop.clockRate = 700.0 * 1000 ; // 700 MHz prop.warpSize = 32 ; prop.sharedMemPerBlock = 32 * (1 << 10); //32 KiB prop.regsPerBlock = 256 * 60 ; prop.maxThreadsPerBlock = 256; prop.totalGlobalMem = 500 * 1024 * 1024; return prop; } void AutoSelectCudaDevice() { int cudaDevicesN = 0; cudaGetDeviceCount(&cudaDevicesN); if (cudaDevicesN == 0) {
    162 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "No CUDA capable GPUs found");
    ? ---------
    162 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "No CUDA capable GPUs found");
    } cudaDeviceProp prop = GetDesiredDeviceProperties(); char errorStr[1000]; int devId; cudaError_t cudaError = cudaChooseDevice(&devId, &prop); //printf("Error device %d:\n %s\n", devId, cudaGetErrorString(err)); if (cudaError != cudaSuccess) {
    172 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "Error choosing device automatically");
    ? ---------
    172 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "Error choosing device automatically");
    } cudaError = cudaSetDevice(devId); if (cudaError == cudaErrorSetOnActiveProcess) { cudaGetLastError(); //clear error cudaGetDevice(&devId); } else if (cudaError != cudaSuccess) { cudaGetLastError(); //clear error sprintf(errorStr, "Error automatically selecting device %d:\n %s\n", devId, cudaGetErrorString(cudaError));
    182 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, errorStr);
    ? ---------
    182 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, errorStr);
    } } void VerifyCudaDevice() { cudaDeviceProp prop = GetDesiredDeviceProperties(); char errorStr[1000]; int devId; cudaError_t cudaError = cudaGetDevice(&devId); if (cudaError != cudaSuccess) {
    194 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "Could not get selected CUDA device ID");
    ? ---------
    194 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "Could not get selected CUDA device ID");
    } cudaDeviceProp deviceProp; cudaError = cudaGetDeviceProperties(&deviceProp, devId); if (cudaError != cudaSuccess) {
    199 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "Could not get CUDA device properties");
    ? ---------
    199 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "Could not get CUDA device properties");
    } if (deviceProp.major < prop.major || (deviceProp.major == prop.major && deviceProp.minor < prop.minor) ) { sprintf(errorStr, "Only SM %d.%d or better GPU devices are currently allowed", prop.major, prop.minor);
    205 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, errorStr );
    ? ---------
    205 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, errorStr );
    } if (deviceProp.major == prop.major && deviceProp.minor < prop.minor) { if (deviceProp.totalGlobalMem < prop.totalGlobalMem) {
    210 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "Not enough global memory on GPU");
    ? ---------
    210 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "Not enough global memory on GPU");
    } } if (deviceProp.sharedMemPerBlock < 16 * 1000) {
    214 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "Not enough shared memory on GPU");
    ? ---------
    214 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "Not enough shared memory on GPU");
    } if (deviceProp.regsPerBlock < prop.regsPerBlock) {
    217 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "Not enough registers per block available on GPU");
    ? ---------
    217 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "Not enough registers per block available on GPU");
    } if (deviceProp.maxThreadsPerBlock < prop.maxThreadsPerBlock) {
    220 af8f5ebe - throw LSST_EXCEPT(GpuRuntimeErrorException, "Not enough threads per block available on GPU");
    ? ---------
    220 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "Not enough threads per block available on GPU");
    } } bool TryToSelectCudaDevice(bool noExceptions, bool reselect) { #if !defined(GPU_BUILD) return false; #else static bool isDeviceSelected = false; static bool isDeviceOk = false; if (reselect){ isDeviceSelected = false; isDeviceOk = false; } if (isDeviceSelected) return isDeviceOk; isDeviceSelected = true; if (!noExceptions) { bool done = SelectPreferredCudaDevice(); if (done) { isDeviceOk = true; return true; } } else { try { bool done = SelectPreferredCudaDevice(); if (done) { isDeviceOk = true; return true; } } catch(...) { return false; } } if (!noExceptions) { AutoSelectCudaDevice(); VerifyCudaDevice(); isDeviceOk = true; return true; } try { AutoSelectCudaDevice(); VerifyCudaDevice(); } catch(...) { return false; } isDeviceOk = true; return true; #endif } void SetCudaDevice(int devId) { cudaError_t cudaError = cudaSetDevice(devId); if (cudaError != cudaSuccess) PrintCudaErrorInfo(cudaError, "SetCudaDevice> unsucessfull"); } void CudaReserveDevice() { int* dataGpu; cudaError_t cudaError = cudaMalloc((void**)&dataGpu, 256 * sizeof(int)); if (cudaError != cudaSuccess) { PrintCudaErrorInfo(cudaError, "CudaReserveDevice> Could not reserve device by calling cudaMalloc"); } cudaError = cudaFree(dataGpu); if (cudaError != cudaSuccess) { PrintCudaErrorInfo(cudaError, "CudaReserveDevice> Could not release memory by calling cudaFree"); } } void CudaThreadExit() { cudaThreadExit(); } } } } } // namespace lsst::afw::gpu::detail ends #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    af8f5ebe

    commit af8f5ebef4f524d96fa4c824d3c8eb1cf11a6869
    Author: Kresimir Cosic 
    Date:   Mon Feb 27 03:39:36 2012 +0100
    
        Added afw::gpu namespace, reorganized files and interfaces to use this namespace
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/coord/coord.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    
                    %{
                    #include "lsst/afw/image.h"    
                    #include "lsst/afw/geom.h"
                    #include "lsst/daf/base.h"    
    
    30 d304da93 - #include "lsst/afw/coord/Utils.h"
    #include "lsst/afw/coord/Coord.h" %}
    33 4d62652f + %useValueEquality(lsst::afw::coord::Coord);
    // The shared pointer declarations must precede the #inlude statement for Coord.h %shared_ptr(lsst::afw::coord::Coord); %shared_ptr(lsst::afw::coord::Fk5Coord); %shared_ptr(lsst::afw::coord::IcrsCoord); %shared_ptr(lsst::afw::coord::GalacticCoord); %shared_ptr(lsst::afw::coord::EclipticCoord); %shared_ptr(lsst::afw::coord::TopocentricCoord); %rename(__getitem__) lsst::afw::coord::Coord::operator[]; // ----------------------------------------------------------------------- // THESE CASTS ARE NOW DEPRECATED; USE E.G. `Fk5Coord.cast()` INSTEAD %inline %{ lsst::afw::coord::Fk5Coord::Ptr cast_Fk5(lsst::afw::coord::Coord::Ptr c) { return boost::dynamic_pointer_cast(c); } lsst::afw::coord::IcrsCoord::Ptr cast_Icrs(lsst::afw::coord::Coord::Ptr c) { return boost::dynamic_pointer_cast(c); } lsst::afw::coord::GalacticCoord::Ptr cast_Galactic(lsst::afw::coord::Coord::Ptr c) { return boost::dynamic_pointer_cast(c); } lsst::afw::coord::EclipticCoord::Ptr cast_Ecliptic(lsst::afw::coord::Coord::Ptr c) { return boost::dynamic_pointer_cast(c); } %} // ----------------------------------------------------------------------- %castShared(lsst::afw::coord::Fk5Coord, lsst::afw::coord::Coord) %castShared(lsst::afw::coord::IcrsCoord, lsst::afw::coord::Coord) %castShared(lsst::afw::coord::GalacticCoord, lsst::afw::coord::Coord) %castShared(lsst::afw::coord::EclipticCoord, lsst::afw::coord::Coord) %castShared(lsst::afw::coord::TopocentricCoord, lsst::afw::coord::Coord)
    70 d304da93 - %include "lsst/afw/coord/Utils.h"
    %include "lsst/afw/coord/Coord.h" %define strCoord(TYPE) %extend lsst::afw::coord::TYPE {
    74 4d62652f + std::string __str__() const {
    75 4d62652f + std::ostringstream os;
    76 4d62652f + os << (*self);
    77 4d62652f + return os.str();
    75 0af6401d - %pythoncode {
    76 0af6401d - def __repr__(self):
    77 0af6401d - return "afwCoord.TYPE(%g*afwGeom.radians, %g*afwGeom.radians)" % \
    78 0af6401d - (self[0].asRadians(), self[1].asRadians())
    79 0af6401d - def __str__(self):
    80 0af6401d - return "(%s, %s)" % (self[0], self[1])
    81 0af6401d -
    }
    79 81c3bd10 + %pythoncode %{
    80 4d62652f + def __repr__(self):
    81 4d62652f + className = self.getClassName()
    82 4d62652f + argList = ["%r * afwGeom.degrees" % (pos.asDegrees(),) for pos in self]
    83 4d62652f + if className == "TopocentricCoord":
    84 4d62652f + topoCoord = TopocentricCoord.cast(self)
    85 4d62652f + argList += [
    86 4d62652f + repr(self.getEpoch()),
    87 4d62652f + "(%r)" % (topoCoord.getObservatory(),),
    88 4d62652f + ]
    89 4d62652f + elif className not in ("IcrsCoord", "GalacticCoord"):
    90 4d62652f + argList.append(repr(self.getEpoch()))
    91 4d62652f + return "%s(%s)" % (self.getClassName(), ", ".join(argList))
    92 81c3bd10 + %}
    } %enddef strCoord(Coord); strCoord(Fk5Coord); strCoord(IcrsCoord); strCoord(GalacticCoord); strCoord(EclipticCoord);
    101 4d62652f + strCoord(TopocentricCoord);
    // Add __iter__ to allow 'ra,dec = coord' statement in python %define genCoord(TYPE) %extend lsst::afw::coord::TYPE {
    95 6c184547 - %pythoncode {
    106 81c3bd10 + %pythoncode %{
    ? +
    96 6c184547 - def __iter__(self):
    ? ----
    107 4d62652f + def __iter__(self):
    97 6c184547 - for i in 0,1:
    ? ----
    108 a5a62a17 + for i in (0, 1):
    ? + + +
    98 6c184547 - yield self[i]
    ? ----
    109 4d62652f + yield self[i]
    110 a5a62a17 + def __len__(self):
    111 a5a62a17 + return 2
    99 6c184547 - }
    112 81c3bd10 + %}
    ? + } %enddef genCoord(Coord); genCoord(Fk5Coord); genCoord(IcrsCoord); genCoord(GalacticCoord); genCoord(EclipticCoord);
    121 a5a62a17 + genCoord(TopocentricCoord);
    // Add __reduce__ for Coord subclasses that take 3 arguments %define reduceCoord3(TYPE) %extend lsst::afw::coord::TYPE {
    113 039a5000 - %pythoncode {
    127 81c3bd10 + %pythoncode %{
    ? +
    114 039a5000 - def __reduce__(self):
    ? ----
    128 4d62652f + def __reduce__(self):
    115 039a5000 - return (TYPE, (self.getLongitude(), self.getLatitude(), self.getEpoch()))
    ? ----
    129 4d62652f + return (TYPE, (self.getLongitude(), self.getLatitude(), self.getEpoch()))
    116 039a5000 - }
    130 81c3bd10 + %}
    ? + } %enddef // Add __reduce__ for Coord subclasses that take 2 arguments %define reduceCoord2(TYPE) %extend lsst::afw::coord::TYPE {
    123 039a5000 - %pythoncode {
    137 81c3bd10 + %pythoncode %{
    ? +
    124 039a5000 - def __reduce__(self):
    ? ----
    138 4d62652f + def __reduce__(self):
    125 039a5000 - return (TYPE, (self.getLongitude(), self.getLatitude()))
    ? ----
    139 4d62652f + return (TYPE, (self.getLongitude(), self.getLatitude()))
    126 039a5000 - }
    140 81c3bd10 + %}
    ? + } %enddef reduceCoord3(Coord); reduceCoord3(Fk5Coord); reduceCoord2(IcrsCoord); reduceCoord2(GalacticCoord); reduceCoord3(EclipticCoord);

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d304da93

    commit d304da93ccf6b9879ea8a52bd737816b61d5eca6
    Author: bick 
    Date:   Thu Mar 11 23:55:19 2010 +0000
    
        Added point3d.
    

    6c184547

    commit 6c1845474f28f528a95190eeb88f095b11999078
    Author: Steven Bickerton 
    Date:   Mon Feb 17 18:18:11 2014 +0900
    
        Check in #3092 (iterable coord) directly on master (due to accidental branch #3092 from #3093)
    

    039a5000

    commit 039a500000525c04c4c9902e55c82cccfca496ce
    Author: Paul Price 
    Date:   Tue Dec 4 12:48:36 2012 -0500
    
        Fix IcrsCoord pickling: doesn't unpickle currently because it doesn't have an epoch in the constructor.
    

    0af6401d

    commit 0af6401d8c1d83d477aab5c0bcab26e78abd6c1a
    Author: Robert Lupton the Good 
    Date:   Thu Jan 19 19:45:39 2012 -0500
    
        Add Coord.__{str,repr}__
    

    Commits in /Users/nate/repos_lsst/afw/

    a5a62a17

    commit a5a62a17d64209eed8759beeb9224c13af441af3
    Author: Russell Owen 
    Date:   Thu Apr 23 06:13:06 2015 -0700
    
        Improve Coord iteration in Python
        
        Add Coord.__len__ to Coord and subclasses
        Implement iteration for TopocentricCoord
    

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    4d62652f

    commit 4d62652fa86a1c53d99c71ca845d3ea3af63565f
    Author: Russell Owen 
    Date:   Wed Apr 22 16:57:18 2015 -0700
    
        Improved string representations of Coords
        
        Improved os << Coord (in C++) and Coord.__str__ and __repr__ in Python
        for Coord and all subclasses, as follows:
        - The coordinate system is shown, even for clones (without the need to cast)
        - Positions are in degrees, instead of radians
        - IcrsCoord and GalacticCoord do not show the epoch
        - TopocentricCoord now has string representations, and the data includes Observatory
        - Coord.__str__ now uses C++ os << Coord, for simplicity and uniformity
        - Coord.__repr__ shows numbers (except observatory to full precision
          (except for observatory data for TopocentricCoord, since it didn't seem worth the extra clutter).
        - Coord.__repr__ omits the leading "afwCoord."
        
        Note: I would prefer to make Coord.__repr__ the same as __str__
        but it was more detailed so I left that feature.
        
        Make Coord.__str__ use << and add observatory information for topo
    

    Return to list

    src/math/detail/BasicConvolveGPU.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * @file
                     *
                     * @brief Definition of basicConvolveGPU, convolveLinearCombinationGPU
                     * and convolveSpatiallyInvariantGPU functions declared in ConvolveGPU.h
                     *
                     * @author Kresimir Cosic
                     * @author Original CPU convolution code by Russell Owen
                     *
                     * @ingroup afw
                     */
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/cstdint.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/ConvolveImage.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/math/FunctionLibrary.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/math/detail/ConvCpuGpuShared.h"
                    #include "lsst/afw/math/detail/Convolve.h"
                    
                    #include "lsst/afw/math/detail/ConvolveGPU.h"
                    #include "lsst/afw/math/detail/convCUDA.h"
                    #include "lsst/afw/gpu/detail/GpuBuffer2D.h"
                    #include "lsst/afw/math/detail/cudaConvWrapper.h"
                    #include "lsst/afw/gpu/detail/CudaSelectGpu.h"
                    #include "lsst/afw/gpu/IsGpuBuild.h"
                    #include "lsst/afw/gpu/GpuExceptions.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace pexLog = lsst::pex::logging;
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwImage = lsst::afw::image;
                    namespace afwMath = lsst::afw::math;
                    namespace afwGpu = lsst::afw::gpu;
                    namespace mathDetail = lsst::afw::math::detail;
                    namespace gpuDetail = lsst::afw::gpu::detail;
                    
                    namespace {
                    
                    typedef mathDetail::VarPixel VarPixel;
                    typedef mathDetail::MskPixel MskPixel;
                    typedef mathDetail::KerPixel KerPixel;
                    
                    // copies data from MaskedImage to three image buffers
                    template 
                    void CopyFromMaskedImage(afwImage::MaskedImage const& image,
                                             gpuDetail::GpuBuffer2D& img,
                                             gpuDetail::GpuBuffer2D& var,
                                             gpuDetail::GpuBuffer2D& msk
                                            )
                    {
                        int width = image.getWidth();
                        int height = image.getHeight();
                        img.Init(width, height);
                        var.Init(width, height);
                        msk.Init(width, height);
                    
                        typedef typename afwImage::MaskedImage
                        ::x_iterator x_iterator;
                    
                        //copy input image data to buffer
                        for (int i = 0; i < height; ++i) {
                            x_iterator inPtr = image.x_at(0, i);
                            PixelT*    imageDataPtr = img.GetImgLinePtr(i);
                            MskPixel*  imageMaskPtr = msk.GetImgLinePtr(i);
                            VarPixel*  imageVarPtr  = var.GetImgLinePtr(i);
                    
                            for (x_iterator cnvEnd = inPtr + width; inPtr != cnvEnd;
                                    ++inPtr, ++imageDataPtr, ++imageMaskPtr, ++imageVarPtr ) {
                                *imageDataPtr = (*inPtr).image();
                                *imageMaskPtr = (*inPtr).mask();
                                *imageVarPtr  = (*inPtr).variance();
                            }
                        }
                    }
                    
                    // copies data from three image buffers to MaskedImage
                    template 
                    void CopyToImage(afwImage::MaskedImage& outImage,
                                     int startX, int startY,
                                     const gpuDetail::GpuBuffer2D& img,
                                     const gpuDetail::GpuBuffer2D& var,
                                     const gpuDetail::GpuBuffer2D& msk
                                    )
                    {
                        assert(img.height == var.height);
                        assert(img.height == msk.height);
                        assert(img.width == var.width);
                        assert(img.width == msk.width);
                    
                        typedef typename afwImage::MaskedImage
                        ::x_iterator x_iterator;
                    
                        for (int i = 0; i < img.height; ++i) {
                            const PixelT*    outPtrImg = img.GetImgLinePtr(i);
                            const MskPixel*  outPtrMsk = msk.GetImgLinePtr(i);
                            const VarPixel*  outPtrVar = var.GetImgLinePtr(i);
                    
                            for (x_iterator cnvPtr = outImage.x_at(startX, i + startY),
                                    cnvEnd = cnvPtr + img.width;    cnvPtr != cnvEnd;    ++cnvPtr )
                            {
                                *cnvPtr = typename x_iterator::type(*outPtrImg, *outPtrMsk, *outPtrVar);
                                ++outPtrImg;
                                ++outPtrMsk;
                                ++outPtrVar;
                            }
                        }
                    }
                    
                    }   // anonymous namespace
                    
                    /**
                     * @brief Low-level convolution function that does not set edge pixels.
                     *
                     * Will use GPU for convolution in following cases:
                     * - kernel is spatially invariant  (calls convolveSpatiallyInvariantGPU)
                     * - kernel is a linear combination (calls convolveLinearCombinationGPU)
                     * Otherwise, delegates calculation to CPU versions of basicConvolve
                     *
                     * convolvedImage must be the same size as inImage.
                     * convolvedImage has a border in which the output pixels are not set. This border has size:
                     * - kernel.getCtrX() along the left edge
                     * - kernel.getCtrY() along the bottom edge
                     * - kernel.getWidth()  - 1 - kernel.getCtrX() along the right edge
                     * - kernel.getHeight() - 1 - kernel.getCtrY() along the top edge
                     *
    
    160 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dimensions
    ? ^^^^^^ ^
    160 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dimensions
    ? ^^ ^
    161 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or height
    ? ^^^^^^ ^
    161 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or height
    ? ^^ ^
    162 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    162 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    163 af8f5ebe - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    163 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    164 03c5e027 - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    164 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    165 af8f5ebe - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    165 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * @ingroup afw */ template mathDetail::ConvolveGpuStatus::ReturnCode mathDetail::basicConvolveGPU( OutImageT &convolvedImage, ///< convolved %image InImageT const& inImage, ///< %image to convolve afwMath::Kernel const& kernel, ///< convolution kernel afwMath::ConvolutionControl const& convolutionControl) ///< convolution control parameters { if (!afwGpu::isGpuBuild()) {
    177 af8f5ebe - throw LSST_EXCEPT(afwGpu::GpuRuntimeErrorException, "Afw not compiled with GPU support");
    ? ---------
    177 21597d88 + throw LSST_EXCEPT(afwGpu::GpuRuntimeError, "Afw not compiled with GPU support");
    } // Because convolve isn't a method of Kernel we can't always use Kernel's vtbl to dynamically // dispatch the correct version of basicConvolve. The case that fails is convolving with a kernel // obtained from a pointer or reference to a Kernel (base class), e.g. as used in LinearCombinationKernel. if (IS_INSTANCE(kernel, afwMath::DeltaFunctionKernel)) { return mathDetail::ConvolveGpuStatus::UNSUPPORTED_KERNEL; } else if (IS_INSTANCE(kernel, afwMath::SeparableKernel)) { return mathDetail::ConvolveGpuStatus::UNSUPPORTED_KERNEL; } else if (IS_INSTANCE(kernel, afwMath::LinearCombinationKernel) && kernel.isSpatiallyVarying()) { pexLog::TTrace<4>("lsst.afw.math.convolve", "generic basicConvolve (GPU): dispatch to convolveLinearCombinationGPU"); return mathDetail::convolveLinearCombinationGPU(convolvedImage, inImage, *dynamic_cast(&kernel), convolutionControl); } // use brute force pexLog::TTrace<3>("lsst.afw.math.convolve", "generic basicConvolve (GPU): dispatch to convolveSpatiallyInvariantGPU"); return mathDetail::convolveSpatiallyInvariantGPU(convolvedImage, inImage, kernel, convolutionControl); } /** * @brief GPU convolution for MaskedImage used when convolving a LinearCombinationKernel * * Alocates input and output image buffers, extracts data from MaskedImage into image buffers, * prepares all other data required for GPU convolution. * calls GPU_ConvolutionMI_LinearCombinationKernel to perform the convolutiuon. * * Delegates calculation to basicConvolve when: * - kernel is too small (less than 30 pixels * - there is not enough shared memory on device to hold the image blocks * (image blocks are larger than kernels) * - kernels don't match each other * - there are too many kernels ( > maxGpuSfCount=100) *
    215 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dimensions
    ? ^^^^^^ ^
    215 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dimensions
    ? ^^ ^
    216 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or height
    ? ^^^^^^ ^
    216 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or height
    ? ^^ ^
    217 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    217 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    218 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    218 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    219 af8f5ebe - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    219 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    220 03c5e027 - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    220 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    221 af8f5ebe - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    221 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * @ingroup afw */ template mathDetail::ConvolveGpuStatus::ReturnCode mathDetail::convolveLinearCombinationGPU( afwImage::MaskedImage& convolvedImage, ///< convolved %image afwImage::MaskedImage const& inImage, ///< %image to convolve afwMath::LinearCombinationKernel const& kernel, ///< convolution kernel afwMath::ConvolutionControl const & convolutionControl) ///< convolution control parameters { if (!afwGpu::isGpuBuild()) {
    233 af8f5ebe - throw LSST_EXCEPT(afwGpu::GpuRuntimeErrorException, "Afw not compiled with GPU support");
    ? ---------
    233 21597d88 + throw LSST_EXCEPT(afwGpu::GpuRuntimeError, "Afw not compiled with GPU support");
    } typedef typename afwMath::Kernel::Pixel KernelPixel; typedef afwImage::Image KernelImage; typedef gpuDetail::GpuBuffer2D KernelBuffer; if (!kernel.isSpatiallyVarying()) { // use the standard algorithm for the spatially invariant case pexLog::TTrace<3>("lsst.afw.math.convolve", "convolveLinearCombinationGPU: spatially invariant; will delegate"); return mathDetail::convolveSpatiallyInvariantGPU(convolvedImage, inImage, kernel, convolutionControl.getDoNormalize()); } else { bool throwExceptionsOn=convolutionControl.getDevicePreference() == afwGpu::USE_GPU; if (afwGpu::detail::TryToSelectCudaDevice(!throwExceptionsOn) == false){ return mathDetail::ConvolveGpuStatus::NO_GPU; } // refactor the kernel if this is reasonable and possible; // then use the standard algorithm for the spatially varying case afwMath::Kernel::Ptr refKernelPtr; // possibly refactored version of kernel if (static_cast(kernel.getNKernelParameters()) > kernel.getNSpatialParameters()) { // refactoring will speed convolution, so try it refKernelPtr = kernel.refactor(); if (!refKernelPtr) { refKernelPtr = kernel.clone(); } } else { // too few basis kernels for refactoring to be worthwhile refKernelPtr = kernel.clone(); } assertDimensionsOK(convolvedImage, inImage, kernel); const afwMath::LinearCombinationKernel* newKernel = dynamic_cast (refKernelPtr.get()); assert(newKernel!=NULL); const int kernelN = newKernel->getNBasisKernels(); const std::vector< afwMath::Kernel::SpatialFunctionPtr > sFn = newKernel->getSpatialFunctionList(); if (sFn.size() < 1) { return mathDetail::ConvolveGpuStatus::SFN_COUNT_ERROR; } if (int(sFn.size()) != kernelN) { return mathDetail::ConvolveGpuStatus::SFN_COUNT_ERROR; } bool isAllCheby = true; for (int i = 0; i < kernelN; i++) { if (! IS_INSTANCE( *sFn[i], afwMath::Chebyshev1Function2 ) ) { isAllCheby = false; } } bool isAllPoly = true; for (int i = 0; i < kernelN; i++) { if (! IS_INSTANCE( *sFn[i], afwMath::PolynomialFunction2 ) ) { isAllPoly = false; } } int order = 0; #ifdef GPU_BUILD SpatialFunctionType_t sfType; #endif if (isAllPoly) { order = dynamic_cast*>( sFn[0].get() ) ->getOrder(); #ifdef GPU_BUILD sfType = sftPolynomial; #endif } else if(isAllCheby) { order = dynamic_cast*>( sFn[0].get() ) ->getOrder(); #ifdef GPU_BUILD sfType = sftChebyshev; #endif } else return mathDetail::ConvolveGpuStatus::SFN_TYPE_ERROR; //get copies of basis kernels const afwMath::KernelList kernelList = newKernel->getKernelList(); //if kernel is too small, call CPU convolution const int minKernelSize = 25; if (newKernel->getWidth() * newKernel->getHeight() < minKernelSize && convolutionControl.getDevicePreference() != lsst::afw::gpu::USE_GPU) { return mathDetail::ConvolveGpuStatus::KERNEL_TOO_SMALL; } //if something is wrong, call CPU convolution const bool shMemOkA = IsSufficientSharedMemoryAvailable_ForImgAndMaskBlock( newKernel->getWidth(), newKernel->getHeight(), sizeof(double)); const bool shMemOkB = IsSufficientSharedMemoryAvailable_ForSfn(order, kernelN); if (!shMemOkA || !shMemOkB) { //cannot fit kernels into shared memory, revert to convolution by CPU return mathDetail::ConvolveGpuStatus::KERNEL_TOO_BIG; } if (kernelN == 0 || kernelN > detail::gpu::maxGpuSfCount) { return mathDetail::ConvolveGpuStatus::KERNEL_COUNT_ERROR; } for (int i = 0; i < kernelN; i++) { if (kernelList[i]->getDimensions() != newKernel->getDimensions() || kernelList[i]->getCtr() != newKernel->getCtr() ) { return mathDetail::ConvolveGpuStatus::INVALID_KERNEL_DATA; } } pexLog::TTrace<3>("lsst.afw.math.convolve", "MaskedImage, convolveLinearCombinationGPU: will use GPU acceleration"); std::vector< KernelBuffer > basisKernels(kernelN); for (int i = 0; i < kernelN; i++) { KernelImage kernelImage(kernelList[i]->getDimensions()); (void)kernelList[i]->computeImage(kernelImage, false); basisKernels[i].Init(kernelImage); } int const inImageWidth = inImage.getWidth(); int const inImageHeight = inImage.getHeight(); int const cnvWidth = inImageWidth + 1 - newKernel->getWidth(); int const cnvHeight = inImageHeight + 1 - newKernel->getHeight(); int const cnvStartX = newKernel->getCtrX(); int const cnvStartY = newKernel->getCtrY(); std::vector colPos(cnvWidth); std::vector rowPos(cnvHeight); for (int i = 0; i < cnvWidth; i++) { colPos[i] = inImage.indexToPosition(i + cnvStartX, afwImage::X); } for (int i = 0; i < cnvHeight; i++) { rowPos[i] = inImage.indexToPosition(i + cnvStartY, afwImage::Y); } gpuDetail::GpuBuffer2D inBufImg; gpuDetail::GpuBuffer2D inBufVar; gpuDetail::GpuBuffer2D inBufMsk; CopyFromMaskedImage(inImage, inBufImg, inBufVar, inBufMsk); gpuDetail::GpuBuffer2D outBufImg(cnvWidth, cnvHeight); gpuDetail::GpuBuffer2D outBufVar(cnvWidth, cnvHeight); gpuDetail::GpuBuffer2D outBufMsk(cnvWidth, cnvHeight); pexLog::TTrace<3>("lsst.afw.math.convolve", "MaskedImage, convolveLinearCombinationGPU: will use GPU acceleration"); #ifdef GPU_BUILD GPU_ConvolutionMI_LinearCombinationKernel( inBufImg, inBufVar, inBufMsk, colPos, rowPos, sFn, outBufImg, outBufVar, outBufMsk, basisKernels, sfType, convolutionControl.getDoNormalize() ); #endif CopyToImage(convolvedImage, cnvStartX, cnvStartY, outBufImg, outBufVar, outBufMsk); } return mathDetail::ConvolveGpuStatus::OK; } /** * @brief GPU convolution for Image class used when convolving a LinearCombinationKernel * * Alocates input and output image buffers, extracts data from Image into image buffers, * prepares all other data required for GPU convolution. * calls GPU_ConvolutionImage_LinearCombinationKernel to perform the convolutiuon. * * Delegates calculation to basicConvolve when: * - kernel is too small (less than 30 pixels * - there is not enough shared memory on device to hold the image blocks * (image blocks are larger than kernels) * - kernels don't match each other *
    407 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dimensions
    ? ^^^^^^ ^
    407 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dimensions
    ? ^^ ^
    408 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or height
    ? ^^^^^^ ^
    408 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or height
    ? ^^ ^
    409 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    409 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    410 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    410 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    411 af8f5ebe - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    411 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    412 03c5e027 - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    412 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    413 af8f5ebe - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    413 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * @ingroup afw */ template mathDetail::ConvolveGpuStatus::ReturnCode mathDetail::convolveLinearCombinationGPU( afwImage::Image& convolvedImage, ///< convolved %image afwImage::Image const& inImage, ///< %image to convolve afwMath::LinearCombinationKernel const& kernel, ///< convolution kernel afwMath::ConvolutionControl const & convolutionControl) ///< convolution control parameters { if (!afwGpu::isGpuBuild()) {
    425 af8f5ebe - throw LSST_EXCEPT(afwGpu::GpuRuntimeErrorException, "Afw not compiled with GPU support");
    ? ---------
    425 21597d88 + throw LSST_EXCEPT(afwGpu::GpuRuntimeError, "Afw not compiled with GPU support");
    } typedef typename afwMath::Kernel::Pixel KernelPixel; typedef afwImage::Image KernelImage; typedef gpuDetail::GpuBuffer2D KernelBuffer; if (!kernel.isSpatiallyVarying()) { // use the standard algorithm for the spatially invariant case pexLog::TTrace<3>("lsst.afw.math.convolve", "convolveLinearCombinationGPU: spatially invariant; delegate"); return mathDetail::convolveSpatiallyInvariantGPU(convolvedImage, inImage, kernel, convolutionControl.getDoNormalize()); } else { bool throwExceptionsOn=convolutionControl.getDevicePreference() == afwGpu::USE_GPU; if (afwGpu::detail::TryToSelectCudaDevice(!throwExceptionsOn) == false){ return mathDetail::ConvolveGpuStatus::NO_GPU; } // refactor the kernel if this is reasonable and possible; // then use the standard algorithm for the spatially varying case afwMath::Kernel::Ptr refKernelPtr; // possibly refactored version of kernel if (static_cast(kernel.getNKernelParameters()) > kernel.getNSpatialParameters()) { // refactoring will speed convolution, so try it refKernelPtr = kernel.refactor(); if (!refKernelPtr) { refKernelPtr = kernel.clone(); } } else { // too few basis kernels for refactoring to be worthwhile refKernelPtr = kernel.clone(); } { assertDimensionsOK(convolvedImage, inImage, kernel); const afwMath::LinearCombinationKernel* newKernel = dynamic_cast (refKernelPtr.get()); assert(newKernel!=NULL); const int kernelN = newKernel->getNBasisKernels(); const std::vector< afwMath::Kernel::SpatialFunctionPtr > sFn = newKernel->getSpatialFunctionList(); if (sFn.size() < 1) { return mathDetail::ConvolveGpuStatus::SFN_COUNT_ERROR; } if (int(sFn.size()) != kernelN) { return mathDetail::ConvolveGpuStatus::SFN_COUNT_ERROR; } bool isAllCheby = true; for (int i = 0; i < kernelN; i++) { if (! IS_INSTANCE( *sFn[i], afwMath::Chebyshev1Function2 ) ) { isAllCheby = false; } } bool isAllPoly = true; for (int i = 0; i < kernelN; i++) { if (! IS_INSTANCE( *sFn[i], afwMath::PolynomialFunction2 ) ) { isAllPoly = false; } } if (!isAllPoly && !isAllCheby) { return mathDetail::ConvolveGpuStatus::SFN_TYPE_ERROR; } int order = 0; #ifdef GPU_BUILD SpatialFunctionType_t sfType; #endif if (isAllPoly) { order = dynamic_cast*>( sFn[0].get() ) ->getOrder(); #ifdef GPU_BUILD sfType = sftPolynomial; #endif } else if(isAllCheby) { order = dynamic_cast*>( sFn[0].get() ) ->getOrder(); #ifdef GPU_BUILD sfType = sftChebyshev; #endif } else { return mathDetail::ConvolveGpuStatus::SFN_TYPE_ERROR; } //get copies of basis kernels const afwMath::KernelList kernelList = newKernel->getKernelList(); //if kernel is too small, call CPU convolution const int minKernelSize = 20; if (newKernel->getWidth() * newKernel->getHeight() < minKernelSize && convolutionControl.getDevicePreference() != lsst::afw::gpu::USE_GPU) { return mathDetail::ConvolveGpuStatus::KERNEL_TOO_SMALL; } //if something is wrong, call CPU convolution const bool shMemOkA = IsSufficientSharedMemoryAvailable_ForImgBlock( newKernel->getWidth(), newKernel->getHeight(), sizeof(double)); const bool shMemOkB = IsSufficientSharedMemoryAvailable_ForSfn(order, kernelN); if (!shMemOkA || !shMemOkB) { //cannot fit kernels into shared memory, revert to convolution by CPU return mathDetail::ConvolveGpuStatus::KERNEL_TOO_BIG; } if (kernelN == 0) { return mathDetail::ConvolveGpuStatus::KERNEL_COUNT_ERROR; } for (int i = 0; i < kernelN; i++) { if (kernelList[i]->getDimensions() != newKernel->getDimensions() || kernelList[i]->getCtr() != newKernel->getCtr() ) { return mathDetail::ConvolveGpuStatus::INVALID_KERNEL_DATA; } } std::vector< KernelBuffer > basisKernels(kernelN); for (int i = 0; i < kernelN; i++) { KernelImage kernelImage(kernelList[i]->getDimensions()); (void)kernelList[i]->computeImage(kernelImage, false); basisKernels[i].Init(kernelImage); } int const inImageWidth = inImage.getWidth(); int const inImageHeight = inImage.getHeight(); int const cnvWidth = inImageWidth + 1 - newKernel->getWidth(); int const cnvHeight = inImageHeight + 1 - newKernel->getHeight(); int const cnvStartX = newKernel->getCtrX(); int const cnvStartY = newKernel->getCtrY(); std::vector colPos(cnvWidth); std::vector rowPos(cnvHeight); for (int i = 0; i < cnvWidth; i++) { colPos[i] = inImage.indexToPosition(i + cnvStartX, afwImage::X); } for (int i = 0; i < cnvHeight; i++) { rowPos[i] = inImage.indexToPosition(i + cnvStartY, afwImage::Y); } gpuDetail::GpuBuffer2D inBuf(inImage); gpuDetail::GpuBuffer2D outBuf(cnvWidth, cnvHeight); pexLog::TTrace<3>("lsst.afw.math.convolve", "plain Image, convolveLinearCombinationGPU: will use GPU acceleration"); #ifdef GPU_BUILD GPU_ConvolutionImage_LinearCombinationKernel( inBuf, colPos, rowPos, sFn, outBuf, basisKernels, sfType, convolutionControl.getDoNormalize() ); #endif outBuf.CopyToImage(convolvedImage, cnvStartX, cnvStartY); } } return mathDetail::ConvolveGpuStatus::OK; } /** * @brief Convolve an Image with a spatially invariant Kernel. * * Alocates input and output image buffers, extracts data from Image into image buffers, * prepares all other data required for GPU convolution. * calls GPU_ConvolutionImage_SpatiallyInvariantKernel to perform the convolutiuon. * * Delegates calculation to basicConvolve when: * - kernel is too small (less than 20 pixels) * - there is not enough shared memory on device to hold the image blocks * (image blocks are larger than kernels) * * @warning Low-level convolution function that does not set edge pixels. * * convolvedImage must be the same size as inImage. * convolvedImage has a border in which the output pixels are not set. This border has size: * - kernel.getCtrX() along the left edge * - kernel.getCtrY() along the bottom edge * - kernel.getWidth() - 1 - kernel.getCtrX() along the right edge * - kernel.getHeight() - 1 - kernel.getCtrY() along the top edge *
    604 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dimensions
    ? ^^^^^^ ^
    604 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dimensions
    ? ^^ ^
    605 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or height
    ? ^^^^^^ ^
    605 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or height
    ? ^^ ^
    606 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    606 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    607 af8f5ebe - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    607 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    608 03c5e027 - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    608 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    609 af8f5ebe - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    609 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * @ingroup afw */ template mathDetail::ConvolveGpuStatus::ReturnCode mathDetail::convolveSpatiallyInvariantGPU( afwImage::Image& convolvedImage, ///< convolved %image afwImage::Image const& inImage, ///< %image to convolve afwMath::Kernel const& kernel, ///< convolution kernel afwMath::ConvolutionControl const & convolutionControl) ///< convolution control parameters { if (!afwGpu::isGpuBuild()) {
    621 af8f5ebe - throw LSST_EXCEPT(afwGpu::GpuRuntimeErrorException, "Afw not compiled with GPU support");
    ? ---------
    621 21597d88 + throw LSST_EXCEPT(afwGpu::GpuRuntimeError, "Afw not compiled with GPU support");
    } const bool doNormalize = convolutionControl.getDoNormalize(); const bool throwExceptionsOn=convolutionControl.getDevicePreference() == afwGpu::USE_GPU; if (afwGpu::detail::TryToSelectCudaDevice(!throwExceptionsOn) == false){ return mathDetail::ConvolveGpuStatus::NO_GPU; } typedef typename afwMath::Kernel::Pixel KernelPixel; typedef afwImage::Image KernelImage; typedef typename KernelImage::const_x_iterator KernelXIterator; typedef typename KernelImage::const_xy_locator KernelXYLocator; if (kernel.isSpatiallyVarying()) { return mathDetail::ConvolveGpuStatus::UNSUPPORTED_KERNEL; } assertDimensionsOK(convolvedImage, inImage, kernel); const int minKernelSize = 25; int const inImageWidth = inImage.getWidth(); int const inImageHeight = inImage.getHeight(); int const kWidth = kernel.getWidth(); int const kHeight = kernel.getHeight(); int const cnvWidth = inImageWidth + 1 - kernel.getWidth(); int const cnvHeight = inImageHeight + 1 - kernel.getHeight(); int const cnvStartX = kernel.getCtrX(); int const cnvStartY = kernel.getCtrY(); KernelImage kernelImage(kernel.getDimensions()); pexLog::TTrace<3>("lsst.afw.math.convolve", "convolveSpatiallyInvariantGPU: using GPU acceleration, " "plain Image, kernel is spatially invariant"); (void)kernel.computeImage(kernelImage, doNormalize); typedef afwImage::Image InImageT; typedef afwImage::Image OutImageT; const bool shMemOk = IsSufficientSharedMemoryAvailable_ForImgBlock(kWidth, kHeight, sizeof(double)); if (!shMemOk) { //cannot fit kernels into shared memory, revert to convolution by CPU return mathDetail::ConvolveGpuStatus::KERNEL_TOO_BIG; } //if kernel is too small, call CPU convolution if (kWidth * kHeight < minKernelSize && convolutionControl.getDevicePreference() != lsst::afw::gpu::USE_GPU) { return mathDetail::ConvolveGpuStatus::KERNEL_TOO_SMALL; } gpuDetail::GpuBuffer2D inBuf(inImage); gpuDetail::GpuBuffer2D outBuf(cnvWidth, cnvHeight); gpuDetail::GpuBuffer2D kernelBuf(kernelImage); #ifdef GPU_BUILD GPU_ConvolutionImage_SpatiallyInvariantKernel(inBuf, outBuf, kernelBuf); #endif outBuf.CopyToImage(convolvedImage, cnvStartX, cnvStartY); return mathDetail::ConvolveGpuStatus::OK; } /** * @brief Convolve an MaskedImage with a spatially invariant Kernel. * * Alocates input and output image buffers, extracts data from Image into image buffers, * prepares all other data required for GPU convolution. * calls GPU_ConvolutionMI_SpatiallyInvariantKernel to perform the convolutiuon. * * Delegates calculation to basicConvolve when: * - kernel is too small (less than 20 pixels) * - there is not enough shared memory on device to hold the image blocks * (image blocks are larger than kernels) * * @warning Low-level convolution function that does not set edge pixels. * * convolvedImage must be the same size as inImage. * convolvedImage has a border in which the output pixels are not set. This border has size: * - kernel.getCtrX() along the left edge * - kernel.getCtrY() along the bottom edge * - kernel.getWidth() - 1 - kernel.getCtrX() along the right edge * - kernel.getHeight() - 1 - kernel.getCtrY() along the top edge *
    705 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dimensions
    ? ^^^^^^ ^
    705 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dimensions
    ? ^^ ^
    706 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or height
    ? ^^^^^^ ^
    706 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or height
    ? ^^ ^
    707 154d7cbd - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    707 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    708 af8f5ebe - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    708 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    709 03c5e027 - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    709 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    710 af8f5ebe - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    710 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * @ingroup afw */ template mathDetail::ConvolveGpuStatus::ReturnCode mathDetail::convolveSpatiallyInvariantGPU( afwImage::MaskedImage& convolvedImage, ///< convolved %image afwImage::MaskedImage const& inImage, ///< %image to convolve afwMath::Kernel const& kernel, ///< convolution kernel afwMath::ConvolutionControl const & convolutionControl) ///< convolution control parameters { if (!afwGpu::isGpuBuild()) {
    722 af8f5ebe - throw LSST_EXCEPT(afwGpu::GpuRuntimeErrorException, "Afw not compiled with GPU support");
    ? ---------
    722 21597d88 + throw LSST_EXCEPT(afwGpu::GpuRuntimeError, "Afw not compiled with GPU support");
    } bool doNormalize = convolutionControl.getDoNormalize(); typedef afwImage::MaskedImage InImageT; typedef afwImage::MaskedImage OutImageT; typedef typename afwMath::Kernel::Pixel KernelPixel; typedef afwImage::Image KernelImage; typedef typename KernelImage::const_x_iterator KernelXIterator; typedef typename KernelImage::const_xy_locator KernelXYLocator; if (kernel.isSpatiallyVarying()) { return mathDetail::ConvolveGpuStatus::UNSUPPORTED_KERNEL; } assertDimensionsOK(convolvedImage, inImage, kernel); const int minKernelSize = 20; int const inImageWidth = inImage.getWidth(); int const inImageHeight = inImage.getHeight(); int const kWidth = kernel.getWidth(); int const kHeight = kernel.getHeight(); int const cnvWidth = inImageWidth + 1 - kernel.getWidth(); int const cnvHeight = inImageHeight + 1 - kernel.getHeight(); int const cnvStartX = kernel.getCtrX(); int const cnvStartY = kernel.getCtrY(); const bool throwExceptionsOn=convolutionControl.getDevicePreference() == afwGpu::USE_GPU; if (afwGpu::detail::TryToSelectCudaDevice(!throwExceptionsOn) == false){ return mathDetail::ConvolveGpuStatus::NO_GPU; } const bool shMemOk = IsSufficientSharedMemoryAvailable_ForImgAndMaskBlock(kWidth, kHeight, sizeof(double)); if (!shMemOk) { //cannot fit kernels into shared memory, revert to convolution by CPU return mathDetail::ConvolveGpuStatus::KERNEL_TOO_BIG; } //if kernel is too small, call CPU convolution if (kWidth * kHeight < minKernelSize && convolutionControl.getDevicePreference() != lsst::afw::gpu::USE_GPU) { return mathDetail::ConvolveGpuStatus::KERNEL_TOO_SMALL; } KernelImage kernelImage(kernel.getDimensions()); pexLog::TTrace<3>("lsst.afw.math.convolve", "convolveSpatiallyInvariantGPU: using GPU acceleration, " "MaskedImage, kernel is spatially invariant"); (void)kernel.computeImage(kernelImage, doNormalize); gpuDetail::GpuBuffer2D inBufImg; gpuDetail::GpuBuffer2D inBufVar; gpuDetail::GpuBuffer2D inBufMsk; CopyFromMaskedImage(inImage, inBufImg, inBufVar, inBufMsk); gpuDetail::GpuBuffer2D outBufImg(cnvWidth, cnvHeight); gpuDetail::GpuBuffer2D outBufVar(cnvWidth, cnvHeight); gpuDetail::GpuBuffer2D outBufMsk(cnvWidth, cnvHeight); gpuDetail::GpuBuffer2D kernelBuf(kernelImage); #ifdef GPU_BUILD GPU_ConvolutionMI_SpatiallyInvariantKernel( inBufImg, inBufVar, inBufMsk, outBufImg, outBufVar, outBufMsk, kernelBuf ); #endif CopyToImage(convolvedImage, cnvStartX, cnvStartY, outBufImg, outBufVar, outBufMsk); return mathDetail::ConvolveGpuStatus::OK; } /* * Explicit instantiation */ /// \cond #define IMAGE(PIXTYPE) afwImage::Image #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage #define NL /* */ // Instantiate Image or MaskedImage versions #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \ template mathDetail::ConvolveGpuStatus::ReturnCode mathDetail::basicConvolveGPU( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::Kernel const&, \ afwMath::ConvolutionControl const&); NL \ template mathDetail::ConvolveGpuStatus::ReturnCode mathDetail::convolveLinearCombinationGPU( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::LinearCombinationKernel const&, \ afwMath::ConvolutionControl const&); NL \ template mathDetail::ConvolveGpuStatus::ReturnCode mathDetail::convolveSpatiallyInvariantGPU( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::Kernel const&, \ afwMath::ConvolutionControl const&); // Instantiate both Image and MaskedImage versions #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE) INSTANTIATE(double, double) INSTANTIATE(double, float) INSTANTIATE(double, int) INSTANTIATE(double, boost::uint16_t) INSTANTIATE(float, float) INSTANTIATE(float, int) INSTANTIATE(float, boost::uint16_t) INSTANTIATE(int, int) INSTANTIATE(boost::uint16_t, boost::uint16_t) /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    af8f5ebe

    commit af8f5ebef4f524d96fa4c824d3c8eb1cf11a6869
    Author: Kresimir Cosic 
    Date:   Mon Feb 27 03:39:36 2012 +0100
    
        Added afw::gpu namespace, reorganized files and interfaces to use this namespace
    

    154d7cbd

    commit 154d7cbd5ab4b7403735cd096dae4ccec36debb4
    Author: cosic 
    Date:   Thu Jul 21 00:26:48 2011 +0000
    
        Initial changes. Both GPU builds and CPU scons builds seem to be working properly
    

    03c5e027

    commit 03c5e027bf9dd0d6fcb145d520bd83379d46fe42
    Author: cosic 
    Date:   Tue Nov 15 22:44:34 2011 +0000
    
        Now makes use of new GPU exceptions
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/geom/XYTransform.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /************************************************************************************************************/
                    
                    %{
    
    28 a06cb6fe + #include "lsst/afw/geom/Functor.h"
    #include "lsst/afw/geom/XYTransform.h"
    30 a06cb6fe + #include "lsst/afw/geom/SeparableXYTransform.h"
    %}
    32 eef4faa3 +
    33 a06cb6fe + %shared_ptr(lsst::afw::geom::Functor);
    34 a06cb6fe + %shared_ptr(lsst::afw::geom::LinearFunctor);
    %shared_ptr(lsst::afw::geom::XYTransform); %shared_ptr(lsst::afw::geom::IdentityXYTransform); %shared_ptr(lsst::afw::geom::InvertedXYTransform);
    39 0ac8b7e8 + %shared_ptr(lsst::afw::geom::AffineXYTransform);
    %shared_ptr(lsst::afw::geom::RadialXYTransform);
    35 d95640da - %shared_ptr(lsst::afw::geom::DetectorXYTransform);
    ? ^^ ^^^^^
    41 a8afb4cc + %shared_ptr(lsst::afw::geom::MultiXYTransform);
    ? ^^^ ^
    42 a06cb6fe + %shared_ptr(lsst::afw::geom::SeparableXYTransform);
    44 5a4777a9 + %template(XYTransformVector) std::vector;
    45 5a4777a9 +
    46 a06cb6fe + %include "lsst/afw/geom/Functor.h"
    %include "lsst/afw/geom/XYTransform.h"
    48 a06cb6fe + %include "lsst/afw/geom/SeparableXYTransform.h"

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d95640da

    commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
    Author: Kendrick Smith 
    Date:   Tue Feb 19 23:44:14 2013 -0500
    
        move afw::image::XYTransform -> afw::geom::XYTransform
             afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
             afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
        
        wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom
    

    Commits in /Users/nate/repos_lsst/afw/

    a06cb6fe

    commit a06cb6fe9ad8724f3f9b48c2a7ccf1013b742312
    Author: Jim Chiang 
    Date:   Tue Feb 17 08:07:00 2015 -0800
    
        Add Functor and SeparableXYTransform classes to support modeling of
        sensor effects.
        
        Functor is an abstract class that SeparableXYTransform takes as
        arguments in its constructor.  Distinct Functor subclass objects are
        used to model the transformations in the x- and y-directions,
        respectively.  Functor provides an inverse(...) member function that
        calls the subclass' concrete implementation of the Functor::derivative(...)
        pure virtual function to compute the inverse of the 1D function using
        Newton-Raphson.  LinearFunctor is provided as an example subclass.
    

    0ac8b7e8

    commit 0ac8b7e884f4a1fbd6a378ed1f44738157624b75
    Author: Simon Krughoff 
    Date:   Fri Feb 7 15:22:02 2014 -0600
    
        Implementation of AffineXYTransform.  Switched Orientation to return AffineXYTransform instead of AffineTransform
    

    5a4777a9

    commit 5a4777a9a5a8ce649192abc16ca895b7a1c7c97d
    Author: Russell Owen 
    Date:   Sat Mar 1 05:43:34 2014 -0800
    
        Fixed SWIG wrapper for a XYTransformVector
        Added InvertedXYTransform and MultiXYTransform to xyTransformRegistry,
        and added unit tests for both.
    

    a8afb4cc

    commit a8afb4cc71b25f8e140c7864ae94dd4d381e908e
    Author: Russell Owen 
    Date:   Fri Feb 28 15:29:33 2014 -0800
    
        Add MultiXYTransform, but something has gone wrong.
    

    eef4faa3

    commit eef4faa3ebbe60ce98d2839f502480e81e936de0
    Author: Jim Bosch 
    Date:   Thu Feb 7 15:10:39 2013 -0500
    
        Add Swig for XYTransform classes.
    

    Return to list

    python/lsst/afw/table/_syntax.py

    Diff:

    1 90e76936 - #
    ? -
    1 348f504b + #
    # LSST Data Management System
    3 90e76936 - # Copyright 2008, 2009, 2010, 2011, 2012 LSST Corporation.
    ? ^^^^^^^^ ^^^^^^^^^^^^^
    3 348f504b + # Copyright 2008-2015 LSST Corporation.
    ? ^ ^
    4 90e76936 - #
    ? -
    4 348f504b + #
    # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version.
    12 90e76936 - #
    ? -
    12 348f504b + #
    # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details.
    17 90e76936 - #
    ? -
    17 348f504b + #
    18 90e76936 - # You should have received a copy of the LSST License Statement and
    ? -
    18 348f504b + # You should have received a copy of the LSST License Statement and
    19 90e76936 - # the GNU General Public License along with this program. If not,
    ? -
    19 348f504b + # the GNU General Public License along with this program. If not,
    # see . # """ Special Python syntactic sugar for Catalogs and Records. This module is imported by tableLib.py, and should not need to be imported by any other module. I've moved the code out of the .i file here to avoid recompiling when only pure-Python code is changed. """ import fnmatch import re import numpy import collections def KeyBaseCov_subfields(self): """a tuple of Key subfield extraction indices (the lower-triangular elements).""" r = [] for i in range(self.getSize()): for j in range(i+1): r.append((i,j)) return tuple(r) def KeyBaseCov_subkeys(self): """a tuple of subelement Keys (the lower-triangular elements).""" r = [] for i in range(self.getSize()): for j in range(i+1): r.append(self[i,j]) return tuple(r) def Schema_extract(self, *patterns, **kwds): """ Extract a dictionary of {: } in which the field names match the given shell-style glob pattern(s). Any number of glob patterns may be passed; the result will be the union of all the result of each glob considered separately. Additional optional arguments may be passed as keywords: regex ------ A regular expression to be used in addition to any glob patterns passed as positional arguments. Note that this will be compared with re.match, not re.search. sub -------- A replacement string template (see re.MatchObject.expand) used to set the dictionary keys of any fields matched by regex. The field name in the SchemaItem is not modified. ordered----- If True, a collections.OrderedDict will be returned instead of a standard dict, with the order corresponding to the definition order of the Schema. """ if kwds.pop("ordered", False): d = collections.OrderedDict() else: d = dict() regex = kwds.pop("regex", None) sub = kwds.pop("sub", None) if sub is not None and regex is None: raise ValueError("'sub' keyword argument to extract is invalid without 'regex' argument") if kwds: raise ValueError("Unrecognized keyword arguments for extract: %s" % ", ".join(kwds.keys())) for item in self:
    84 9a07d2de - name = item.field.getName()
    ? ^
    84 25e84506 + trueName = item.field.getName()
    ? ^^^^^
    85 25e84506 + names = [trueName]
    86 25e84506 + for alias, target in self.getAliasMap().iteritems():
    87 25e84506 + if trueName.startswith(target):
    88 25e84506 + names.append(trueName.replace(target, alias, 1))
    89 25e84506 + for name in names:
    85 9a07d2de - if regex is not None:
    90 25e84506 + if regex is not None:
    ? ++++
    86 9a07d2de - m = re.match(regex, name)
    91 25e84506 + m = re.match(regex, name)
    ? ++++
    87 9a07d2de - if m is not None:
    92 25e84506 + if m is not None:
    ? ++++
    88 9a07d2de - if sub is not None:
    93 25e84506 + if sub is not None:
    ? ++++
    89 9a07d2de - name = m.expand(sub)
    94 25e84506 + name = m.expand(sub)
    ? ++++
    90 9a07d2de - d[name] = item
    95 25e84506 + d[name] = item
    ? ++++
    91 9a07d2de - continue # continue outer loop so we don't match the same name twice
    ? ^^^ -
    96 25e84506 + continue # continue middle loop so we don't match the same name twice
    ? ++++ ^^^^^
    92 9a07d2de - for pattern in patterns:
    97 25e84506 + for pattern in patterns:
    ? ++++
    93 9a07d2de - if fnmatch.fnmatchcase(item.field.getName(), pattern):
    ? ^^^^^^^^^^^^^^^ --
    98 25e84506 + if fnmatch.fnmatchcase(name, pattern):
    ? ++++ ^
    94 9a07d2de - d[name] = item
    99 25e84506 + d[name] = item
    ? ++++
    95 9a07d2de - break # break inner loop so we don't match the same name twice
    100 25e84506 + break # break inner loop so we don't match the same name twice
    ? ++++ return d def BaseRecord_extract(self, *patterns, **kwds): """ Extract a dictionary of {: } in which the field names match the given shell-style glob pattern(s). Any number of glob patterns may be passed; the result will be the union of all the result of each glob considered separately. Additional optional arguments may be passed as keywords: items ------ The result of a call to self.schema.extract(); this will be used instead of doing any new matching, and allows the pattern matching to be reused to extract values from multiple records. This keyword is incompatible with any position arguments and the regex, sub, and ordered keyword arguments. split ------ If True, fields with named subfields (e.g. points) will be split into separate items in the dict; instead of {"point": lsst.afw.geom.Point2I(2,3)}, for instance, you'd get {"point.x": 2, "point.y": 3}. Default is False. regex ------ A regular expression to be used in addition to any glob patterns passed as positional arguments. Note that this will be compared with re.match, not re.search. sub -------- A replacement string (see re.MatchObject.expand) used to set the dictionary keys of any fields matched by regex. ordered----- If True, a collections.OrderedDict will be returned instead of a standard dict, with the order corresponding to the definition order of the Schema. Default is False. """ d = kwds.pop("items", None) split = kwds.pop("split", False) if d is None: d = self.schema.extract(*patterns, **kwds).copy() elif kwds: raise ValueError("Unrecognized keyword arguments for extract: %s" % ", ".join(kwds.keys())) for name, schemaItem in d.items(): # can't use iteritems because we might be adding/deleting elements key = schemaItem.key if split and key.HAS_NAMED_SUBFIELDS: for subname, subkey in zip(key.subfields, key.subkeys): d["%s.%s" % (name, subname)] = self.get(subkey) del d[name] else: d[name] = self.get(schemaItem.key) return d def BaseColumnView_extract(self, *patterns, **kwds): """ Extract a dictionary of {: } in which the field names match the given shell-style glob pattern(s). Any number of glob patterns may be passed; the result will be the union of all the result of each glob considered separately. Note that extract("*", copy=True) provides an easy way to transform a row-major ColumnView into a possibly more efficient set of contiguous NumPy arrays. This routines unpacks Flag columns into full boolean arrays and covariances into dense (i.e. non-triangular packed) arrays with dimension (N,M,M), where N is the number of records and M is the dimension of the covariance matrix. Fields with named subfields (e.g. points) are always split into separate dictionary items, as is done in BaseRecord.extract(..., split=True). String fields are silently ignored. Additional optional arguments may be passed as keywords: items ------ The result of a call to self.schema.extract(); this will be used instead of doing any new matching, and allows the pattern matching to be reused to extract values from multiple records. This keyword is incompatible with any position arguments and the regex, sub, and ordered keyword arguments. where ------ Any expression that can be passed as indices to a NumPy array, including slices, boolean arrays, and index arrays, that will be used to index each column array. This is applied before arrays are copied when copy is True, so if the indexing results in an implicit copy no unnecessary second copy is performed. copy ------- If True, the returned arrays will be contiguous copies rather than strided views into the catalog. This ensures that the lifetime of the catalog is not tied to the lifetime of a particular catalog, and it also may improve the performance if the array is used repeatedly. Default is False. regex ------ A regular expression to be used in addition to any glob patterns passed as positional arguments. Note that this will be compared with re.match, not re.search. sub -------- A replacement string (see re.MatchObject.expand) used to set the dictionary keys of any fields matched by regex. ordered----- If True, a collections.OrderedDict will be returned instead of a standard dict, with the order corresponding to the definition order of the Schema. Default is False. """ copy = kwds.pop("copy", False) where = kwds.pop("where", None) d = kwds.pop("items", None) if d is None: d = self.schema.extract(*patterns, **kwds).copy() elif kwds: raise ValueError("Unrecognized keyword arguments for extract: %s" % ", ".join(kwds.keys())) def processArray(a): if where is not None: a = a[where] if copy: a = numpy.ascontiguousarray(a) return a for name, schemaItem in d.items(): # can't use iteritems because we might be adding/deleting elements key = schemaItem.key if key.HAS_NAMED_SUBFIELDS: for subname, subkey in zip(key.subfields, key.subkeys): d["%s.%s" % (name, subname)] = processArray(self.get(subkey)) del d[name] elif key.getTypeString().startswith("Cov"): unpacked = None for idx, subkey in zip(key.subfields, key.subkeys): i, j = idx array = processArray(self.get(subkey)) if unpacked is None: unpacked = numpy.zeros((array.size, key.getSize(), key.getSize()), dtype=array.dtype) unpacked[:,i,j] = array if i != j: unpacked[:,j,i] = array d[name] = unpacked elif key.getTypeString() == "String": del d[name] else: d[name] = processArray(self.get(schemaItem.key)) return d

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9a07d2de

    commit 9a07d2debffaa8528da2d1f2f93f079938fb74b3
    Author: Jim Bosch 
    Date:   Thu May 24 19:42:52 2012 -0400
    
        Added Python dictionary extractors to Schema, BaseRecord, and BaseColumnView.
    

    90e76936

    commit 90e7693682b5aa1f5863e08ead2a108ddfc87527
    Author: Jim Bosch 
    Date:   Wed Aug 29 15:41:55 2012 -0400
    
        tweak docstrings, add LSST license boilerplate
    

    Commits in /Users/nate/repos_lsst/afw/

    348f504b

    commit 348f504bf4889a94c0124042bdd2ddf27d2fbfbc
    Author: Jim Bosch 
    Date:   Fri Jan 23 16:55:05 2015 -0500
    
        tables/_syntax.py: cleanup whitespace / update copyright
    

    25e84506

    commit 25e84506758c975a55e7941ebcdde88d8a0923f0
    Author: Jim Bosch 
    Date:   Mon Jan 26 12:13:19 2015 -0500
    
        Include aliases in table extract() methods.
    

    Return to list

    python/lsst/afw/image/image.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %{
                    #   include "lsst/afw/image/Image.h"
                    #   include "lsst/afw/image/ImagePca.h"
                    %}
                    
                    //
                    // Must go Before the %include
                    //
                    %define %imagePtr(PIXEL_TYPE...)
                    %shared_ptr(lsst::afw::image::ImageBase);
                    %shared_ptr(lsst::afw::image::Image);
                    %shared_ptr(lsst::afw::image::DecoratedImage);
                    %declareNumPyConverters(lsst::afw::image::ImageBase::Array);
                    %declareNumPyConverters(lsst::afw::image::ImageBase::ConstArray);
                    %enddef
                    
                    //
                    // Must go After the %include
                    //
                    %define %image(NAME, TYPE, PIXEL_TYPE...)
                    %template(NAME##TYPE##Base) lsst::afw::image::ImageBase;
                    %template(NAME##TYPE) lsst::afw::image::Image;
                    %template(Decorated##NAME##TYPE) lsst::afw::image::DecoratedImage;
                    %lsst_persistable(lsst::afw::image::Image);
                    %lsst_persistable(lsst::afw::image::DecoratedImage);
                    
                    %template(vector##NAME##TYPE) std::vector > >;
                    %template(NAME##Pca##TYPE) lsst::afw::image::ImagePca >;
                    %template(NAME##PcaM##TYPE) lsst::afw::image::ImagePca >;
                    
                    %template(innerProduct) lsst::afw::image::innerProduct,
                                                                           lsst::afw::image::Image  >;
                    
                    %extend lsst::afw::image::Image {
                    
                        /**
                         * Set an image to the value val
                         */
                        void set(double val) {
                            *self = val;
                        }
                        /**
                         * Set pixel (x,y) to val
                         */
                        void set(int x, int y, double val) {
                            self->operator()(x, y, lsst::afw::image::CheckIndices(true)) = val;
                        }
                    
                        PIXEL_TYPE get(int x, int y) {
                            return self->operator()(x, y, lsst::afw::image::CheckIndices(true));
                        }
                    
                        void set0(int x, int y, double val) {
                            self->set0(x, y, val, lsst::afw::image::CheckIndices(true));
                        }
                        PIXEL_TYPE get0(int x, int y) {
                            PIXEL_TYPE p = self->get0(x, y, lsst::afw::image::CheckIndices(true));
                            return p;
                        }
                    
    
    85 f8edfe90 - %pythoncode {
    85 81c3bd10 + %pythoncode %{
    ? +
    86 f8edfe90 - #
    86 81c3bd10 + #
    87 f8edfe90 - # Deal with incorrect swig wrappers for C++ "void operator op=()"
    ? ----
    87 81c3bd10 + # Deal with incorrect swig wrappers for C++ "void operator op=()"
    88 f8edfe90 - #
    88 81c3bd10 + #
    89 f8edfe90 - def __ilshift__(*args):
    ? ----
    89 81c3bd10 + def __ilshift__(*args):
    90 f8edfe90 - """__ilshift__(self, NAME src) -> self"""
    ? ----
    90 81c3bd10 + """__ilshift__(self, NAME src) -> self"""
    91 f8edfe90 - _imageLib.NAME##TYPE##Base##___ilshift__(*args)
    ? ----
    91 81c3bd10 + _imageLib.NAME##TYPE##Base##___ilshift__(*args)
    92 f8edfe90 - return args[0]
    ? ----
    92 81c3bd10 + return args[0]
    94 f8edfe90 - def __iadd__(*args):
    ? ----
    94 81c3bd10 + def __iadd__(*args):
    95 f8edfe90 - """
    ? ----
    95 81c3bd10 + """
    96 f8edfe90 - __iadd__(self, float scalar) -> self
    ? ----
    96 81c3bd10 + __iadd__(self, float scalar) -> self
    97 f8edfe90 - __iadd__(self, NAME inputImage) -> self
    ? ----
    97 81c3bd10 + __iadd__(self, NAME inputImage) -> self
    98 f8edfe90 - """
    ? ----
    98 81c3bd10 + """
    99 f8edfe90 - _imageLib.NAME##TYPE##___iadd__(*args)
    ? ----
    99 81c3bd10 + _imageLib.NAME##TYPE##___iadd__(*args)
    100 f8edfe90 - return args[0]
    ? ----
    100 81c3bd10 + return args[0]
    102 f8edfe90 - def __isub__(*args):
    ? ----
    102 81c3bd10 + def __isub__(*args):
    103 f8edfe90 - """
    ? ----
    103 81c3bd10 + """
    104 f8edfe90 - __isub__(self, float scalar)
    ? ----
    104 81c3bd10 + __isub__(self, float scalar)
    105 f8edfe90 - __isub__(self, NAME inputImage)
    ? ----
    105 81c3bd10 + __isub__(self, NAME inputImage)
    106 f8edfe90 - """
    ? ----
    106 81c3bd10 + """
    107 f8edfe90 - _imageLib.NAME##TYPE##___isub__(*args)
    ? ----
    107 81c3bd10 + _imageLib.NAME##TYPE##___isub__(*args)
    108 f8edfe90 - return args[0]
    ? ----
    108 81c3bd10 + return args[0]
    109 f8edfe90 -
    110 81c3bd10 +
    111 f8edfe90 - def __imul__(*args):
    ? ----
    111 81c3bd10 + def __imul__(*args):
    112 f8edfe90 - """
    ? ----
    112 81c3bd10 + """
    113 f8edfe90 - __imul__(self, float scalar)
    ? ----
    113 81c3bd10 + __imul__(self, float scalar)
    114 f8edfe90 - __imul__(self, NAME inputImage)
    ? ----
    114 81c3bd10 + __imul__(self, NAME inputImage)
    115 f8edfe90 - """
    ? ----
    115 81c3bd10 + """
    116 f8edfe90 - _imageLib.NAME##TYPE##___imul__(*args)
    ? ----
    116 81c3bd10 + _imageLib.NAME##TYPE##___imul__(*args)
    117 f8edfe90 - return args[0]
    ? ----
    117 81c3bd10 + return args[0]
    119 f8edfe90 - def __idiv__(*args):
    ? ----
    119 81c3bd10 + def __idiv__(*args):
    120 f8edfe90 - """
    ? ----
    120 81c3bd10 + """
    121 f8edfe90 - __idiv__(self, float scalar)
    ? ----
    121 81c3bd10 + __idiv__(self, float scalar)
    122 f8edfe90 - __idiv__(self, NAME inputImage)
    ? ----
    122 81c3bd10 + __idiv__(self, NAME inputImage)
    123 f8edfe90 - """
    ? ----
    123 81c3bd10 + """
    124 f8edfe90 - _imageLib.NAME##TYPE##___idiv__(*args)
    ? ----
    124 81c3bd10 + _imageLib.NAME##TYPE##___idiv__(*args)
    125 f8edfe90 - return args[0]
    ? ----
    125 81c3bd10 + return args[0]
    126 81c3bd10 +
    127 81c3bd10 + # support "__from__ future import division" in Python 2; not needed for Python 3
    128 81c3bd10 + __itruediv__ = __idiv__
    129 81c3bd10 +
    126 f8edfe90 - }
    130 81c3bd10 + %}
    ? + } %defineClone(NAME##TYPE, lsst::afw::image::Image, PIXEL_TYPE); %supportSlicing(lsst::afw::image::Image, PIXEL_TYPE); %fits_reduce(lsst::afw::image::Image); %enddef /************************************************************************************************************/ %ignore lsst::afw::image::ImageBase::operator(); %ignore lsst::afw::image::ImageBase::get0; %ignore lsst::afw::image::ImageBase::set0; %ignore lsst::afw::image::ImageBase::swap; %ignore lsst::afw::image::ImageBase::begin; %ignore lsst::afw::image::ImageBase::end; %ignore lsst::afw::image::ImageBase::rbegin; %ignore lsst::afw::image::ImageBase::rend; %ignore lsst::afw::image::ImageBase::at; %ignore lsst::afw::image::ImageBase::row_begin; %ignore lsst::afw::image::ImageBase::row_end; %ignore lsst::afw::image::ImageBase::x_at; %ignore lsst::afw::image::ImageBase::col_begin; %ignore lsst::afw::image::ImageBase::col_end; %ignore lsst::afw::image::ImageBase::y_at; %ignore lsst::afw::image::ImageBase::xy_at; %imagePtr(boost::uint16_t); %imagePtr(boost::uint64_t); %imagePtr(int); %imagePtr(float); %imagePtr(double); %include "lsst/afw/image/Utils.h" %include "lsst/afw/image/Image.h" %include "lsst/afw/image/ImagePca.h" %include "lsst/afw/image/Mask.h" %image(Image, U, boost::uint16_t); %image(Image, L, boost::uint64_t); %image(Image, I, int); %image(Image, F, float); %image(Image, D, double); %template(vectorBBox) std::vector; %extend lsst::afw::image::Image { %newobject convertF; lsst::afw::image::Image convertF() { return lsst::afw::image::Image(*self, true); }
    176 e020773b - %pythoncode {
    180 81c3bd10 + %pythoncode %{
    ? + def convertFloat(self, *args): """Alias for convertF""" return self.convertF(*args)
    181 e020773b - }
    185 81c3bd10 + %}
    ? + } %extend lsst::afw::image::Image { %newobject convertD; lsst::afw::image::Image convertD() { return lsst::afw::image::Image(*self, true); }
    189 f0e831df - %pythoncode {
    193 81c3bd10 + %pythoncode %{
    ? + def convertDouble(self, *args): """Alias for convertD""" return self.convertD(*args)
    194 f0e831df - }
    198 81c3bd10 + %}
    ? + } %extend lsst::afw::image::Image { %newobject convertF; lsst::afw::image::Image convertF() { return lsst::afw::image::Image(*self, true); }
    202 e020773b - %pythoncode {
    206 81c3bd10 + %pythoncode %{
    ? + def convertFloat(self, *args): """Alias for convertF""" return self.convertF(*args)
    207 e020773b - }
    211 81c3bd10 + %}
    ? + } %extend lsst::afw::image::Image { %newobject convertD; lsst::afw::image::Image convertD() { return lsst::afw::image::Image(*self, true); } %newobject convertU; lsst::afw::image::Image convertU() { return lsst::afw::image::Image(*self, true); }
    219 e020773b - %pythoncode {
    223 81c3bd10 + %pythoncode %{
    ? + def convertU16(self, *args): """Alias for convertU""" return self.convertU(*args)
    224 e020773b - }
    228 81c3bd10 + %}
    ? + }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    e020773b

    commit e020773b0ed266a438b033d9c6fa67e7a34e1a25
    Author: rhl 
    Date:   Fri Apr 9 17:28:58 2010 +0000
    
        Add converter for MaskedImageU -> MaskedImageF; change names e.g. convertFloat -> convertF (but preserve old names as aliases)
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    f0e831df

    commit f0e831df133cdf9a2fc2f9d6ea1cbb6094ceebd5
    Author: price 
    Date:   Mon Nov 7 19:13:59 2011 +0000
    
        Changing footprint id type required adding support for uint64_t throughout afw.
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    src/detection/Threshold.cc

    Diff:

                    /* 
                     * LSST Data Management System 
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include 
                    #include 
                    #include 
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/math/Statistics.h"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/detection/Threshold.h"
                    
                    namespace image = lsst::afw::image;
                    namespace math = lsst::afw::math;
                    namespace pexLogging = lsst::pex::logging;
                    
                    namespace lsst {
                    namespace afw {
                    namespace detection {
                    
                    Threshold::ThresholdType Threshold::parseTypeString(std::string const & typeStr) {
                        if (typeStr.compare("bitmask") == 0) {
                            return Threshold::BITMASK;           
                        } else if (typeStr.compare("value") == 0) {
                            return Threshold::VALUE;           
                        } else if (typeStr.compare("stdev") == 0) {
                            return Threshold::STDEV;
                        } else if (typeStr.compare("variance") == 0) {
                            return Threshold::VARIANCE;
                        } else if (typeStr.compare("pixel_stdev") == 0) {
                            return Threshold::PIXEL_STDEV;
                        } else {
                            throw LSST_EXCEPT(
    
    53 17d1d529 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    53 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Unsupported Threshold type: %s") % typeStr).str() ); } } std::string Threshold::getTypeString(ThresholdType const & type) { if (type == VALUE) { return "value"; } else if (type == STDEV) { return "stdev"; } else if (type == VARIANCE) { return "variance"; } else { throw LSST_EXCEPT(
    68 17d1d529 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    68 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Unsopported Threshold type: %d") % type).str() ); } } /** * return value of threshold, to be interpreted via type * @param param value of variance/stdev if needed * @return value of threshold */ double Threshold::getValue(const double param) const { switch (_type) { case STDEV: if (param <= 0) { throw LSST_EXCEPT(
    84 17d1d529 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    84 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("St. dev. must be > 0: %g") % param).str() ); } return _value*param; case VALUE: case BITMASK: case PIXEL_STDEV: return _value; case VARIANCE: if (param <= 0) { throw LSST_EXCEPT(
    96 17d1d529 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    96 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Variance must be > 0: %g") % param).str() ); } return _value*std::sqrt(param); default: throw LSST_EXCEPT(
    103 17d1d529 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    103 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Unsupported type: %d") % _type).str() ); } } template double Threshold::getValue(ImageT const& image) const { double param = -1; // Parameter for getValue() if (_type == STDEV || _type == VARIANCE) { math::Statistics stats = math::makeStatistics(image, math::STDEVCLIP); double const sd = stats.getValue(math::STDEVCLIP); pexLogging::TTrace<3>("afw.detection", "St. Dev = %g", sd); if (_type == VARIANCE) { param = sd*sd; } else { param = sd; } } return getValue(param); } /** * \brief Factory method for creating Threshold objects * * @param value value of threshold * @param typeStr string representation of a ThresholdType. This parameter is * optional. Allowed values are: "variance", "value", "stdev", "pixel_stdev" * @param polarity If true detect positive objects, false for negative * * @return desired Threshold */ Threshold createThreshold( double const value, std::string const typeStr, bool const polarity ) { return Threshold(value, Threshold::parseTypeString(typeStr), polarity); } // // Explicit instantiations // #define INSTANTIATE(TYPE) \ template double Threshold::getValue(image::TYPE const&) const; \ template double Threshold::getValue(image::TYPE const&) const; \ template double Threshold::getValue(image::TYPE const&) const; \ template double Threshold::getValue(image::TYPE const&) const; \ template double Threshold::getValue(image::TYPE const&) const; #ifndef DOXYGEN INSTANTIATE(Image); INSTANTIATE(MaskedImage); #endif }}}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    17d1d529

    commit 17d1d529ed63e98f98e5d1a7a7da4811e95fc26c
    Author: dubcovsky 
    Date:   Tue Feb 15 00:00:43 2011 +0000
    
        #1556 Split Footprint.h into Threshold.h, FootprintSet.h, and FootprintFunctor.h, to correspond with class names. Added a constructors to Footprint which use geom objects (BoxI and Ellipse) to construct footprints. Footprints now exclusively use geom::PointI and geom::BoxI internally. (but still accept image::PointI and image::BBox for backwards compatibility wherever possible). FootprintArray.h contains a static functions to flatten and expand ndarrays using a Footprint to map between 2-d and 1-d indices.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/table/SchemaMapper.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_SchemaMapper_h_INCLUDED
                    #define AFW_TABLE_SchemaMapper_h_INCLUDED
                    
                    #include "boost/scoped_ptr.hpp"
                    
                    #include "lsst/afw/table/detail/SchemaMapperImpl.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    class BaseRecord;
                    
                    /**
                     *  @brief A mapping between the keys of two Schemas, used to copy data between them.
                     *
                     *  SchemaMapper is initialized with its input Schema, and contains member functions
                     *  to add mapped or unmapped fields to the output Schema.
                     */
                    class SchemaMapper {
                    public:
                    
                        /// @brief Return the input schema (copy-on-write).
                        Schema const getInputSchema() const { return _impl->_input; }
                    
                        /// @brief Return the output schema (copy-on-write).
                        Schema const getOutputSchema() const { return _impl->_output; }
                    
                        /// @brief Return a reference to the output schema that allows it to be modified in place.
                        Schema & editOutputSchema() { return _impl->_output; }
                    
                        /// @brief Add a new field to the output Schema that is not connected to the input Schema.
                        template 
                        Key addOutputField(Field const & newField, bool doReplace=false) {
                            return _impl->_output.addField(newField, doReplace);
                        }
                    
                        /**
                         *  @brief Add a new field to the output Schema that is a copy of a field in the input Schema.
                         *
                         *  If the input Key has already been mapped, the existing output Key will be reused
                         *  but the associated Field in the output Schema will be reset to a copy of the input Field.
                         *
                         *  If doReplace=True and a field with same name already exists in the output schema, that
                         *  field will be mapped instead of adding a new field to the output schema.  If doReplace=false
                         *  and a name conflict occurs, an exception will be thrown.
                         */
                        template 
                        Key addMapping(Key const & inputKey, bool doReplace=false);
                    
                        /**
                         *  @brief Add a new mapped field to the output Schema with new descriptions.
                         *
                         *  If the input Key has already been mapped, the existing output Key will be reused
                         *  but the associated Field will be replaced with the given one.
                         *
                         *  If doReplace=True and a field with same name already exists in the output schema, that
                         *  field will be mapped instead of adding a new field to the output schema.  If doReplace=false
                         *  and a name conflict occurs, an exception will be thrown.
                         */
                        template 
                        Key addMapping(Key const & inputKey, Field const & outputField, bool doReplace=false);
                    
                        /**
                         *  @brief Add a new mapped field to the output Schema with a new name.
                         *
                         *  If the input Key has already been mapped, the existing output Key will be reused
                         *  but the associated Field will be replaced with one with the given name.
                         *
                         *  If doReplace=True and a field with same name already exists in the output schema, that
                         *  field will be mapped instead of adding a new field to the output schema.  If doReplace=false
                         *  and a name conflict occurs, an exception will be thrown.
                         */
                        template 
                        Key addMapping(Key const & inputKey, std::string const & outputName, bool doReplace=true);
                    
                        /**
                         *  @brief Add mappings for all fields that match criteria defined by a predicate.
                         *
                         *  A mapping in the output Schema will be created for each SchemaItem 'i' in the input Schema
                         *  such that 'predicate(i)' is true.  Note that the predicate must have a templated
                         *  and/or sufficiently overloaded operator() to match all supported field types,
                         *  not just those present in the input Schema.
                         *
                         *  If doReplace=True and a field with same name already exists in the output schema, that
                         *  field will be mapped instead of adding a new field to the output schema.  If doReplace=false
                         *  and a name conflict occurs, an exception will be thrown.
                         */
                        template 
                        void addMappingsWhere(Predicate predicate, bool doReplace=true);
                    
                        /**
                         *  @brief Add the given minimal schema to the output schema.
                         *
                         *  This is intended to be used to ensure the output schema starts with some minimal schema.
                         *  It must be called before any other fields are added to the output schema.
                         *
                         *  @param[in] minimal     Minimal schema to be added to the beginning of the output schema.
                         *  @param[in] doMap       Whether to map minimal schema fields that are also present
                         *                         in the input schema.
                         */
                        void addMinimalSchema(Schema const & minimal, bool doMap=true);
                    
                        /**
                         *  @brief Create a mapper by removing fields from the front of a schema.
                         *
                         *  The returned mapper maps all fields in the input schema to all fields that are not
                         *  in the minimal schema (compared by keys, so the overlap must appear at the beginning
                         *  of the input schema).
                         *
                         *  @param[in] input       Input schema for the mapper.
                         *  @param[in] minimal     The minimal schema the input schema starts with.
                         */
                        static SchemaMapper removeMinimalSchema(Schema const & input, Schema const & minimal);
                    
                        /// @brief Swap the input and output schemas in-place.
                        void invert();
                    
                        /// @brief Return true if the given input Key is mapped to an output Key.
                        template 
                        bool isMapped(Key const & inputKey) const;
                    
    
    122 8f7cd2c5 - /// @brief Return the output Key corresponding to the given input Key, or raise NotFoundException.
    ? ^^^^^^ ^
    122 21597d88 + /// @brief Return the output Key corresponding to the given input Key, or raise NotFoundError.
    ? ^^ ^ template Key getMapping(Key const & inputKey) const; /** * @brief Call the given functor for each key pair in the mapper. * * Function objects should have a template and/or overloaded operator() * that takes two Key objects with the same type: * @code * struct Functor { * template * void operator()(Key const & input, Key const & output) const; * }; * @endcode * * The order of iteration is the same as the order in which mappings were added. */ template void forEach(F func) const { Impl::VisitorWrapper::type &> visitor(func); std::for_each(_impl->_map.begin(), _impl->_map.end(), visitor); } /// @brief Construct an empty mapper; useless unless you assign a fully-constructed one to it. explicit SchemaMapper(); /**
    150 c65fceac - * @brief Construct a mapper from the given input Schema and optional initial output Schema
    ? ---------
    150 56df42d2 + * @brief Construct a mapper from the given input Schema and initial output Schema
    * * @param[in] input The Schema that fields will be mapped from. * @param[in] output The starting point for the Schema that fields will be mapped to (no * mappings will be created automaticaly). Use addMapping() with * doReplace=true to connect input fields to preexisting fields in * the output schema. * * Note that the addMapping() methods will not connect input schema fields to existing * output schema fields unless doReplace=true; instead, these will by default append * new fields to the output schema. So most often you'll want to start with an empty * output schema and construct it as fields are mapped from the input schema, or be sure * to always pass doReplace=true to addMapping. */
    164 3a64a413 - explicit SchemaMapper(Schema const & input, Schema const & output=Schema());
    ? ---------
    164 56df42d2 + explicit SchemaMapper(Schema const & input, Schema const & output);
    165 56df42d2 +
    166 56df42d2 + /**
    167 56df42d2 + * @brief Construct a mapper from the given input Schema
    168 56df42d2 + *
    169 e1aa105a + * @param[in] input The Schema that fields will be mapped from.
    170 f1760fcb + * @param[in] shareAliasMap If true, install the input Schema's AliasMap in the
    171 f1760fcb + * output Schema.
    172 56df42d2 + *
    173 56df42d2 + * Note that the addMapping() methods will not connect input schema fields to existing
    174 56df42d2 + * output schema fields unless doReplace=true; instead, these will by default append
    175 56df42d2 + * new fields to the output schema. So most often you'll want to start with an empty
    176 56df42d2 + * output schema and construct it as fields are mapped from the input schema, or be sure
    177 56df42d2 + * to always pass doReplace=true to addMapping.
    178 56df42d2 + *
    179 e1aa105a + * The initial (empty) output schema will have the same version as the input schema, and
    180 e1aa105a + * they will share the same AliasMap (use editOutputSchema().disconnectAliases() to
    181 e1aa105a + * use a copy of the AliasMap).
    182 56df42d2 + */
    183 f1760fcb + explicit SchemaMapper(Schema const & input, bool shareAliasMap=false);
    /// @brief Copy construct (copy-on-write). SchemaMapper(SchemaMapper const & other); /// @brief Assignement (copy-on-write). SchemaMapper & operator=(SchemaMapper const & other); /** * @brief Combine a sequence of schemas into one, creating a SchemaMapper for each. * * @param[in] inputs A vector of input schemas to merge. * @param[in] prefixes An optional vector of prefixes for the output field names, * either empty or of the same size as the inputs vector. * * Each of the returned SchemaMappers has the same output schema. */ static std::vector join( std::vector const & inputs, std::vector const & prefixes = std::vector() ); private: template struct AddMappingsWhere { template void operator()(SchemaItem const & item) const { if (predicate(item)) mapper->addMapping(item.key, doReplace); } AddMappingsWhere(SchemaMapper * mapper_, Predicate predicate_, bool doReplace_) : mapper(mapper_), predicate(predicate_), doReplace(doReplace_) {} SchemaMapper * mapper; Predicate predicate; bool doReplace; }; typedef detail::SchemaMapperImpl Impl; boost::scoped_ptr _impl; }; template void SchemaMapper::addMappingsWhere(Predicate predicate, bool doReplace) { _impl->_input.forEach(AddMappingsWhere(this, predicate, doReplace)); } }}} // namespace lsst::afw::table #endif // !AFW_TABLE_SchemaMapper_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    3a64a413

    commit 3a64a4130c9480a8e13b05da0971822a0509fbe3
    Author: Jim Bosch 
    Date:   Thu Jan 16 12:20:09 2014 -0500
    
        Add output schema argument to SchemaMapper ctor
    

    8f7cd2c5

    commit 8f7cd2c59916e119aea9a5d20be9ae8b8bc7ddc7
    Author: Jim Bosch 
    Date:   Tue Nov 29 18:55:25 2011 -0500
    
        cleaned up Layout and added LayoutMapper
    

    c65fceac

    commit c65fceac2e281bff399bed4217a56288ca2f219e
    Author: Jim Bosch 
    Date:   Tue Jun 3 17:08:24 2014 -0400
    
        Documentation fix on SchemaMapper ctor's confusing behavior.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    56df42d2

    commit 56df42d2bb5dd4ebec2e5c67b0d16a137bb1dee2
    Author: Jim Bosch 
    Date:   Wed Aug 20 13:27:23 2014 -0400
    
        Add constructors to Schema and SchemaMapper to set version immediately.
    

    e1aa105a

    commit e1aa105ab8031359ba0a56c11573899780a6834a
    Author: Jim Bosch 
    Date:   Tue Apr 7 19:08:28 2015 -0400
    
        Transfer aliases when initializing SchemaMapper.
    

    f1760fcb

    commit f1760fcb7952e5dbf1baf526b40e502027f30491
    Author: Jim Bosch 
    Date:   Tue Apr 14 19:09:13 2015 -0400
    
        Make transfer of aliases in SchemaMapper optional.
        
        The previous change to always transfer aliases in SchemaMapper
        broke existing code; this change reverts to the original behavior,
        with an easy option for to transfer aliases if desired (which is now
        used by SourceTable and ExposureTable).
    

    Return to list

    src/math/detail/BasicConvolve.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * @file
                     *
                     * @brief Definition of basicConvolve and convolveWithBruteForce functions declared in detail/ConvolveImage.h
                     *
                     * @author Russell Owen
                     *
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/cstdint.hpp"
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/afw/image/MaskedImage.h"
                    #include "lsst/afw/math/ConvolveImage.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/math/detail/Convolve.h"
                    #include "lsst/afw/math/detail/ConvCpuGpuShared.h"
                    #include "lsst/afw/math/detail/ConvolveGPU.h"
                    #include "lsst/afw/gpu/IsGpuBuild.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace pexLog = lsst::pex::logging;
                    namespace afwGeom = lsst::afw::geom;
                    namespace afwImage = lsst::afw::image;
                    namespace afwMath = lsst::afw::math;
                    namespace mathDetail = lsst::afw::math::detail;
                    
                    namespace {
                    
                        /*
                         * @brief Compute the dot product of a kernel row or column and the overlapping portion of an %image
                         *
                         * @return computed dot product
                         *
                         * The pixel computed belongs at position imageIter + kernel center.
                         *
                         * @todo get rid of KernelPixelT parameter if possible by not computing local variable kVal,
                         * or by using iterator traits:
                         *     typedef typename std::iterator_traits::value_type KernelPixel;
                         * Unfortunately, in either case compilation fails with this sort of message:
                    \verbatim
                    include/lsst/afw/image/Pixel.h: In instantiation of ‘lsst::afw::image::pixel::exprTraits, boost::mpl::range_c > > >’:
                    include/lsst/afw/image/Pixel.h:385:   instantiated from ‘lsst::afw::image::pixel::BinaryExpr, boost::gil::pixel, boost::mpl::range_c > >, std::multiplies, lsst::afw::image::pixel::bitwise_or, lsst::afw::image::pixel::variance_multiplies >’
                    src/math/ConvolveImage.cc:59:   instantiated from ‘OutPixelT::kernelDotProduct(ImageIterT, KernelIterT, int) [with OutPixelT = lsst::afw::image::pixel::SinglePixel, ImageIterT = lsst::afw::image::MaskedImage::const_MaskedImageIterator, KernelIterT = const boost::gil::gray64f_noscalec_pixel_t*]’
                    src/math/ConvolveImage.cc:265:   instantiated from ‘void lsst::afw::math::basicConvolve(OutImageT&, const InImageT&, const lsst::afw::math::Kernel&, bool) [with OutImageT = lsst::afw::image::MaskedImage, InImageT = lsst::afw::image::MaskedImage]’
                    src/math/ConvolveImage.cc:451:   instantiated from ‘void lsst::afw::math::convolve(OutImageT&, const InImageT&, const KernelT&, bool, int) [with OutImageT = lsst::afw::image::MaskedImage, InImageT = lsst::afw::image::MaskedImage, KernelT = lsst::afw::math::AnalyticKernel]’
                    src/math/ConvolveImage.cc:587:   instantiated from here
                    include/lsst/afw/image/Pixel.h:210: error: no type named ‘ImagePixelT’ in ‘struct boost::gil::pixel, boost::mpl::range_c > >’
                    include/lsst/afw/image/Pixel.h:211: error: no type named ‘MaskPixelT’ in ‘struct boost::gil::pixel, boost::mpl::range_c > >’
                    include/lsst/afw/image/Pixel.h:212: error: no type named ‘VariancePixelT’ in ‘struct boost::gil::pixel, boost::mpl::range_c > >’
                    \endverbatim
                         */
                        template 
                        inline OutPixelT kernelDotProduct(
                                ImageIterT imageIter,       ///< start of input %image that overlaps kernel vector
                                KernelIterT kernelIter,     ///< start of kernel vector
                                int kWidth)                 ///< width of kernel
                        {
                            OutPixelT outPixel(0);
                            for (int x = 0; x < kWidth; ++x, ++imageIter, ++kernelIter) {
                                KernelPixelT kVal = *kernelIter;
                                if (kVal != 0) {
                                    outPixel += static_cast((*imageIter) * kVal);
                                }
                            }
                            return outPixel;
                        }
                    
                        /**
                         * @brief Throws exception when trying to USE_GPU without GPU support
                         *
                         * If GPU support was not included at compile time, USE_GPU option will cause
                         * this function to throw an exception
                         *
    
    106 af8f5ebe - * @throw lsst::pex::exceptions::RuntimeErrorException when USE_GPU enabled with no GPU support
    ? ---------
    106 21597d88 + * @throw lsst::pex::exceptions::RuntimeError when USE_GPU enabled with no GPU support
    * * @ingroup afw */ void CheckForceGpuOnNoGpu(afwMath::ConvolutionControl const& convolutionControl) { #ifndef GPU_BUILD if (lsst::afw::gpu::isGpuEnabled()==true && convolutionControl.getDevicePreference()==lsst::afw::gpu::USE_GPU) {
    115 62e1db6a - throw LSST_EXCEPT(pexExcept::RuntimeErrorException,
    ? ---------
    115 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError,
    "Gpu acceleration must be enabled at compiling for lsst::afw::gpu::USE_GPU"); } #endif } /** * @brief Throws exception whenever trying to USE_GPU * * USE_GPU option will cause this function to throw an exception *
    125 af8f5ebe - * @throw lsst::pex::exceptions::InvalidParameterException when USE_GPU is selected
    ? ^^^^^^ ^
    125 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError when USE_GPU is selected
    ? ^^ ^ * * @ingroup afw */ void CheckForceGpuOnUnsupportedKernel(afwMath::ConvolutionControl const& convolutionControl) { if (lsst::afw::gpu::isGpuEnabled()==true && convolutionControl.getDevicePreference()==lsst::afw::gpu::USE_GPU) {
    133 af8f5ebe - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "Gpu can not process this type of kernel");
    ? ^^^^^^ ^
    133 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "Gpu can not process this type of kernel");
    ? ^^ ^ } } } // anonymous namespace /** * @brief Low-level convolution function that does not set edge pixels. * * convolvedImage must be the same size as inImage. * convolvedImage has a border in which the output pixels are not set. This border has size: * - kernel.getCtrX() along the left edge * - kernel.getCtrY() along the bottom edge * - kernel.getWidth() - 1 - kernel.getCtrX() along the right edge * - kernel.getHeight() - 1 - kernel.getCtrY() along the top edge *
    149 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dimensions
    ? ^^^^^^ ^
    149 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dimensions
    ? ^^ ^
    150 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or height
    ? ^^^^^^ ^
    150 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or height
    ? ^^ ^
    151 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    151 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    152 d2b4aeab - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    152 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    153 d2b4aeab - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    153 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    154 d2b4aeab - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    154 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * @ingroup afw */ template void mathDetail::basicConvolve( OutImageT &convolvedImage, ///< convolved %image InImageT const& inImage, ///< %image to convolve afwMath::Kernel const& kernel, ///< convolution kernel afwMath::ConvolutionControl const& convolutionControl) ///< convolution control parameters { // Because convolve isn't a method of Kernel we can't always use Kernel's vtbl to dynamically // dispatch the correct version of basicConvolve. The case that fails is convolving with a kernel // obtained from a pointer or reference to a Kernel (base class), e.g. as used in LinearCombinationKernel. if (IS_INSTANCE(kernel, afwMath::DeltaFunctionKernel)) { pexLog::TTrace<4>("lsst.afw.math.convolve", "generic basicConvolve: dispatch to DeltaFunctionKernel basicConvolve"); mathDetail::basicConvolve(convolvedImage, inImage, *dynamic_cast(&kernel), convolutionControl); return; } else if (IS_INSTANCE(kernel, afwMath::SeparableKernel)) { pexLog::TTrace<4>("lsst.afw.math.convolve", "generic basicConvolve: dispatch to SeparableKernel basicConvolve"); mathDetail::basicConvolve(convolvedImage, inImage, *dynamic_cast(&kernel), convolutionControl); return; } else if (IS_INSTANCE(kernel, afwMath::LinearCombinationKernel) && kernel.isSpatiallyVarying()) { pexLog::TTrace<4>("lsst.afw.math.convolve", "generic basicConvolve: dispatch to spatially varying LinearCombinationKernel basicConvolve"); mathDetail::basicConvolve(convolvedImage, inImage, *dynamic_cast(&kernel), convolutionControl); return; } // OK, use general (and slower) form if (kernel.isSpatiallyVarying() && (convolutionControl.getMaxInterpolationDistance() > 1)) { // use linear interpolation pexLog::TTrace<3>("lsst.afw.math.convolve", "generic basicConvolve: using linear interpolation"); mathDetail::convolveWithInterpolation(convolvedImage, inImage, kernel, convolutionControl); } else { // use brute force pexLog::TTrace<3>("lsst.afw.math.convolve", "generic basicConvolve: using brute force"); mathDetail::convolveWithBruteForce(convolvedImage, inImage, kernel,convolutionControl); } } /** * @brief A version of basicConvolve that should be used when convolving delta function kernels *
    206 62e1db6a - * @throw lsst::pex::exceptions::InvalidParameterException when GPU acceleration forced
    ? ^^^^^^ ^
    206 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError when GPU acceleration forced
    ? ^^ ^ * * @ingroup afw */ template void mathDetail::basicConvolve( OutImageT& convolvedImage, ///< convolved %image InImageT const& inImage, ///< %image to convolve afwMath::DeltaFunctionKernel const &kernel, ///< convolution kernel afwMath::ConvolutionControl const &convolutionControl) ///< convolution control parameters { assert (!kernel.isSpatiallyVarying()); assertDimensionsOK(convolvedImage, inImage, kernel); CheckForceGpuOnUnsupportedKernel(convolutionControl); int const mImageWidth = inImage.getWidth(); // size of input region int const mImageHeight = inImage.getHeight(); int const cnvWidth = mImageWidth + 1 - kernel.getWidth(); int const cnvHeight = mImageHeight + 1 - kernel.getHeight(); int const cnvStartX = kernel.getCtrX(); int const cnvStartY = kernel.getCtrY(); int const inStartX = kernel.getPixel().getX(); int const inStartY = kernel.getPixel().getY(); pexLog::TTrace<3>("lsst.afw.math.convolve", "DeltaFunctionKernel basicConvolve"); for (int i = 0; i < cnvHeight; ++i) { typename InImageT::x_iterator inPtr = inImage.x_at(inStartX, i + inStartY); for (typename OutImageT::x_iterator cnvPtr = convolvedImage.x_at(cnvStartX, i + cnvStartY), cnvEnd = cnvPtr + cnvWidth; cnvPtr != cnvEnd; ++cnvPtr, ++inPtr){ *cnvPtr = *inPtr; } } } /** * @brief A version of basicConvolve that should be used when convolving a LinearCombinationKernel * * The Algorithm: * - If the kernel is spatially varying and contains only DeltaFunctionKernels * then convolves the input Image by each basis kernel in turn, solves the spatial model * for that component and adds in the appropriate amount of the convolved %image. * - In all other cases uses normal convolution *
    251 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dimensions
    ? ^^^^^^ ^
    251 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dimensions
    ? ^^ ^
    252 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or height
    ? ^^^^^^ ^
    252 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or height
    ? ^^ ^
    253 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    253 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    254 d2b4aeab - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    254 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    255 d2b4aeab - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    255 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    256 d2b4aeab - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    256 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * @ingroup afw */ template void mathDetail::basicConvolve( OutImageT& convolvedImage, ///< convolved %image InImageT const& inImage, ///< %image to convolve afwMath::LinearCombinationKernel const& kernel, ///< convolution kernel afwMath::ConvolutionControl const & convolutionControl) ///< convolution control parameters { if (!kernel.isSpatiallyVarying()) { // use the standard algorithm for the spatially invariant case pexLog::TTrace<3>("lsst.afw.math.convolve", "basicConvolve for LinearCombinationKernel: spatially invariant; using brute force"); return mathDetail::convolveWithBruteForce(convolvedImage, inImage, kernel, convolutionControl.getDoNormalize()); } else { CheckForceGpuOnNoGpu(convolutionControl); if (lsst::afw::gpu::isGpuBuild() && lsst::afw::gpu::isGpuEnabled()==true) { if (convolutionControl.getDevicePreference() == lsst::afw::gpu::AUTO_WITH_CPU_FALLBACK) { try { mathDetail::ConvolveGpuStatus::ReturnCode rc = mathDetail::convolveLinearCombinationGPU(convolvedImage,inImage,kernel, convolutionControl); if (rc == mathDetail::ConvolveGpuStatus::OK) return;
    282 af8f5ebe - } catch(lsst::afw::gpu::GpuMemoryException) { }
    ? ^^^^^^ ^
    282 21597d88 + } catch(lsst::afw::gpu::GpuMemoryError) { }
    ? ^^ ^
    283 03c5e027 - catch(pexExcept::MemoryException) { }
    ? ^^^^^^ ^
    283 21597d88 + catch(pexExcept::MemoryError) { }
    ? ^^ ^
    284 af8f5ebe - catch(lsst::afw::gpu::GpuRuntimeErrorException) { }
    ? ---------
    284 21597d88 + catch(lsst::afw::gpu::GpuRuntimeError) { }
    } else if (convolutionControl.getDevicePreference() != lsst::afw::gpu::USE_CPU) { mathDetail::ConvolveGpuStatus::ReturnCode rc = mathDetail::convolveLinearCombinationGPU(convolvedImage,inImage,kernel, convolutionControl); if (rc == mathDetail::ConvolveGpuStatus::OK) return; if (convolutionControl.getDevicePreference() == lsst::afw::gpu::USE_GPU) {
    291 62e1db6a - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Gpu will not process this kernel");
    ? ---------
    291 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Gpu will not process this kernel");
    } } } // refactor the kernel if this is reasonable and possible; // then use the standard algorithm for the spatially varying case PTR(afwMath::Kernel) refKernelPtr; // possibly refactored version of kernel if (static_cast(kernel.getNKernelParameters()) > kernel.getNSpatialParameters()) { // refactoring will speed convolution, so try it refKernelPtr = kernel.refactor(); if (!refKernelPtr) { refKernelPtr = kernel.clone(); } } else { // too few basis kernels for refactoring to be worthwhile refKernelPtr = kernel.clone(); } if (convolutionControl.getMaxInterpolationDistance() > 1) { pexLog::TTrace<3>("lsst.afw.math.convolve", "basicConvolve for LinearCombinationKernel: using interpolation"); return mathDetail::convolveWithInterpolation(convolvedImage, inImage, *refKernelPtr, convolutionControl); } else { pexLog::TTrace<3>("lsst.afw.math.convolve", "basicConvolve for LinearCombinationKernel: maxInterpolationError < 0; using brute force"); return mathDetail::convolveWithBruteForce(convolvedImage, inImage, *refKernelPtr, convolutionControl.getDoNormalize()); } } } /** * @brief A version of basicConvolve that should be used when convolving separable kernels *
    325 62e1db6a - * @throw lsst::pex::exceptions::InvalidParameterException when GPU acceleration forced
    ? ^^^^^^ ^
    325 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError when GPU acceleration forced
    ? ^^ ^ * * @ingroup afw */ template void mathDetail::basicConvolve( OutImageT& convolvedImage, ///< convolved %image InImageT const& inImage, ///< %image to convolve afwMath::SeparableKernel const &kernel, ///< convolution kernel afwMath::ConvolutionControl const & convolutionControl) ///< convolution control parameters { typedef typename afwMath::Kernel::Pixel KernelPixel; typedef typename std::vector KernelVector; typedef KernelVector::const_iterator KernelIterator; typedef typename InImageT::const_x_iterator InXIterator; typedef typename InImageT::const_xy_locator InXYLocator; typedef typename OutImageT::x_iterator OutXIterator; typedef typename OutImageT::y_iterator OutYIterator; typedef typename OutImageT::SinglePixel OutPixel; assertDimensionsOK(convolvedImage, inImage, kernel); CheckForceGpuOnUnsupportedKernel(convolutionControl); afwGeom::Box2I const fullBBox = inImage.getBBox(image::LOCAL); afwGeom::Box2I const goodBBox = kernel.shrinkBBox(fullBBox); KernelVector kernelXVec(kernel.getWidth()); KernelVector kernelYVec(kernel.getHeight()); if (kernel.isSpatiallyVarying()) { pexLog::TTrace<3>("lsst.afw.math.convolve", "SeparableKernel basicConvolve: kernel is spatially varying"); for (int cnvY = goodBBox.getMinY(); cnvY <= goodBBox.getMaxY(); ++cnvY) { double const rowPos = inImage.indexToPosition(cnvY, afwImage::Y); InXYLocator inImLoc = inImage.xy_at(0, cnvY - goodBBox.getMinY()); OutXIterator cnvXIter = convolvedImage.row_begin(cnvY) + goodBBox.getMinX(); for (int cnvX = goodBBox.getMinX(); cnvX <= goodBBox.getMaxX(); ++cnvX, ++inImLoc.x(), ++cnvXIter) { double const colPos = inImage.indexToPosition(cnvX, afwImage::X); KernelPixel kSum = kernel.computeVectors(kernelXVec, kernelYVec, convolutionControl.getDoNormalize(), colPos, rowPos); // why does this trigger warnings? It did not in the past. *cnvXIter = afwMath::convolveAtAPoint(inImLoc, kernelXVec, kernelYVec); if (convolutionControl.getDoNormalize()) { *cnvXIter = *cnvXIter/kSum; } } } } else { // kernel is spatially invariant // The basic sequence: // - For each output row: // - Compute x-convolved data: a kernel height's strip of input image convolved with kernel x vector // - Compute one row of output by dotting each column of x-convolved data with the kernel y vector // The x-convolved data is stored in a kernel-height by good-width buffer. // This is circular buffer along y (to avoid shifting pixels before setting each new row); // so for each new row the kernel y vector is rotated to match the order of the x-convolved data. pexLog::TTrace<3>("lsst.afw.math.convolve", "SeparableKernel basicConvolve: kernel is spatially invariant"); kernel.computeVectors(kernelXVec, kernelYVec, convolutionControl.getDoNormalize()); KernelIterator const kernelXVecBegin = kernelXVec.begin(); KernelIterator const kernelYVecBegin = kernelYVec.begin(); // buffer for x-convolved data OutImageT buffer(afwGeom::Extent2I(goodBBox.getWidth(), kernel.getHeight())); // pre-fill x-convolved data buffer with all but one row of data int yInd = 0; // during initial fill bufY = inImageY int const yPrefillEnd = buffer.getHeight() - 1; for (; yInd < yPrefillEnd; ++yInd) { OutXIterator bufXIter = buffer.x_at(0, yInd); OutXIterator const bufXEnd = buffer.x_at(goodBBox.getWidth(), yInd); InXIterator inXIter = inImage.x_at(0, yInd); for ( ; bufXIter != bufXEnd; ++bufXIter, ++inXIter) { *bufXIter = kernelDotProduct( inXIter, kernelXVecBegin, kernel.getWidth()); } } // compute output pixels using the sequence described above int inY = yPrefillEnd; int bufY = yPrefillEnd; int cnvY = goodBBox.getMinY(); while (true) { // fill next buffer row and compute output row InXIterator inXIter = inImage.x_at(0, inY); OutXIterator bufXIter = buffer.x_at(0, bufY); OutXIterator cnvXIter = convolvedImage.x_at(goodBBox.getMinX(), cnvY); for (int bufX = 0; bufX < goodBBox.getWidth(); ++bufX, ++cnvXIter, ++bufXIter, ++inXIter) { // note: bufXIter points to the row of the buffer that is being updated, // whereas bufYIter points to row 0 of the buffer *bufXIter = kernelDotProduct( inXIter, kernelXVecBegin, kernel.getWidth()); OutYIterator bufYIter = buffer.y_at(bufX, 0); *cnvXIter = kernelDotProduct( bufYIter, kernelYVecBegin, kernel.getHeight()); } // test for done now, instead of the start of the loop, // to avoid an unnecessary extra rotation of the kernel Y vector if (cnvY >= goodBBox.getMaxY()) break; // update y indices, including bufY, and rotate the kernel y vector to match ++inY; bufY = (bufY + 1) % kernel.getHeight(); ++cnvY; std::rotate(kernelYVec.begin(), kernelYVec.end()-1, kernelYVec.end()); } } } /** * @brief Convolve an Image or MaskedImage with a Kernel by computing the kernel image * at every point. (If the kernel is not spatially varying then only compute it once). * * @warning Low-level convolution function that does not set edge pixels. * * convolvedImage must be the same size as inImage. * convolvedImage has a border in which the output pixels are not set. This border has size: * - kernel.getCtrX() along the left edge * - kernel.getCtrY() along the bottom edge * - kernel.getWidth() - 1 - kernel.getCtrX() along the right edge * - kernel.getHeight() - 1 - kernel.getCtrY() along the top edge *
    457 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if convolvedImage dimensions != inImage dimensions
    ? ^^^^^^ ^
    457 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if convolvedImage dimensions != inImage dimensions
    ? ^^ ^
    458 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if inImage smaller than kernel in width or height
    ? ^^^^^^ ^
    458 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if inImage smaller than kernel in width or height
    ? ^^ ^
    459 f0a2e370 - * @throw lsst::pex::exceptions::InvalidParameterException if kernel width or height < 1
    ? ^^^^^^ ^
    459 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if kernel width or height < 1
    ? ^^ ^
    460 62e1db6a - * @throw lsst::pex::exceptions::InvalidParameterException when GPU acceleration forced on spatially varying kernel
    ? ^^^^^^ ^
    460 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError when GPU acceleration forced on spatially varying kernel
    ? ^^ ^
    461 d2b4aeab - * @throw lsst::pex::exceptions::MemoryException when allocation of CPU memory fails
    ? ^^^^^^ ^
    461 21597d88 + * @throw lsst::pex::exceptions::MemoryError when allocation of CPU memory fails
    ? ^^ ^
    462 d2b4aeab - * @throw lsst::afw::gpu::GpuMemoryException when allocation or transfer to/from GPU memory fails
    ? ^^^^^^ ^
    462 21597d88 + * @throw lsst::afw::gpu::GpuMemoryError when allocation or transfer to/from GPU memory fails
    ? ^^ ^
    463 d2b4aeab - * @throw lsst::afw::gpu::GpuRuntimeErrorException when GPU code run fails
    ? ---------
    463 21597d88 + * @throw lsst::afw::gpu::GpuRuntimeError when GPU code run fails
    * * @ingroup afw */ template void mathDetail::convolveWithBruteForce( OutImageT &convolvedImage, ///< convolved %image InImageT const& inImage, ///< %image to convolve afwMath::Kernel const& kernel, ///< convolution kernel afwMath::ConvolutionControl const & convolutionControl) ///< convolution control parameters { bool doNormalize=convolutionControl.getDoNormalize(); typedef typename afwMath::Kernel::Pixel KernelPixel; typedef afwImage::Image KernelImage; typedef typename KernelImage::const_x_iterator KernelXIterator; typedef typename KernelImage::const_xy_locator KernelXYLocator; typedef typename InImageT::const_x_iterator InXIterator; typedef typename InImageT::const_xy_locator InXYLocator; typedef typename OutImageT::x_iterator OutXIterator; typedef typename OutImageT::SinglePixel OutPixel; assertDimensionsOK(convolvedImage, inImage, kernel); int const inImageWidth = inImage.getWidth(); int const inImageHeight = inImage.getHeight(); int const kWidth = kernel.getWidth(); int const kHeight = kernel.getHeight(); int const cnvWidth = inImageWidth + 1 - kernel.getWidth(); int const cnvHeight = inImageHeight + 1 - kernel.getHeight(); int const cnvStartX = kernel.getCtrX(); int const cnvStartY = kernel.getCtrY(); int const cnvEndX = cnvStartX + cnvWidth; // end index + 1 int const cnvEndY = cnvStartY + cnvHeight; // end index + 1 KernelImage kernelImage(kernel.getDimensions()); KernelXYLocator const kernelLoc = kernelImage.xy_at(0,0); if (kernel.isSpatiallyVarying()) { pexLog::TTrace<5>("lsst.afw.math.convolve", "convolveWithBruteForce: kernel is spatially varying"); CheckForceGpuOnUnsupportedKernel(convolutionControl); for (int cnvY = cnvStartY; cnvY != cnvEndY; ++cnvY) { double const rowPos = inImage.indexToPosition(cnvY, afwImage::Y); InXYLocator inImLoc = inImage.xy_at(0, cnvY - cnvStartY); OutXIterator cnvXIter = convolvedImage.x_at(cnvStartX, cnvY); for (int cnvX = cnvStartX; cnvX != cnvEndX; ++cnvX, ++inImLoc.x(), ++cnvXIter) { double const colPos = inImage.indexToPosition(cnvX, afwImage::X); KernelPixel kSum = kernel.computeImage(kernelImage, false, colPos, rowPos); *cnvXIter = afwMath::convolveAtAPoint( inImLoc, kernelLoc, kWidth, kHeight); if (doNormalize) { *cnvXIter = *cnvXIter/kSum; } } } } else { pexLog::TTrace<5>("lsst.afw.math.convolve", "convolveWithBruteForce: kernel is spatially invariant"); CheckForceGpuOnNoGpu(convolutionControl); if (lsst::afw::gpu::isGpuBuild() && lsst::afw::gpu::isGpuEnabled()==true) { if (convolutionControl.getDevicePreference() == lsst::afw::gpu::AUTO_WITH_CPU_FALLBACK) { try { mathDetail::ConvolveGpuStatus::ReturnCode rc = mathDetail::convolveSpatiallyInvariantGPU(convolvedImage,inImage,kernel, convolutionControl); if (rc == mathDetail::ConvolveGpuStatus::OK) return;
    536 af8f5ebe - } catch(lsst::afw::gpu::GpuMemoryException) { }
    ? ^^^^^^ ^
    536 21597d88 + } catch(lsst::afw::gpu::GpuMemoryError) { }
    ? ^^ ^
    537 03c5e027 - catch(pexExcept::MemoryException) { }
    ? ^^^^^^ ^
    537 21597d88 + catch(pexExcept::MemoryError) { }
    ? ^^ ^
    538 af8f5ebe - catch(lsst::afw::gpu::GpuRuntimeErrorException) { }
    ? ---------
    538 21597d88 + catch(lsst::afw::gpu::GpuRuntimeError) { }
    } else if (convolutionControl.getDevicePreference() != lsst::afw::gpu::USE_CPU) { mathDetail::ConvolveGpuStatus::ReturnCode rc = mathDetail::convolveSpatiallyInvariantGPU(convolvedImage,inImage,kernel, convolutionControl); if (rc == mathDetail::ConvolveGpuStatus::OK) return; if (convolutionControl.getDevicePreference() == lsst::afw::gpu::USE_GPU) {
    545 62e1db6a - throw LSST_EXCEPT(pexExcept::RuntimeErrorException, "Gpu will not process this kernel");
    ? ---------
    545 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError, "Gpu will not process this kernel");
    } } } (void)kernel.computeImage(kernelImage, doNormalize); for (int inStartY = 0, cnvY = cnvStartY; inStartY < cnvHeight; ++inStartY, ++cnvY) { KernelXIterator kernelXIter = kernelImage.x_at(0, 0); InXIterator inXIter = inImage.x_at(0, inStartY); OutXIterator cnvXIter = convolvedImage.x_at(cnvStartX, cnvY); for (int x = 0; x < cnvWidth; ++x, ++cnvXIter, ++inXIter) { *cnvXIter = kernelDotProduct( inXIter, kernelXIter, kWidth); } for (int kernelY = 1, inY = inStartY + 1; kernelY < kHeight; ++inY, ++kernelY) { KernelXIterator kernelXIter = kernelImage.x_at(0, kernelY); InXIterator inXIter = inImage.x_at(0, inY); OutXIterator cnvXIter = convolvedImage.x_at(cnvStartX, cnvY); for (int x = 0; x < cnvWidth; ++x, ++cnvXIter, ++inXIter) { *cnvXIter += kernelDotProduct( inXIter, kernelXIter, kWidth); } } } } } /* * Explicit instantiation */ /// \cond #define IMAGE(PIXTYPE) afwImage::Image #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage #define NL /* */ // Instantiate Image or MaskedImage versions #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \ template void mathDetail::basicConvolve( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::Kernel const&, \ afwMath::ConvolutionControl const&); NL \ template void mathDetail::basicConvolve( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::DeltaFunctionKernel const&, \ afwMath::ConvolutionControl const&); NL \ template void mathDetail::basicConvolve( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::LinearCombinationKernel const&, \ afwMath::ConvolutionControl const&); NL \ template void mathDetail::basicConvolve( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::SeparableKernel const&, \ afwMath::ConvolutionControl const&); NL \ template void mathDetail::convolveWithBruteForce( \ IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::Kernel const&, \ afwMath::ConvolutionControl const&); // Instantiate both Image and MaskedImage versions #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \ INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE) INSTANTIATE(double, double) INSTANTIATE(double, float) INSTANTIATE(double, int) INSTANTIATE(double, boost::uint16_t) INSTANTIATE(float, float) INSTANTIATE(float, int) INSTANTIATE(float, boost::uint16_t) INSTANTIATE(int, int) INSTANTIATE(boost::uint16_t, boost::uint16_t) /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f0a2e370

    commit f0a2e370f838fd5323a7746c9e8f12da9f58c4d1
    Author: rowen 
    Date:   Thu Jun 24 23:37:24 2010 +0000
    
        Implemented ticket #1345:
        - convolve sets xy0 of the output image (not yet tested; I'll add this)
        - convolve throws an exception if kernel width or height < 1 (tested)
        - the default constructor for DeltaFunctionKernel sets isDeltaFunctionBasis (not unit testable)
        - Kernel and subclasses should not support copy or assignment (not unit testable)
    

    62e1db6a

    commit 62e1db6a824a3e00d3e747c1ea44a6b22e7429ae
    Author: cosic 
    Date:   Thu Jul 21 15:10:48 2011 +0000
    
        GPU/CPU device selection by ConvolutionControl implemented
    

    03c5e027

    commit 03c5e027bf9dd0d6fcb145d520bd83379d46fe42
    Author: cosic 
    Date:   Tue Nov 15 22:44:34 2011 +0000
    
        Now makes use of new GPU exceptions
    

    af8f5ebe

    commit af8f5ebef4f524d96fa4c824d3c8eb1cf11a6869
    Author: Kresimir Cosic 
    Date:   Mon Feb 27 03:39:36 2012 +0100
    
        Added afw::gpu namespace, reorganized files and interfaces to use this namespace
    

    d2b4aeab

    commit d2b4aeab82fff0526c277614f8b85caa2aee3cda
    Author: Kresimir Cosic 
    Date:   Fri Mar 23 04:59:14 2012 +0100
    
        Should work with w2012
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/geom/ellipses/Quadrupole.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include "lsst/afw/geom/ellipses/Quadrupole.h"
                    #include "lsst/afw/geom/ellipses/Axes.h"
                    
                    namespace lsst { namespace afw { namespace geom { namespace ellipses {
                    
                    BaseCore::Registrar Quadrupole::registrar;
                    
                    std::string Quadrupole::getName() const { return "Quadrupole"; }
                    
                    void Quadrupole::normalize() {
                        if (_matrix(0, 1) != _matrix(1, 0))
    
    35 ce01a540 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException, "Quadrupole matrix must be symmetric.");
    ? ^^^^^^ ^
    35 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, "Quadrupole matrix must be symmetric.");
    ? ^^ ^ if (getIxx() < 0 || getIyy() < 0)
    37 ce01a540 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException, "Quadrupole matrix cannot have negative diagonal elements.");
    ? ^^^^^^ ^
    37 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, "Quadrupole matrix cannot have negative diagonal elements.");
    ? ^^ ^ if (getDeterminant() < 0)
    39 ce01a540 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException, "Quadrupole matrix cannot have negative determinant.");
    ? ^^^^^^ ^
    39 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, "Quadrupole matrix cannot have negative determinant.");
    ? ^^ ^ } void Quadrupole::readParameters(double const * iter) { setIxx(*iter++); setIyy(*iter++); setIxy(*iter++); } void Quadrupole::writeParameters(double * iter) const { *iter++ = getIxx(); *iter++ = getIyy(); *iter++ = getIxy(); } Quadrupole::Quadrupole(double ixx, double iyy, double ixy, bool normalize) { setIxx(ixx); setIyy(iyy); setIxy(ixy); if (normalize) this->normalize(); } Quadrupole::Quadrupole(BaseCore::ParameterVector const & vector, bool normalize) { setIxx(vector[IXX]); setIyy(vector[IYY]); setIxy(vector[IXY]); if (normalize) this->normalize(); } Quadrupole::Quadrupole(Matrix const & matrix, bool normalize) : _matrix(matrix) { if (normalize) this->normalize(); } void Quadrupole::_assignToQuadrupole(double & ixx, double & iyy, double & ixy) const { ixx = getIxx(); iyy = getIyy(); ixy = getIxy(); } BaseCore::Jacobian Quadrupole::_dAssignToQuadrupole(double & ixx, double & iyy, double & ixy) const { ixx = getIxx(); iyy = getIyy(); ixy = getIxy(); return Jacobian::Identity(); } void Quadrupole::_assignToAxes(double & a, double & b, double & theta) const { BaseCore::_assignQuadrupoleToAxes(getIxx(), getIyy(), getIxy(), a, b, theta); } BaseCore::Jacobian Quadrupole::_dAssignToAxes(double & a, double & b, double & theta) const { return BaseCore::_dAssignQuadrupoleToAxes(getIxx(), getIyy(), getIxy(), a, b, theta); } void Quadrupole::_assignFromQuadrupole(double ixx, double iyy, double ixy) { setIxx(ixx); setIyy(iyy); setIxy(ixy); } BaseCore::Jacobian Quadrupole::_dAssignFromQuadrupole(double ixx, double iyy, double ixy) { setIxx(ixx); setIyy(iyy); setIxy(ixy); return Jacobian::Identity(); } void Quadrupole::_assignFromAxes(double a, double b, double theta) { BaseCore::_assignAxesToQuadrupole(a, b, theta, _matrix(0,0), _matrix(1,1), _matrix(0,1)); _matrix(1,0) = _matrix(0,1); } BaseCore::Jacobian Quadrupole::_dAssignFromAxes(double a, double b, double theta) { Jacobian r = BaseCore::_dAssignAxesToQuadrupole(a, b, theta, _matrix(0,0), _matrix(1,1), _matrix(0,1)); _matrix(1,0) = _matrix(0,1); return r; } }}}} // namespace lsst::afw::geom::ellipses

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ce01a540

    commit ce01a5406f327071e1701d534e563f0e75b870c4
    Author: jbosch 
    Date:   Wed Feb 2 01:27:08 2011 +0000
    
        afw #1556 - ellipses updated (#1551), but swig wrappers for ellipses now broken
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/ticket2905.py

    Diff:

    1 f59ee963 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008-2013 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # import os, os.path import unittest import lsst.afw.image as afwImage import lsst.utils.tests as utilsTests #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class Ticket2905Test(unittest.TestCase): """Test reading a FITS header that contains: INR-STR = 2E-05 """ def test(self): path = os.path.join("tests", "data", "ticket2905.fits") md = afwImage.readMetadata(path) value = md.get("INR-STR") self.assertEqual(type(value), float) self.assertEqual(value, 2.0e-5) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(Ticket2905Test) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f59ee963

    commit f59ee96362fbaa30cb358b96ec464c81bf2e09bf
    Author: Paul Price 
    Date:   Tue Jul 2 12:12:03 2013 -0400
    
        fits: fix regex for doubles in header (#2905)
        
        Also add test operating on a stripped-down version of the
        FITS header that identified the problem.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    src/math/warpExposure.cc

    Diff:

                    // -*- LSST-C++ -*- // fixed format comment for emacs
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * \file
                     *
                     * \ingroup afw
                     *
                     * \brief Support for warping an %image to a new Wcs.
                     */
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/shared_ptr.hpp"
                    #include "boost/pointer_cast.hpp"
                    #include "boost/cstdint.hpp"
                    #include "boost/regex.hpp"
                    
                    #include "lsst/pex/logging/Trace.h"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/warpExposure.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/math/Kernel.h"
                    #include "lsst/afw/coord/Coord.h"
                    #include "lsst/afw/image/Calib.h"
                    #include "lsst/afw/image/Wcs.h"
                    #include "lsst/afw/gpu/IsGpuBuild.h"
                    #include "lsst/afw/gpu/GpuExceptions.h"
                    #include "lsst/afw/gpu/DevicePreference.h"
                    #include "lsst/afw/math/detail/CudaLanczosWrapper.h"
    
    59 8a049406 - #include "lsst/afw/math/detail/SrcPosFunctor.h"
    ? ---
    59 624db730 + #include "lsst/afw/math/detail/PositionFunctor.h"
    ? +++++ #include "lsst/afw/math/detail/WarpAtOnePoint.h" namespace pexExcept = lsst::pex::exceptions; namespace pexLog = lsst::pex::logging; namespace afwImage = lsst::afw::image; namespace afwGeom = lsst::afw::geom; namespace afwCoord = lsst::afw::coord; namespace afwMath = lsst::afw::math; // // A helper function for the warping kernels which provides error-checking: // the warping kernels are designed to work in two cases // 0 < x < 1 and ctrX=(size-1)/2 // -1 < x < 0 and ctrX=(size+1)/2 // (and analogously for y). Note that to get the second case, Kernel::setCtrX(1) must be // called before calling Kernel::setKernelParameter(). [see afw::math::offsetImage() for // an example] // // FIXME eventually the 3 warping kernels will inherit from a common base class WarpingKernel // and this routine can be eliminated by putting the code in WarpingKernel::setKernelParameter() // static inline void checkWarpingKernelParameter(const afwMath::SeparableKernel *p, unsigned int ind, double value) { if (ind > 1) {
    85 5a91bf50 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "bad ind argument in WarpingKernel::setKernelParameter()");
    ? ^^^^^^ ^
    85 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "bad ind argument in WarpingKernel::setKernelParameter()");
    ? ^^ ^ } int ctr = p->getCtr()[ind]; int size = p->getDimensions()[ind]; if (ctr == (size-1)/2) { if (value < -1e-6 || value > 1+1e-6) {
    92 5a91bf50 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "bad coordinate in WarpingKernel::setKernelParameter()");
    ? ^^^^^^ ^
    92 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "bad coordinate in WarpingKernel::setKernelParameter()");
    ? ^^ ^ } } else if (ctr == (size+1)/2) { if (value < -1-1e-6 || value > 1e-6) {
    96 5a91bf50 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "bad coordinate in WarpingKernel::setKernelParameter()");
    ? ^^^^^^ ^
    96 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "bad coordinate in WarpingKernel::setKernelParameter()");
    ? ^^ ^ } } else {
    99 5a91bf50 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "bad ctr value in WarpingKernel::setKernelParameter()");
    ? ^^^^^^ ^
    99 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "bad ctr value in WarpingKernel::setKernelParameter()");
    ? ^^ ^ } } PTR(afwMath::Kernel) afwMath::LanczosWarpingKernel::clone() const { return PTR(afwMath::Kernel)(new afwMath::LanczosWarpingKernel(this->getOrder())); } /** * @brief get the order of the kernel */ int afwMath::LanczosWarpingKernel::getOrder() const { return this->getWidth() / 2; } void afwMath::LanczosWarpingKernel::setKernelParameter(unsigned int ind, double value) const { checkWarpingKernelParameter(this, ind, value); SeparableKernel::setKernelParameter(ind, value); } PTR(afwMath::Kernel) afwMath::BilinearWarpingKernel::clone() const { return PTR(afwMath::Kernel)(new afwMath::BilinearWarpingKernel()); } /** * \brief Solve bilinear equation * * Only the following arguments will give reliably meaningful values: * * 0.0 or 1.0 if the kernel center index is 0 in this axis * * -1.0 or 0.0 if the kernel center index is 1 in this axis */ afwMath::Kernel::Pixel afwMath::BilinearWarpingKernel::BilinearFunction1::operator() (double x) const { // // this->_params[0] = value of x where we want to interpolate the function // x = integer value of x where we evaluate the function in the interpolation // // The following weird-looking expression has no if/else statements, is roundoff-tolerant, // and works in the following two cases: // 0 < this->_params[0] < 1, x \in {0,1} // -1 < this->_params[0] < 0, x \in {-1,0} // // The checks in BilinearWarpingKernel::setKernelParameter() ensure that one of these // conditions is satisfied // return 0.5 + (1.0 - (2.0 * fabs(this->_params[0]))) * (0.5 - fabs(x)); } void afwMath::BilinearWarpingKernel::setKernelParameter(unsigned int ind, double value) const { checkWarpingKernelParameter(this, ind, value); SeparableKernel::setKernelParameter(ind, value); } /** * \brief Return string representation. */ std::string afwMath::BilinearWarpingKernel::BilinearFunction1::toString(std::string const& prefix) const { std::ostringstream os; os << "_BilinearFunction1: "; os << Function1::toString(prefix); return os.str(); } PTR(afwMath::Kernel) afwMath::NearestWarpingKernel::clone() const { return PTR(afwMath::Kernel)(new afwMath::NearestWarpingKernel()); } /** * \brief Solve nearest neighbor equation * * Only the following arguments will give reliably meaningful values: * * 0.0 or 1.0 if the kernel center index is 0 in this axis * * -1.0 or 0.0 if the kernel center index is 1 in this axis */ afwMath::Kernel::Pixel afwMath::NearestWarpingKernel::NearestFunction1::operator() (double x) const { // this expression is faster than using conditionals, but offers no sanity checking return static_cast((fabs(this->_params[0]) < 0.5) == (fabs(x) < 0.5)); } void afwMath::NearestWarpingKernel::setKernelParameter(unsigned int ind, double value) const { checkWarpingKernelParameter(this, ind, value); SeparableKernel::setKernelParameter(ind, value); } /** * \brief Return string representation. */ std::string afwMath::NearestWarpingKernel::NearestFunction1::toString(std::string const& prefix) const { std::ostringstream os; os << "_NearestFunction1: "; os << Function1::toString(prefix); return os.str(); } boost::shared_ptr afwMath::makeWarpingKernel(std::string name) { typedef boost::shared_ptr KernelPtr; boost::cmatch matches; static const boost::regex LanczosRE("lanczos(\\d+)"); if (name == "bilinear") { return KernelPtr(new BilinearWarpingKernel()); } else if (boost::regex_match(name.c_str(), matches, LanczosRE)) { std::string orderStr(matches[1].first, matches[1].second); int order; std::istringstream(orderStr) >> order; return KernelPtr(new LanczosWarpingKernel(order)); } else if (name == "nearest") { return KernelPtr(new NearestWarpingKernel()); } else {
    211 068759b9 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    211 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ "unknown warping kernel name: \"" + name + "\""); } } PTR(afwMath::SeparableKernel) afwMath::WarpingControl::getWarpingKernel() const { if (_warpingKernelPtr->getCacheSize() != _cacheSize) { _warpingKernelPtr->computeCache(_cacheSize); } return _warpingKernelPtr; }; void afwMath::WarpingControl::setWarpingKernelName( std::string const &warpingKernelName ) { PTR(SeparableKernel) warpingKernelPtr(makeWarpingKernel(warpingKernelName)); setWarpingKernel(*warpingKernelPtr); } void afwMath::WarpingControl::setWarpingKernel( SeparableKernel const &warpingKernel ) { if (_maskWarpingKernelPtr) { _testWarpingKernels(warpingKernel, *_maskWarpingKernelPtr); } PTR(SeparableKernel) warpingKernelPtr(boost::static_pointer_cast(warpingKernel.clone())); _testDevicePreference(_devicePreference, warpingKernelPtr); _warpingKernelPtr = warpingKernelPtr; } PTR(afwMath::SeparableKernel) afwMath::WarpingControl::getMaskWarpingKernel() const { if (_maskWarpingKernelPtr) { // lazily update kernel cache if (_maskWarpingKernelPtr->getCacheSize() != _cacheSize) { _maskWarpingKernelPtr->computeCache(_cacheSize); } } return _maskWarpingKernelPtr; } void afwMath::WarpingControl::setMaskWarpingKernelName( std::string const &maskWarpingKernelName ) { if (!maskWarpingKernelName.empty()) { PTR(SeparableKernel) maskWarpingKernelPtr(makeWarpingKernel(maskWarpingKernelName)); setMaskWarpingKernel(*maskWarpingKernelPtr); } else { _maskWarpingKernelPtr.reset(); } } void afwMath::WarpingControl::setMaskWarpingKernel( SeparableKernel const & maskWarpingKernel ) { _testWarpingKernels(*_warpingKernelPtr, maskWarpingKernel); _maskWarpingKernelPtr = boost::static_pointer_cast(maskWarpingKernel.clone()); } void afwMath::WarpingControl::_testWarpingKernels( SeparableKernel const &warpingKernel, SeparableKernel const &maskWarpingKernel ) const { lsst::afw::geom::Box2I kernelBBox = lsst::afw::geom::Box2I( lsst::afw::geom::Point2I(0, 0) - lsst::afw::geom::Extent2I(warpingKernel.getCtr()), warpingKernel.getDimensions() ); lsst::afw::geom::Box2I maskKernelBBox = lsst::afw::geom::Box2I( lsst::afw::geom::Point2I(0, 0) - lsst::afw::geom::Extent2I(maskWarpingKernel.getCtr()), maskWarpingKernel.getDimensions() ); if (!kernelBBox.contains(maskKernelBBox)) {
    283 00ce5756 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    283 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "warping kernel is smaller than mask warping kernel"); } } void afwMath::WarpingControl::_testDevicePreference( lsst::afw::gpu::DevicePreference const &devicePreference, CONST_PTR(SeparableKernel) const &warpingKernelPtr ) const { CONST_PTR(LanczosWarpingKernel) const lanczosKernelPtr = boost::dynamic_pointer_cast(warpingKernelPtr); if (devicePreference == lsst::afw::gpu::USE_GPU && !lanczosKernelPtr) {
    295 00ce5756 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    295 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "devicePreference = USE_GPU, but warping kernel not Lanczos"); } } template int afwMath::warpExposure( DestExposureT &destExposure, SrcExposureT const &srcExposure, afwMath::WarpingControl const &control, typename DestExposureT::MaskedImageT::SinglePixel padValue ) { if (!destExposure.hasWcs()) {
    311 8a049406 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "destExposure has no Wcs");
    ? ^^^^^^ ^
    311 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "destExposure has no Wcs");
    ? ^^ ^ } if (!srcExposure.hasWcs()) {
    314 8a049406 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "srcExposure has no Wcs");
    ? ^^^^^^ ^
    314 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "srcExposure has no Wcs");
    ? ^^ ^ } typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage(); boost::shared_ptr calibCopy(new afwImage::Calib(*srcExposure.getCalib())); destExposure.setCalib(calibCopy); destExposure.setFilter(srcExposure.getFilter()); return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(), control, padValue); } template int afwMath::warpExposure( DestExposureT &destExposure, SrcExposureT const &srcExposure, afwMath::SeparableKernel &warpingKernel, int const interpLength, typename DestExposureT::MaskedImageT::SinglePixel padValue, lsst::afw::gpu::DevicePreference devPref ) { if (!destExposure.hasWcs()) {
    335 84d4fa7d - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "destExposure has no Wcs");
    ? ^^^^^^ ^
    335 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "destExposure has no Wcs");
    ? ^^ ^ } if (!srcExposure.hasWcs()) {
    338 84d4fa7d - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "srcExposure has no Wcs");
    ? ^^^^^^ ^
    338 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "srcExposure has no Wcs");
    ? ^^ ^ } typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage(); boost::shared_ptr calibCopy(new afwImage::Calib(*srcExposure.getCalib())); destExposure.setCalib(calibCopy); destExposure.setFilter(srcExposure.getFilter()); return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(), warpingKernel, interpLength, padValue, devPref); } /************************************************************************************************************/ namespace { inline afwGeom::Point2D computeSrcPos( int destCol, ///< destination column index int destRow, ///< destination row index afwGeom::Point2D const &destXY0, ///< xy0 of destination image afwImage::Wcs const &destWcs, ///< WCS of remapped %image afwImage::Wcs const &srcWcs) ///< WCS of source %image { double const col = afwImage::indexToPosition(destCol + destXY0[0]); double const row = afwImage::indexToPosition(destRow + destXY0[1]); afwGeom::Angle sky1, sky2; destWcs.pixelToSky(col, row, sky1, sky2); return srcWcs.skyToPixel(sky1, sky2); } inline double computeRelativeArea( afwGeom::Point2D const &srcPos, /// source position at desired destination pixel afwGeom::Point2D const &leftSrcPos, /// source position one destination pixel to the left afwGeom::Point2D const &upSrcPos) /// source position one destination pixel above { afwGeom::Extent2D dSrcA = srcPos - leftSrcPos; afwGeom::Extent2D dSrcB = srcPos - upSrcPos; return std::abs(dSrcA.getX()*dSrcB.getY() - dSrcA.getY()*dSrcB.getX()); } template int doWarpImage( DestImageT &destImage, ///< remapped %image SrcImageT const &srcImage, ///< source %image
    383 8f6195b0 - afwMath::detail::SrcPosFunctor const &computeSrcPos, ///< Functor to compute source position
    ? ---
    383 624db730 + afwMath::detail::PositionFunctor const &computeSrcPos, ///< Functor to compute source position
    ? +++++ afwMath::WarpingControl const &control, ///< warping parameters typename DestImageT::SinglePixel padValue ///< value to use for undefined pixels ) { if (afwMath::details::isSameObject(destImage, srcImage)) {
    388 efc19368 - throw LSST_EXCEPT(pexExcept::InvalidParameterException,
    ? ^^^^^^ ^
    388 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError,
    ? ^^ ^ "destImage is srcImage; cannot warp in place"); } if (destImage.getBBox(afwImage::LOCAL).isEmpty()) { return 0; } // if src image is too small then don't try to warp try { PTR(afwMath::SeparableKernel) warpingKernelPtr = control.getWarpingKernel(); warpingKernelPtr->shrinkBBox(srcImage.getBBox(afwImage::LOCAL)); } catch(...) { for (int y = 0, height = destImage.getHeight(); y < height; ++y) { for (typename DestImageT::x_iterator destPtr = destImage.row_begin(y), end = destImage.row_end(y); destPtr != end; ++destPtr) { *destPtr = padValue; } } return 0; } PTR(afwMath::SeparableKernel) warpingKernelPtr = control.getWarpingKernel(); int interpLength = control.getInterpLength(); lsst::afw::gpu::DevicePreference devPref = control.getDevicePreference(); boost::shared_ptr const lanczosKernelPtr = boost::dynamic_pointer_cast(warpingKernelPtr); if (lsst::afw::gpu::isGpuEnabled()) { if(!lanczosKernelPtr) { if (devPref == lsst::afw::gpu::USE_GPU) {
    417 7d6d57d5 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, "Gpu can process only Lanczos kernels");
    ? ^^^^^^ ^
    417 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, "Gpu can process only Lanczos kernels");
    ? ^^ ^ } } else if (devPref == lsst::afw::gpu::USE_GPU || (lsst::afw::gpu::isGpuBuild() && interpLength > 0) ) { PTR(afwMath::SeparableKernel) maskWarpingKernelPtr = control.getWarpingKernel(); if (control.getMaskWarpingKernel() ) maskWarpingKernelPtr = control.getMaskWarpingKernel(); if (devPref == lsst::afw::gpu::AUTO_WITH_CPU_FALLBACK) { try { std::pair result = afwMath::detail::warpImageGPU(destImage, srcImage, *lanczosKernelPtr, *maskWarpingKernelPtr, computeSrcPos, interpLength, padValue, false); if (result.second == afwMath::detail::WarpImageGpuStatus::OK) return result.first; }
    431 7d6d57d5 - catch(lsst::afw::gpu::GpuMemoryException) { }
    ? ^^^^^^ ^
    431 21597d88 + catch(lsst::afw::gpu::GpuMemoryError) { }
    ? ^^ ^
    432 7d6d57d5 - catch(pexExcept::MemoryException) { }
    ? ^^^^^^ ^
    432 21597d88 + catch(pexExcept::MemoryError) { }
    ? ^^ ^
    433 7d6d57d5 - catch(lsst::afw::gpu::GpuRuntimeErrorException) { }
    ? ---------
    433 21597d88 + catch(lsst::afw::gpu::GpuRuntimeError) { }
    } else if (devPref != lsst::afw::gpu::USE_CPU) { std::pair result = afwMath::detail::warpImageGPU(destImage, srcImage, *lanczosKernelPtr, *maskWarpingKernelPtr, computeSrcPos, interpLength, padValue, devPref == lsst::afw::gpu::USE_GPU); if (result.second == afwMath::detail::WarpImageGpuStatus::OK) return result.first; if (devPref == lsst::afw::gpu::USE_GPU) {
    442 7d6d57d5 - throw LSST_EXCEPT(pexExcept::RuntimeErrorException,
    ? ---------
    442 21597d88 + throw LSST_EXCEPT(pexExcept::RuntimeError,
    "Gpu cannot perform this warp (kernel too big?)"); } } } } int numGoodPixels = 0;
    450 c31ebcf9 -
    451 efc19368 - typedef afwImage::Image KernelImageT;
    // Get the source MaskedImage and a pixel accessor to it. int const srcWidth = srcImage.getWidth(); int const srcHeight = srcImage.getHeight(); pexLog::TTrace<3>("lsst.afw.math.warp", "source image width=%d; height=%d", srcWidth, srcHeight); int const destWidth = destImage.getWidth(); int const destHeight = destImage.getHeight(); pexLog::TTrace<3>("lsst.afw.math.warp", "remap image width=%d; height=%d", destWidth, destHeight); // Set each pixel of destExposure's MaskedImage pexLog::TTrace<4>("lsst.afw.math.warp", "Remapping masked image"); // A cache of pixel positions on the source corresponding to the previous or current row // of the destination image. // The first value is for column -1 because the previous source position is used to compute relative area // To simplify the indexing, use an iterator that starts at begin+1, thus: // srcPosView = _srcPosList.begin() + 1 // srcPosView[col-1] and lower indices are for this row // srcPosView[col] and higher indices are for the previous row std::vector _srcPosList(1 + destWidth); std::vector::iterator const srcPosView = _srcPosList.begin() + 1; int const maxCol = destWidth - 1; int const maxRow = destHeight - 1; afwMath::detail::WarpAtOnePoint warpAtOnePoint(srcImage, control, padValue); if (interpLength > 0) { // Use interpolation. Note that 1 produces the same result as no interpolation // but uses this code branch, thus providing an easy way to compare the two branches. // Estimate for number of horizontal interpolation band edges, to reserve memory in vectors int const numColEdges = 2 + ((destWidth - 1) / interpLength); // A list of edge column indices for interpolation bands; // starts at -1, increments by interpLen (except the final interval), and ends at destWidth-1 std::vector edgeColList; edgeColList.reserve(numColEdges); // A list of 1/column width for horizontal interpolation bands; the first value is garbage. // The inverse is used for speed because the values is always multiplied. std::vector invWidthList; invWidthList.reserve(numColEdges); // Compute edgeColList and invWidthList edgeColList.push_back(-1); invWidthList.push_back(0.0); for (int prevEndCol = -1; prevEndCol < maxCol; prevEndCol += interpLength) { int endCol = prevEndCol + interpLength; if (endCol > maxCol) { endCol = maxCol; } edgeColList.push_back(endCol); assert(endCol - prevEndCol > 0); invWidthList.push_back(1.0 / static_cast(endCol - prevEndCol)); } assert(edgeColList.back() == maxCol); // A list of delta source positions along the edge columns of the horizontal interpolation bands std::vector yDeltaSrcPosList(edgeColList.size()); // Initialize _srcPosList for row -1 //srcPosView[-1] = computeSrcPos(-1, -1, destXY0, destWcs, srcWcs); srcPosView[-1] = computeSrcPos(-1, -1); for (int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) { int const prevEndCol = edgeColList[colBand-1]; int const endCol = edgeColList[colBand]; afwGeom::Point2D leftSrcPos = srcPosView[prevEndCol]; afwGeom::Point2D rightSrcPos = computeSrcPos(endCol, -1); afwGeom::Extent2D xDeltaSrcPos = (rightSrcPos - leftSrcPos) * invWidthList[colBand]; for (int col = prevEndCol + 1; col <= endCol; ++col) { srcPosView[col] = srcPosView[col-1] + xDeltaSrcPos; } } int endRow = -1; while (endRow < maxRow) { // Next horizontal interpolation band int prevEndRow = endRow; endRow = prevEndRow + interpLength; if (endRow > maxRow) { endRow = maxRow; } assert(endRow - prevEndRow > 0); double interpInvHeight = 1.0 / static_cast(endRow - prevEndRow); // Set yDeltaSrcPosList for this horizontal interpolation band for (int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) { int endCol = edgeColList[colBand]; afwGeom::Point2D bottomSrcPos = computeSrcPos(endCol, endRow); yDeltaSrcPosList[colBand] = (bottomSrcPos - srcPosView[endCol]) * interpInvHeight; } for (int row = prevEndRow + 1; row <= endRow; ++row) { typename DestImageT::x_iterator destXIter = destImage.row_begin(row); srcPosView[-1] += yDeltaSrcPosList[0]; for (int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) { /// Next vertical interpolation band int const prevEndCol = edgeColList[colBand-1]; int const endCol = edgeColList[colBand]; // Compute xDeltaSrcPos; remember that srcPosView contains // positions for this row in prevEndCol and smaller indices, // and positions for the previous row for larger indices (including endCol) afwGeom::Point2D leftSrcPos = srcPosView[prevEndCol]; afwGeom::Point2D rightSrcPos = srcPosView[endCol] + yDeltaSrcPosList[colBand]; afwGeom::Extent2D xDeltaSrcPos = (rightSrcPos - leftSrcPos) * invWidthList[colBand]; for (int col = prevEndCol + 1; col <= endCol; ++col, ++destXIter) { afwGeom::Point2D leftSrcPos = srcPosView[col-1]; afwGeom::Point2D srcPos = leftSrcPos + xDeltaSrcPos; double relativeArea = computeRelativeArea(srcPos, leftSrcPos, srcPosView[col]); srcPosView[col] = srcPos; if (warpAtOnePoint(destXIter, srcPos, relativeArea, typename lsst::afw::image::detail::image_traits::image_category())) { ++numGoodPixels; } } // for col } // for col band } // for row } // while next row band } else { // No interpolation // initialize _srcPosList for row -1; // the first value is not needed, but it's safer to compute it std::vector::iterator srcPosView = _srcPosList.begin() + 1; for (int col = -1; col < destWidth; ++col) { srcPosView[col] = computeSrcPos(col, -1); } for (int row = 0; row < destHeight; ++row) { typename DestImageT::x_iterator destXIter = destImage.row_begin(row); srcPosView[-1] = computeSrcPos(-1, row); for (int col = 0; col < destWidth; ++col, ++destXIter) { afwGeom::Point2D srcPos = computeSrcPos(col, row); double relativeArea = computeRelativeArea(srcPos, srcPosView[col-1], srcPosView[col]); srcPosView[col] = srcPos; if (warpAtOnePoint(destXIter, srcPos, relativeArea, typename lsst::afw::image::detail::image_traits::image_category())) { ++numGoodPixels; } } // for col } // for row } // if interp return numGoodPixels; } } // namespace template int afwMath::warpImage( DestImageT &destImage, lsst::afw::image::Wcs const &destWcs, SrcImageT const &srcImage, lsst::afw::image::Wcs const &srcWcs, afwMath::WarpingControl const &control, typename DestImageT::SinglePixel padValue ) { afwGeom::Point2D const destXY0(destImage.getXY0());
    625 8a049406 - afwMath::detail::WcsSrcPosFunctor const computeSrcPos(destXY0, destWcs, srcWcs);
    ? ---
    623 624db730 + afwMath::detail::WcsPositionFunctor const computeSrcPos(destXY0, destWcs, srcWcs);
    ? +++++ return doWarpImage(destImage, srcImage, computeSrcPos, control, padValue); } template int afwMath::warpImage( DestImageT &destImage, afwImage::Wcs const &destWcs, SrcImageT const &srcImage, afwImage::Wcs const &srcWcs, afwMath::SeparableKernel &warpingKernel, int const interpLength, typename DestImageT::SinglePixel padValue, lsst::afw::gpu::DevicePreference devPref ) { afwGeom::Point2D const destXY0(destImage.getXY0());
    641 8f6195b0 - afwMath::detail::WcsSrcPosFunctor const computeSrcPos(destXY0, destWcs, srcWcs);
    ? ---
    639 624db730 + afwMath::detail::WcsPositionFunctor const computeSrcPos(destXY0, destWcs, srcWcs);
    ? +++++ afwMath::WarpingControl control(warpingKernel, interpLength, devPref); return doWarpImage(destImage, srcImage, computeSrcPos, control, padValue); } template int afwMath::warpImage( DestImageT &destImage, SrcImageT const &srcImage, afwGeom::AffineTransform const &affineTransform, afwMath::WarpingControl const &control, typename DestImageT::SinglePixel padValue ) { afwGeom::Point2D const destXY0(destImage.getXY0());
    656 8a049406 - afwMath::detail::AffineTransformSrcPosFunctor const computeSrcPos(destXY0, affineTransform);
    ? ---
    654 624db730 + afwMath::detail::AffineTransformPositionFunctor const computeSrcPos(destXY0, affineTransform);
    ? +++++ return doWarpImage(destImage, srcImage, computeSrcPos, control, padValue); } template int afwMath::warpImage( DestImageT &destImage, SrcImageT const &srcImage, afwMath::SeparableKernel &warpingKernel, afwGeom::AffineTransform const &affineTransform, int const interpLength, typename DestImageT::SinglePixel padValue, lsst::afw::gpu::DevicePreference devPref ) { afwGeom::Point2D const destXY0(destImage.getXY0());
    673 8a049406 - afwMath::detail::AffineTransformSrcPosFunctor const computeSrcPos(destXY0, affineTransform);
    ? ---
    671 624db730 + afwMath::detail::AffineTransformPositionFunctor const computeSrcPos(destXY0, affineTransform);
    ? +++++ afwMath::WarpingControl control(warpingKernel, interpLength, devPref); return doWarpImage(destImage, srcImage, computeSrcPos, control, padValue); } template int afwMath::warpCenteredImage( DestImageT &destImage, SrcImageT const &srcImage, afwGeom::LinearTransform const &linearTransform,
    684 8a049406 - afwGeom::Point2D const ¢erPixel,
    ? ^^^
    682 7edb421a + afwGeom::Point2D const ¢erPosition,
    ? ++ ^^^^ afwMath::WarpingControl const &control, typename DestImageT::SinglePixel padValue ) { // force src and dest to be the same size and xy0 if ( (destImage.getWidth() != srcImage.getWidth()) || (destImage.getHeight() != srcImage.getHeight()) || (destImage.getXY0() != srcImage.getXY0()) ) { std::ostringstream errStream; errStream << "src and dest images must have same size and xy0.";
    696 861c006b - throw LSST_EXCEPT(pexExcept::InvalidParameterException, errStream.str());
    ? ^^^^^^ ^
    694 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, errStream.str());
    ? ^^ ^ } // set the xy0 coords to 0,0 to make life easier SrcImageT srcImageCopy(srcImage, true); srcImageCopy.setXY0(0, 0); destImage.setXY0(0, 0);
    703 861c006b - afwGeom::Extent2D cLocal = afwGeom::Extent2D(centerPixel) - afwGeom::Extent2D(srcImage.getXY0());
    ? ^^^
    701 7edb421a + afwGeom::Extent2D cLocal = afwGeom::Extent2D(centerPosition) - afwGeom::Extent2D(srcImage.getXY0());
    ? ++ ^^^^
    705 861c006b - // for the affine transform, the centerPixel will not only get sheared, but also
    ? ^^^
    703 7edb421a + // for the affine transform, the centerPosition will not only get sheared, but also
    ? ++ ^^^^ // moved slightly. So we'll include a translation to move it back by an amount
    707 861c006b - // centerPixel - translatedCenterPixel
    ? ^^^ ^^^
    705 7edb421a + // centerPosition - translatedCenterPosition
    ? ++ ^^^^ ++ ^^^^ afwGeom::AffineTransform affTran(linearTransform, cLocal - linearTransform(cLocal)); // now warp #if 0 static float t = 0.0; float t_before = 1.0*clock()/CLOCKS_PER_SEC; int n = warpImage(destImage, srcImageCopy, affTran, control, padValue); float t_after = 1.0*clock()/CLOCKS_PER_SEC; float dt = t_after - t_before; t += dt; std::cout < int afwMath::warpCenteredImage( DestImageT &destImage, SrcImageT const &srcImage, afwMath::SeparableKernel &warpingKernel, afwGeom::LinearTransform const &linearTransform,
    736 fac833c8 - afwGeom::Point2D const ¢erPixel,
    ? ^^^
    734 7edb421a + afwGeom::Point2D const ¢erPosition,
    ? ++ ^^^^ int const interpLength, typename DestImageT::SinglePixel padValue, lsst::afw::gpu::DevicePreference devPref ) { afwMath::WarpingControl control(warpingKernel, interpLength, devPref);
    742 fac833c8 - return warpCenteredImage(destImage, srcImage, linearTransform, centerPixel, control, padValue);
    ? ^^^
    740 7edb421a + return warpCenteredImage(destImage, srcImage, linearTransform, centerPosition, control, padValue);
    ? ++ ^^^^ } // // Explicit instantiations // /// \cond // may need to omit default params for EXPOSURE -- original code did that and it worked #define EXPOSURE(PIXTYPE) afwImage::Exposure #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage #define IMAGE(PIXTYPE) afwImage::Image #define NL /* */ #define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT) \ template int afwMath::warpCenteredImage( \ IMAGE(DESTIMAGEPIXELT) &destImage, \ IMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwGeom::LinearTransform const &linearTransform, \
    761 fac833c8 - afwGeom::Point2D const ¢erPixel, \
    ? ^^^
    759 7edb421a + afwGeom::Point2D const ¢erPosition, \
    ? ++ ^^^^ afwMath::WarpingControl const &control, \ IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \ template int afwMath::warpCenteredImage( \ MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \ MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwGeom::LinearTransform const &linearTransform, \
    768 fac833c8 - afwGeom::Point2D const ¢erPixel, \
    ? ^^^
    766 7edb421a + afwGeom::Point2D const ¢erPosition, \
    ? ++ ^^^^ afwMath::WarpingControl const &control, \ MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \ template int afwMath::warpCenteredImage( \ IMAGE(DESTIMAGEPIXELT) &destImage, \ IMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwMath::SeparableKernel &warpingKernel, \ afwGeom::LinearTransform const &linearTransform, \
    776 8a049406 - afwGeom::Point2D const ¢erPixel, \
    ? ^^^
    774 7edb421a + afwGeom::Point2D const ¢erPosition, \
    ? ++ ^^^^ int const interpLength, \ IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue, \ lsst::afw::gpu::DevicePreference devPref); NL \ template int afwMath::warpCenteredImage( \ MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \ MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwMath::SeparableKernel &warpingKernel, \ afwGeom::LinearTransform const &linearTransform, \
    785 8a049406 - afwGeom::Point2D const ¢erPixel, \
    ? ^^^
    783 7edb421a + afwGeom::Point2D const ¢erPosition, \
    ? ++ ^^^^ int const interpLength, \ MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue, \ lsst::afw::gpu::DevicePreference devPref); NL \ template int afwMath::warpImage( \ IMAGE(DESTIMAGEPIXELT) &destImage, \ IMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwGeom::AffineTransform const &affineTransform, \ afwMath::WarpingControl const &control, \ IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \ template int afwMath::warpImage( \ MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \ MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwGeom::AffineTransform const &affineTransform, \ afwMath::WarpingControl const &control, \ MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \ template int afwMath::warpImage( \ IMAGE(DESTIMAGEPIXELT) &destImage, \ IMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwMath::SeparableKernel &warpingKernel, \ afwGeom::AffineTransform const &affineTransform, \ int const interpLength, \ IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue, \ lsst::afw::gpu::DevicePreference devPref); NL \ template int afwMath::warpImage( \ MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \ MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwMath::SeparableKernel &warpingKernel, \ afwGeom::AffineTransform const &affineTransform, \ int const interpLength, \ MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue, \ lsst::afw::gpu::DevicePreference devPref); NL \ template int afwMath::warpImage( \ IMAGE(DESTIMAGEPIXELT) &destImage, \ afwImage::Wcs const &destWcs, \ IMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwImage::Wcs const &srcWcs, \ afwMath::WarpingControl const &control, \ IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \ template int afwMath::warpImage( \ MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \ afwImage::Wcs const &destWcs, \ MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwImage::Wcs const &srcWcs, \ afwMath::WarpingControl const &control, \ MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \ template int afwMath::warpImage( \ IMAGE(DESTIMAGEPIXELT) &destImage, \ afwImage::Wcs const &destWcs, \ IMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwImage::Wcs const &srcWcs, \ afwMath::SeparableKernel &warpingKernel, \ int const interpLength, \ IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue, \ lsst::afw::gpu::DevicePreference devPref); NL \ template int afwMath::warpImage( \ MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \ afwImage::Wcs const &destWcs, \ MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \ afwImage::Wcs const &srcWcs, \ afwMath::SeparableKernel &warpingKernel, \ int const interpLength, \ MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue, \ lsst::afw::gpu::DevicePreference devPref); NL \ template int afwMath::warpExposure( \ EXPOSURE(DESTIMAGEPIXELT) &destExposure, \ EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, \ afwMath::WarpingControl const &control,\ EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue); NL \ template int afwMath::warpExposure( \ EXPOSURE(DESTIMAGEPIXELT) &destExposure, \ EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, \ afwMath::SeparableKernel &warpingKernel, \ int const interpLength, \ EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue, \ lsst::afw::gpu::DevicePreference devPref); INSTANTIATE(double, double) INSTANTIATE(double, float) INSTANTIATE(double, int) INSTANTIATE(double, boost::uint16_t) INSTANTIATE(float, float) INSTANTIATE(float, int) INSTANTIATE(float, boost::uint16_t) INSTANTIATE(int, int) INSTANTIATE(boost::uint16_t, boost::uint16_t) /// \endcond

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    068759b9

    commit 068759b9de5ac7caee50d816e7ff6d2c468b4867
    Author: rowen 
    Date:   Mon Sep 28 21:26:58 2009 +0000
    
        Changed Kernel's PixelT to Pixel and PtrT to Ptr
        Added Kernel::ConstPtr
        Renamed KernelList specializations to remove final D (except KernelList itself,
        alas, because I could not make that work).
        Renamed some math .i files to the proper convention.
    

    7d6d57d5

    commit 7d6d57d5591fd71bc9f1e31cc0a6dc0f660319eb
    Author: Kresimir Cosic 
    Date:   Fri Mar 23 03:02:07 2012 +0100
    
        Cleaned up log messages, and other minor improvements.
    

    861c006b

    commit 861c006bab2e333a2742d700148035c1f3980161
    Author: Steven Bickerton 
    Date:   Thu Jan 5 14:14:06 2012 -0500
    
        centered warp working
    

    8f6195b0

    commit 8f6195b059b8c0f4392157b2cdc6a60df8894eaa
    Author: Kresimir Cosic 
    Date:   Sat Mar 3 10:38:32 2012 +0100
    
        Almost compiles
    

    5a91bf50

    commit 5a91bf5078c51f55f02336271bf6ad2bae2347d2
    Author: Kendrick Smith 
    Date:   Thu Jan 10 17:00:43 2013 -0500
    
        change some tabs to spaces
    

    84d4fa7d

    commit 84d4fa7def01e40f6674bb7ebd2eca93cd7b2741
    Merge: 19ed381 846aff9
    Author: rowen 
    Date:   Thu May 14 00:07:00 2009 +0000
    
        Implemented warpImage, including unit tests.
        Note:
        - The new unit tests show some disagreement with swarp around bad columns;
          this was masked by bad pixels in the MaskedImage tests.
        - Edge pixels have value (NaN, EDGE, infinity), based on ticket #806 and as implemented by new
          edgePixel function. This is a change from the trunk, so I prefer to hold off merging
          this ticket to the trunk until after DC3a. (If necessary we can hack the edgePixel method
          to match the old behavior, but I would prefer to wait if we can.)
          Hence it is probably not safe to merge to the trunk until after DC3a.
        - The convolve functions have not yet been modified to use the new edge pixel function;
          (ticket #806); this will involve removing the edge bit mask argument.
    

    c31ebcf9

    commit c31ebcf91bbcbc4de7a046a83af1ac3f3da22545
    Merge: 46325ba 8e1872d
    Author: Kresimir Cosic 
    Date:   Sat Mar 3 10:10:28 2012 +0100
    
        Fixed conflicts, adapted to changes
    

    00ce5756

    commit 00ce575662c509aecfdb39f8b73813a7fb362b85
    Author: Russell Owen 
    Date:   Mon Oct 8 16:46:08 2012 -0700
    
        Done
    

    8a049406

    commit 8a0494065e210e37d4f92d61b38f9d126372b7eb
    Author: Russell Owen 
    Date:   Wed Jun 27 17:09:10 2012 -0700
    
        Preparatory work to support warping the mask plane with a different kernel (e.g. bilinear):
         * Added a WarpingControl object that allows specifying a separate mask kernel
         * Added getCacheSize method to Kernel to support WarpingControl
         * Added new versions of the various warping functions that support this control object,
           and modified the old ones to internally make a control object
         * Moved SrcPosFunctor to its own header file and moved the AffineTransform version there,
           to keep company with the base and WCS versions and make everything easier to find.
    

    fac833c8

    commit fac833c87de064a4149664a51d8f5a8269c5a88d
    Author: Russell Owen 
    Date:   Fri Jun 29 14:37:28 2012 -0700
    
        Add new version of warpCenteredImage that uses WarpingControl and modified the old version to call it.
        Modified examples to use the new warping API. That only leaves the GPU example and tests
        which I'm reluctant to test without a GPU.
    

    efc19368

    commit efc19368d828dca9b8df8ae53586503a78887165
    Author: Russell Owen 
    Date:   Mon Jan 9 15:29:56 2012 -0800
    
        Move warpImage's doc header to the correct location.
        Remove tabs from examples/warpWithTransform.py
    

    Commits in /Users/nate/repos_lsst/afw/

    624db730

    commit 624db730b18aee1cfa2bed9d4b6c64a67da00a26
    Author: Steven Bickerton 
    Date:   Tue Feb 18 18:24:47 2014 +0900
    
        renamed SrcPosFunctor -> PositionFunctor
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    7edb421a

    commit 7edb421a3873253a40cbdd4600c0ab25c47ba88a
    Author: Steven Bickerton 
    Date:   Mon Feb 17 15:50:18 2014 +0900
    
        variable centerPixel -> centerPosition.  Use 'position' in comments.
    

    Return to list

    include/lsst/afw/cameraGeom/Detector.h

    Diff:

                    /* 
                     * LSST Data Management System
    
    3 a6d55f08 - * Copyright 2008, 2009, 2010 LSST Corporation.
    ? ------------ ^
    3 465c0d6c + * Copyright 2014 LSST Corporation.
    ? ^ * * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the LSST License Statement and * the GNU General Public License along with this program. If not, * see . */ #if !defined(LSST_AFW_CAMERAGEOM_DETECTOR_H) #define LSST_AFW_CAMERAGEOM_DETECTOR_H #include
    27 5caed4f7 + #include
    27 ac97fc48 - #include "boost/weak_ptr.hpp"
    28 ac97fc48 - #include
    #include "lsst/base.h"
    30 3b753c09 - #include "lsst/daf/base/Citizen.h"
    31 60edffcc - #include "lsst/afw/geom.h"
    29 6f5ea58d + #include "lsst/afw/geom/TransformMap.h"
    ? +++++++++++++
    32 2ebad60d - #include "lsst/afw/image/Defect.h"
    ? ^^ ^ ^^ ^^^
    30 5046e7f3 + #include "lsst/afw/table/AmpInfo.h"
    ? ^ ^^ ^^^^^ ^
    33 60edffcc - #include "lsst/afw/image/Utils.h"
    34 60edffcc - #include "lsst/afw/cameraGeom/Id.h"
    ? ^^
    31 1aa18059 + #include "lsst/afw/cameraGeom/CameraSys.h"
    ? ^^^^^^^^^
    32 dabee87e + #include "lsst/afw/cameraGeom/CameraPoint.h"
    #include "lsst/afw/cameraGeom/Orientation.h"
    37 e88ff0cd - #include "lsst/afw/cameraGeom/FpPoint.h"
    38 9cee260a -
    39 60edffcc - /**
    40 60edffcc - * @file
    41 60edffcc - *
    42 60edffcc - * Describe the physical layout of pixels in the focal plane
    43 60edffcc - */
    namespace lsst { namespace afw { namespace cameraGeom {
    38 ac97fc48 +
    47 9cee260a -
    48 9a0b3ed0 - class Distortion;
    49 9a0b3ed0 -
    /**
    51 60edffcc - * Describe a detector (e.g. a CCD)
    40 3b7632d5 + * Type of imaging detector
    */
    42 3b7632d5 + enum DetectorType {
    43 3b7632d5 + SCIENCE,
    44 3b7632d5 + FOCUS,
    45 3b7632d5 + GUIDER,
    46 3b7632d5 + WAVEFRONT,
    47 3b7632d5 + };
    48 3b7632d5 +
    49 3b7632d5 +
    50 3b7632d5 + /**
    51 3b7632d5 + * Information about a CCD or other imaging detector
    52 3b7632d5 + *
    53 3d477d32 + * Supports conversion of CameraPoint between FOCAL_PLANE and pixel-based coordinate systems.
    54 3d477d32 + * Also an iterator over amplifiers (in C++ use begin(), end(), in Python use "for amplifier in detector").
    55 4384a0a2 + *
    56 18439e6c + * @todo: this would probably be a bit more robust if it used a ConstAmpInfoCatalog
    57 18439e6c + * (a catalog with const records) but I don't think const catalogs really work yet;
    58 18439e6c + * for instance it is not possible to construct one from a non-const catalog,
    59 18439e6c + * so I don't know how to construct one.
    60 18439e6c + *
    61 5046e7f3 + * @note: code definitions use lsst::afw::table:: instead of table:: because the latter confused swig
    62 44c74a49 + * when I tried it. This is a known issue: ticket #2461.
    63 3b7632d5 + */
    53 18d5e213 - class Detector
    ? ----
    64 465c0d6c + class Detector {
    ? ++
    54 e9d5e2b6 - : public lsst::daf::base::Citizen
    55 18d5e213 - #if !defined(SWIG)
    56 e9d5e2b6 - , public boost::enable_shared_from_this
    65 dabee87e + public:
    66 465c0d6c + /**
    67 465c0d6c + * Make a Detector
    68 465c0d6c + *
    69 3b7632d5 + * @warning
    70 3b7632d5 + * * The keys for the detector-specific coordinate systems in the transform registry
    71 3b7632d5 + * must include the detector name (even though this is redundant).
    72 e6a90084 + *
    73 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if:
    74 e6a90084 + * - any amplifier names are not unique
    75 e6a90084 + * - any CamerSys in transformMap has a detector name other than "" or this detector's name
    76 465c0d6c + */
    77 465c0d6c + explicit Detector(
    78 3b7632d5 + std::string const &name, ///< name of detector's location in the camera
    79 d1426bf7 + int id, ///< detector integer ID; used as keys in some tables
    80 3b7632d5 + DetectorType type, ///< type of detector
    81 3b7632d5 + std::string const &serial, ///< serial "number" that identifies the physical detector
    82 5caed4f7 + geom::Box2I const &bbox, ///< bounding box
    83 18439e6c + lsst::afw::table::AmpInfoCatalog const &InfoCatalog, ///< catalog of amplifier information
    84 4384a0a2 + Orientation const &orientation, ///< detector position and orientation in focal plane
    85 5046e7f3 + geom::Extent2D const &pixelSize, ///< pixel size (mm)
    86 dab65f42 + CameraTransformMap::Transforms const &transforms ///< map of
    87 dab65f42 + ///< CameraSys: lsst::afw::geom::XYTransform, where each transform's "forwardTransform" method
    88 dab65f42 + ///< transforms from PIXELS to the specified camera system
    89 d2d7f999 + );
    90 ac97fc48 +
    91 465c0d6c + ~Detector() {}
    92 20ea8e44 +
    93 465c0d6c + /** Get the detector name */
    94 5caed4f7 + std::string getName() const { return _name; }
    95 e60c1c57 +
    96 d1426bf7 + /** Get the detector ID */
    97 d1426bf7 + int getId() const { return _id; }
    98 d1426bf7 +
    99 3b7632d5 + DetectorType getType() const { return _type; }
    100 3b7632d5 +
    101 e60c1c57 + /** Get the detector serial "number" */
    102 5caed4f7 + std::string getSerial() const { return _serial; }
    103 5caed4f7 +
    104 5caed4f7 + /** Get the bounding box */
    105 5caed4f7 + lsst::afw::geom::Box2I getBBox() const { return _bbox; }
    106 5caed4f7 +
    107 5caed4f7 + /** Get the corners of the detector in the specified coordinate system */
    108 5caed4f7 + std::vector getCorners(CameraSys const &cameraSys) const;
    109 3754257c +
    110 03b91f22 + /** Get the corners of the detector in the specified coordinate system prefix */
    111 03b91f22 + std::vector getCorners(CameraSysPrefix const &cameraSysPrefix) const;
    112 03b91f22 +
    113 03b91f22 + /** Get the center of the detector in the specified coordinate system */
    114 03b91f22 + CameraPoint getCenter(CameraSys const &cameraSys) const;
    115 03b91f22 +
    116 03b91f22 + /** Get the center of the detector in the specified coordinate system prefix */
    117 03b91f22 + CameraPoint getCenter(CameraSysPrefix const &cameraSysPrefix) const;
    118 03b91f22 +
    119 5046e7f3 + /** Get the amplifier information catalog */
    120 18439e6c + lsst::afw::table::AmpInfoCatalog const getAmpInfoCatalog() const { return _ampInfoCatalog; }
    121 5046e7f3 +
    122 3754257c + /** Get detector's orientation in the focal plane */
    123 3754257c + Orientation const getOrientation() const { return _orientation; }
    124 3754257c +
    125 5046e7f3 + /** Get size of pixel along (mm) */
    126 5caed4f7 + geom::Extent2D getPixelSize() const { return _pixelSize; }
    127 ac97fc48 +
    128 465c0d6c + /** Get the transform registry */
    129 6f5ea58d + CameraTransformMap const getTransformMap() const { return _transformMap; }
    130 4384a0a2 +
    131 4384a0a2 + /** Get iterator to beginning of amplifier list */
    132 18439e6c + lsst::afw::table::AmpInfoCatalog::const_iterator begin() const { return _ampInfoCatalog.begin(); }
    133 4384a0a2 +
    134 4384a0a2 + /** Get iterator to end of amplifier list */
    135 18439e6c + lsst::afw::table::AmpInfoCatalog::const_iterator end() const { return _ampInfoCatalog.end(); }
    136 4384a0a2 +
    137 4384a0a2 + /**
    138 4384a0a2 + * Get the amplifier specified by index
    139 4384a0a2 + *
    140 5046e7f3 + * @throw std::out_of_range) if index is out of range
    141 4384a0a2 + */
    142 47d30d84 + lsst::afw::table::AmpInfoRecord const & operator[](size_t i) const { return _ampInfoCatalog.at(i); }
    143 4384a0a2 +
    144 4384a0a2 + /**
    145 4384a0a2 + * Get the amplifier specified by name
    146 4384a0a2 + *
    147 21597d88 + * @throw lst::pex::exceptions::InvalidParameterError if no such amplifier
    148 4384a0a2 + */
    149 47d30d84 + lsst::afw::table::AmpInfoRecord const & operator[](std::string const &name) const;
    150 4384a0a2 +
    151 3d477d32 + /**
    152 3d477d32 + * Get number of amplifiers. Renamed to __len__ in Python.
    153 3d477d32 + */
    154 5046e7f3 + size_t size() const {return _ampInfoCatalog.size(); }
    155 dabee87e +
    156 dab65f42 + /** Does the specified CameraSys exist in the transform registry */
    157 dab65f42 + bool hasTransform(CameraSys const &cameraSys) const;
    158 dab65f42 +
    159 dab65f42 + /** Does the specified CameraSysPrefix exist in the transform registry */
    160 dab65f42 + bool hasTransform(CameraSysPrefix const &cameraSysPrefix) const;
    161 dab65f42 +
    162 dab65f42 + /**
    163 dab65f42 + * Get an XYTransform that transforms from cameraSys to the native system in the forward direction
    164 dab65f42 + *
    165 dab65f42 + * @param[in] cameraSys camera coordinate system
    166 dab65f42 + * @return a shared_ptr to an lsst::afw::XYTransform
    167 dab65f42 + *
    168 dab65f42 + * @throw pexExcept::InvalidParameterError if coordSys is unknown
    169 dab65f42 + */
    170 dab65f42 + CONST_PTR(afw::geom::XYTransform) getTransform(CameraSys const &cameraSys) const;
    171 dab65f42 +
    172 dab65f42 + /**
    173 dab65f42 + * Get an XYTransform that transforms from cameraSysPrefix to the native system in the forward direction
    174 dab65f42 + *
    175 dab65f42 + * @param[in] cameraSysPrefix camera coordinate system prefix
    176 dab65f42 + * @return a shared_ptr to an lsst::afw::geom::XYTransform
    177 dab65f42 + *
    178 dab65f42 + * @throw pexExcept::InvalidParameterError if coordSys is unknown
    179 dab65f42 + */
    180 dab65f42 + CONST_PTR(afw::geom::XYTransform) getTransform(CameraSysPrefix const &cameraSysPrefix) const;
    181 dab65f42 +
    182 dabee87e + /**
    183 17788019 + * Make a CameraPoint from a point and a camera system
    184 47d30d84 + *
    185 47d30d84 + * @note the CameraSysPrefix version needs the detector name, which is why this is not static.
    186 dabee87e + */
    187 dabee87e + CameraPoint makeCameraPoint(
    188 dabee87e + geom::Point2D point, ///< 2-d point
    189 17788019 + CameraSys cameraSys ///< coordinate system
    190 e60c1c57 + ) const {
    191 17788019 + return CameraPoint(point, cameraSys);
    192 17788019 + }
    193 17788019 +
    194 17788019 + /**
    195 17788019 + * Make a CameraPoint from a point and a camera system prefix
    196 17788019 + */
    197 17788019 + CameraPoint makeCameraPoint(
    198 17788019 + geom::Point2D point, ///< 2-d point
    199 17788019 + CameraSysPrefix cameraSysPrefix ///< coordinate system prefix
    200 17788019 + ) const {
    201 17788019 + return CameraPoint(point, makeCameraSys(cameraSysPrefix));
    202 17788019 + }
    203 17788019 +
    204 17788019 + /**
    205 17788019 + * Get a coordinate system from a coordinate system (return input unchanged and untested)
    206 47d30d84 + *
    207 47d30d84 + * @note the CameraSysPrefix version needs the detector name, which is why this is not static.
    208 17788019 + */
    209 17788019 + CameraSys const makeCameraSys(CameraSys const &cameraSys) const { return cameraSys; }
    210 17788019 +
    211 17788019 + /**
    212 17788019 + * Get a coordinate system from a detector system prefix (add detector name)
    213 17788019 + */
    214 17788019 + CameraSys const makeCameraSys(CameraSysPrefix const &cameraSysPrefix) const {
    215 17788019 + return CameraSys(cameraSysPrefix.getSysName(), _name);
    216 dabee87e + }
    217 9a0b3ed0 +
    218 5caed4f7 + /**
    219 5caed4f7 + * Convert a CameraPoint from one coordinate system to another
    220 5caed4f7 + *
    221 21597d88 + * @throw pexExcept::InvalidParameterError if from or to coordinate system is unknown
    222 5caed4f7 + */
    223 5caed4f7 + CameraPoint transform(
    224 5caed4f7 + CameraPoint const &fromCameraPoint, ///< camera point to transform
    225 5caed4f7 + CameraSys const &toSys ///< coordinate system to which to transform
    226 5caed4f7 + ) const {
    227 5caed4f7 + return CameraPoint(
    228 5caed4f7 + _transformMap.transform(fromCameraPoint.getPoint(), fromCameraPoint.getCameraSys(), toSys),
    229 5caed4f7 + toSys);
    230 5caed4f7 + }
    231 5caed4f7 +
    232 5caed4f7 + /**
    233 5caed4f7 + * Convert a CameraPoint from one coordinate system to a coordinate system prefix
    234 5caed4f7 + *
    235 5caed4f7 + * The coordinate system prefix is filled in with this detector's name
    236 5caed4f7 + *
    237 21597d88 + * @throw pexExcept::InvalidParameterError if from or to coordinate system is unknown
    238 5caed4f7 + */
    239 5caed4f7 + CameraPoint transform(
    240 5caed4f7 + CameraPoint const &fromCameraPoint, ///< camera point to transform
    241 5caed4f7 + CameraSysPrefix const &toSys ///< coordinate system prefix to which to transform
    242 5caed4f7 + ) const {
    243 5caed4f7 + return transform(fromCameraPoint, makeCameraSys(toSys));
    244 5caed4f7 + }
    245 5caed4f7 +
    246 60edffcc + private:
    247 18439e6c + typedef boost::unordered_map _AmpInfoMap;
    248 e6a90084 + /**
    249 e6a90084 + * Finish constructing this object
    250 e6a90084 + *
    251 5046e7f3 + * Set _ampNameIterMap from _ampInfoCatalog
    252 e6a90084 + * Check detector name in the CoordSys in the transform registry
    253 e6a90084 + *
    254 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if:
    255 e6a90084 + * - any amplifier names are not unique
    256 e6a90084 + * - any CamerSys in transformMap has a detector name other than "" or this detector's name
    257 e6a90084 + */
    258 e6a90084 + void _init();
    259 4384a0a2 +
    260 3b7632d5 + std::string _name; ///< name of detector's location in the camera
    261 d1426bf7 + int _id; ///< detector numeric ID
    262 5046e7f3 + DetectorType _type; ///< type of detectorsize_t
    263 3b7632d5 + std::string _serial; ///< serial "number" that identifies the physical detector
    264 5caed4f7 + geom::Box2I _bbox; ///< bounding box
    265 18439e6c + table::AmpInfoCatalog _ampInfoCatalog; ///< list of amplifier data
    266 5046e7f3 + _AmpInfoMap _ampNameIterMap; ///< map of amplifier name: catalog iterator
    267 4384a0a2 + Orientation _orientation; ///< position and orientation of detector in focal plane
    268 5046e7f3 + geom::Extent2D _pixelSize; ///< pixel size (mm)
    269 6f5ea58d + CameraTransformMap _transformMap; ///< registry of coordinate transforms
    270 dabee87e + };
    271 d95640da +
    272 60edffcc + }}}
    273 60edffcc +
    #endif
    58 18d5e213 - {
    59 60edffcc - public:
    60 85c4c76e - typedef boost::shared_ptr Ptr;
    61 85c4c76e - typedef boost::shared_ptr ConstPtr;
    62 85c4c76e -
    63 f846bf5f - explicit Detector(
    64 53f42b75 - Id id, ///< Detector's Id
    65 f846bf5f - bool hasTrimmablePixels=false, ///< true iff Detector has pixels that can be trimmed (e.g. a CCD)
    66 53f42b75 - double pixelSize=0.0 ///< Size of pixels, mm
    67 f846bf5f - ) :
    68 3b753c09 - lsst::daf::base::Citizen(typeid(this)),
    69 f846bf5f - _id(id), _isTrimmed(false), _allPixels(),
    70 6b9ab890 - _hasTrimmablePixels(hasTrimmablePixels), _pixelSize(pixelSize), _center(),
    71 9a0b3ed0 - _distortion(PTR(Distortion)()) // init as a null pointer
    72 f846bf5f - {
    73 ac97fc48 - _parent = boost::weak_ptr();
    74 ac97fc48 -
    75 f846bf5f - if (_hasTrimmablePixels) {
    76 f846bf5f - _trimmedAllPixels = _allPixels;
    77 f846bf5f - }
    78 60edffcc - }
    79 60edffcc - virtual ~Detector() {}
    80 60edffcc - /// Return the Detector's Id
    81 60edffcc - Id getId() const { return _id; }
    82 60edffcc -
    83 ac97fc48 - /// Return the detector's parent in the hierarchy
    84 ac97fc48 - ///
    85 ac97fc48 - /// If the parent is unknown or has been deleted, and empty Ptr is returned
    86 ac97fc48 - void setParent(Ptr parent) {
    87 ac97fc48 - _parent = boost::weak_ptr(parent);
    88 ac97fc48 - }
    89 ac97fc48 -
    90 ac97fc48 - /// Return the detector's parent in the hierarchy
    91 ac97fc48 - ///
    92 e2db5f35 - /// If the parent is unknown or has been deleted, an empty Ptr is returned
    93 ac97fc48 - Ptr getParent() const {
    94 ac97fc48 - return Ptr(_parent.lock());
    95 ac97fc48 - }
    96 ac97fc48 -
    97 20ea8e44 - /// Are two Detectors identical, in the sense that they have the same name
    98 20ea8e44 - bool operator==(Detector const& rhs ///< Detector to compare too
    99 20ea8e44 - ) const {
    100 20ea8e44 - return getId() == rhs.getId();
    101 20ea8e44 - }
    102 20ea8e44 -
    103 20ea8e44 - /// Is this less than rhs, based on comparing names
    104 20ea8e44 - bool operator<(Detector const& rhs ///< Detector to compare too
    105 20ea8e44 - ) const {
    106 20ea8e44 - return _id < rhs._id;
    107 20ea8e44 - }
    108 20ea8e44 -
    109 60edffcc - /// Has the bias/overclock been removed?
    110 f846bf5f - bool isTrimmed() const { return (_hasTrimmablePixels && _isTrimmed); }
    111 60edffcc - /// Set the trimmed status of this Detector
    112 60edffcc - virtual void setTrimmed(bool isTrimmed ///< True iff the bias/overclock have been removed
    113 60edffcc - ) {
    114 60edffcc - _isTrimmed = isTrimmed;
    115 60edffcc - }
    116 60edffcc -
    117 60edffcc - /// Set the pixel size in mm
    118 60edffcc - void setPixelSize(double pixelSize ///< Size of a pixel, mm
    119 60edffcc - ) { _pixelSize = pixelSize; }
    120 60edffcc - /// Return the pixel size, mm/pixel
    121 60edffcc - double getPixelSize() const { return _pixelSize; }
    122 60edffcc -
    123 e88ff0cd - virtual FpExtent getSize() const;
    124 60edffcc -
    125 60edffcc - /// Return Detector's total footprint
    126 9964091c - virtual lsst::afw::geom::Box2I& getAllPixels() {
    127 f846bf5f - return (_hasTrimmablePixels && _isTrimmed) ? _trimmedAllPixels : _allPixels;
    128 60edffcc - }
    129 2ebad60d - /// Return Detector's total footprint
    130 9964091c - virtual lsst::afw::geom::Box2I const& getAllPixels() const {
    131 60edffcc - return getAllPixels(_isTrimmed);
    132 60edffcc - }
    133 2ebad60d - /// Return Detector's total footprint
    134 9964091c - virtual lsst::afw::geom::Box2I const& getAllPixels(bool isTrimmed ///< Has the bias/overclock have been removed?
    135 7ffd25c1 - ) const {
    136 f846bf5f - return (_hasTrimmablePixels && isTrimmed) ? _trimmedAllPixels : _allPixels;
    137 60edffcc - }
    138 e193729a - /// Return the Detector's footprint without applying any rotations that were used when inserting
    139 e193729a - /// it into its parent (e.g. Raft)
    140 a8f86353 - virtual lsst::afw::geom::BoxI getAllPixelsNoRotation(bool isTrimmed=true) const;
    141 e3c14206 -
    142 e3c14206 - /// Get the center pixel of the detector
    143 e3c14206 - geom::Point2D getCenterPixel() const;
    144 e3c14206 -
    145 60edffcc - //
    146 60edffcc - // Geometry of Detector --- i.e. mm not pixels
    147 60edffcc - //
    148 4b6acf34 - virtual void setOrientation(Orientation const& orientation);
    149 78652121 - /// Return the Detector's Orientation
    150 ffc2778f - Orientation const& getOrientation() const { return _orientation;}
    151 78652121 -
    152 78652121 - /// Set the Detector's center
    153 e88ff0cd - virtual void setCenter(FpPoint const& center) { _center = center; }
    154 6b9ab890 -
    155 e3c14206 - /// Set the Detector's center relative to the old center.
    156 e3c14206 - virtual void shiftCenter(FpExtent const & offset) { _center = FpPoint(_center.getMm() + offset.getMm()); }
    157 e3c14206 -
    158 78652121 - /// Return the Detector's center
    159 e88ff0cd - FpPoint getCenter() const { return _center; }
    160 61d4e3d9 -
    161 61d4e3d9 - /// Translate between physical positions in mm to pixels
    162 e88ff0cd - virtual lsst::afw::geom::Point2D getPixelFromPosition(FpPoint const& pos) const;
    163 6a1d1266 - virtual FpPoint getPositionFromPixel(lsst::afw::geom::Point2D const& pix) const;
    164 61d4e3d9 -
    165 61d4e3d9 - /// Local linearizations of the preceding coordinate-changing routines
    166 61d4e3d9 - virtual lsst::afw::geom::AffineTransform linearizePixelFromPosition(FpPoint const &pos) const;
    167 61d4e3d9 - virtual lsst::afw::geom::AffineTransform linearizePositionFromPixel(lsst::afw::geom::Point2D const &pix) const;
    168 ffc2778f -
    169 1ac3f936 - virtual void shift(int dx, int dy);
    170 2ebad60d - //
    171 2ebad60d - // Defects within this Detector
    172 2ebad60d - //
    173 2ebad60d - /// Set the Detector's Defect list
    174 c5e868b7 - virtual void setDefects(
    175 9964091c - std::vector > const& defects ///< Defects in this detector
    176 c5e868b7 - ) {
    177 2ebad60d - _defects = defects;
    178 2ebad60d - }
    179 2ebad60d - /// Get the Detector's Defect list
    180 9964091c - std::vector > const& getDefects() const { return _defects; }
    181 9964091c - std::vector >& getDefects() { return _defects; }
    182 9a0b3ed0 -
    183 f3c9341f - void setDistortion(CONST_PTR(Distortion) distortion);
    184 f3c9341f - CONST_PTR(Distortion) getDistortion() const;
    185 9a0b3ed0 -
    186 9a0b3ed0 -
    187 60edffcc - protected:
    188 ac97fc48 - /// Return a shared pointer to this
    189 ac97fc48 - Ptr getThisPtr() {
    190 ac97fc48 - return shared_from_this();
    191 ac97fc48 - }
    192 ac97fc48 -
    193 9964091c - lsst::afw::geom::Box2I& getAllTrimmedPixels() {
    194 f846bf5f - return _hasTrimmablePixels ? _trimmedAllPixels : _allPixels;
    195 60edffcc - }
    196 9a0b3ed0 -
    197 9a0b3ed0 -
    198 9a0b3ed0 -
    199 60edffcc - private:
    200 60edffcc - Id _id;
    201 60edffcc - bool _isTrimmed; // Have all the bias/overclock regions been trimmed?
    202 9964091c - lsst::afw::geom::Box2I _allPixels; // Bounding box of all the Detector's pixels
    203 f846bf5f - bool _hasTrimmablePixels; // true iff Detector has pixels that can be trimmed (e.g. a CCD)
    204 60edffcc - double _pixelSize; // Size of a pixel in mm
    205 ffc2778f - Orientation _orientation; // orientation of this Detector
    206 e88ff0cd - FpPoint _center; // position of _centerPixel (mm)
    207 9964091c - lsst::afw::geom::Extent2D _size; // Size in mm of this Detector
    208 9964091c - lsst::afw::geom::Box2I _trimmedAllPixels; // Bounding box of all the Detector's pixels after bias trimming
    209 ac97fc48 - boost::weak_ptr _parent; // Parent Detector in the hierarchy
    210 2ebad60d -
    211 9964091c - std::vector _defects; // Defects in this detector
    212 9a0b3ed0 -
    213 f3c9341f - CONST_PTR(Distortion) _distortion;
    214 60edffcc - };
    215 60edffcc -
    216 4b6acf34 - namespace detail {
    217 20ea8e44 - template
    218 20ea8e44 - struct sortPtr :
    219 fccddbab - public std::binary_function {
    220 20ea8e44 - bool operator()(typename T::Ptr &lhs, typename T::Ptr const& rhs) const {
    221 20ea8e44 - return *lhs < *rhs;
    222 20ea8e44 - }
    223 20ea8e44 - };
    224 3f3d5e23 - /**
    225 3f3d5e23 - * Rotate a BBox about the center of some larger region by a multiple of 90 degrees
    226 06309dc2 - *
    227 06309dc2 - * If dimensions is nonzero, interpret it as the size of an image, and the initial bbox as a bbox in
    228 06309dc2 - * that image. Then rotate about the center of the image
    229 06309dc2 - *
    230 06309dc2 - * If dimensions is 0, rotate the bbox about its LLC
    231 3f3d5e23 - */
    232 9964091c - lsst::afw::geom::Box2I rotateBBoxBy90(
    233 9964091c - lsst::afw::geom::Box2I const& bbox, ///< the BBox to rotate
    234 7ffd25c1 - int n90, ///< number of 90-degree anti-clockwise turns to make
    235 9964091c - lsst::afw::geom::Extent2I const& dimensions ///< The size of the region wherein bbox dwells
    236 a8f86353 - );
    237 4b6acf34 - }
    238 d95640da -
    239 d95640da -
    240 d95640da - /**
    241 d95640da - * @brief DetectorXYTransform: converts an XYTransform in FP coordinate system to detector coords
    242 d95640da - *
    243 d95640da - * Given a "global" XYTransform in the focal plane coordinate system, this class implements the
    244 d95640da - * coordinate transformation necessary to get the same XYTransform in the coordinate system of an
    245 d95640da - * individual detector.
    246 d95640da - */
    247 d95640da - class DetectorXYTransform : public afw::geom::XYTransform
    248 d95640da - {
    249 d95640da - public:
    250 d95640da - DetectorXYTransform(CONST_PTR(afw::geom::XYTransform) fpTransform, CONST_PTR(Detector) detector);
    251 d95640da - virtual ~DetectorXYTransform() { }
    252 d95640da -
    253 d95640da - virtual PTR(afw::geom::XYTransform) clone() const;
    254 d95640da - virtual PTR(afw::geom::XYTransform) invert() const;
    255 d95640da - virtual Point2D forwardTransform(Point2D const &pixel) const;
    256 d95640da - virtual Point2D reverseTransform(Point2D const &pixel) const;
    257 d95640da - virtual AffineTransform linearizeForwardTransform(Point2D const &pixel) const;
    258 d95640da - virtual AffineTransform linearizeReverseTransform(Point2D const &pixel) const;
    259 d95640da -
    260 d95640da - protected:
    261 d95640da - CONST_PTR(XYTransform) _fpTransform;
    262 d95640da - CONST_PTR(Detector) _detector;
    263 d95640da - };
    264 d95640da -
    265 4b6acf34 -
    266 60edffcc - }}}
    267 60edffcc -
    268 60edffcc - #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9a0b3ed0

    commit 9a0b3ed09fa81b663487c75696e7198af0cf257d
    Author: bick 
    Date:   Fri Aug 26 23:03:09 2011 +0000
    
        #1753 (not yet working) distortion stuff initial check-in.
    

    20ea8e44

    commit 20ea8e447836046d5e9c15511e9221e2119dfa64
    Author: rhl 
    Date:   Wed Feb 10 21:34:03 2010 +0000
    
        Sort components by Id; #1168
    

    7ffd25c1

    commit 7ffd25c1b6fa71ec4641f4718d6eddc839f7a758
    Author: rhl 
    Date:   Sun Apr 4 15:59:56 2010 +0000
    
        Added support for amps being stored on disk in separate files
    

    18d5e213

    commit 18d5e213c7bc81d057e35f0ba9ceba05917e8ee9
    Author: rhl 
    Date:   Wed Apr 7 00:46:43 2010 +0000
    
        Add Detector to Exposure
    

    6a1d1266

    commit 6a1d126697a1ee97ea3c164eb061b3362aca8af3
    Author: Robert Lupton the Good 
    Date:   Sat Feb 18 18:04:52 2012 -0500
    
        virtual functions must be declared in the base class, not just the derived one
    

    61d4e3d9

    commit 61d4e3d9786f54bc560d5bd4e36fe08ca51c4d1d
    Author: Kendrick Smith 
    Date:   Wed Feb 6 16:09:29 2013 -0500
    
        add routines to linearize the pixel->FP coordinate change
    

    e2db5f35

    commit e2db5f350ff2de3f767262cf04f4aee513be725b
    Author: krughoff 
    Date:   Thu Nov 10 23:55:40 2011 +0000
    
        Final changes to geometry before merge
    

    c5e868b7

    commit c5e868b7b00ffc22fcb6941522b22a623b04e33a
    Author: rhl 
    Date:   Fri Jan 15 10:09:01 2010 +0000
    
        Added support for Defects.  N.b. Defect is a base class; the real Defect code is in meas/algorithms which needs to be updated to inherit from afwImage::Defect
    

    6b9ab890

    commit 6b9ab89018f35300a86e2e17ffd05895f9264480
    Author: Steven Bickerton 
    Date:   Sat Jan 28 22:25:49 2012 -0600
    
        added basic tests.  img distort not great, but working.
    

    ac97fc48

    commit ac97fc48802ae9a8b7333ddf8a8ab51bea064133
    Author: rhl 
    Date:   Tue Apr 6 22:03:14 2010 +0000
    
        Added Id.getIndex(); Detector.getParent()
    

    e9d5e2b6

    commit e9d5e2b6ba1e51182be40b60641ff992929a0bbe
    Author: Robert Lupton the Good 
    Date:   Mon Feb 27 12:14:44 2012 -0500
    
        Swig 2.0 seems to be OK with the Citizen
    

    a8f86353

    commit a8f86353b4d794d8e2accd0ce6950e72a06c3f66
    Merge: a128aac 246b6dd
    Author: dubcovsky 
    Date:   Thu Mar 31 20:50:37 2011 +0000
    
        #1556 trunk merged to ticket branch
    

    3f3d5e23

    commit 3f3d5e23184916da9caf2bbd21eaf87513bb099c
    Author: rhl 
    Date:   Thu Jun 3 18:12:24 2010 +0000
    
        Changes to make doxygen a little less unhappy
    

    fccddbab

    commit fccddbabb1a929463ba18c37488a204d4d6acf66
    Author: rhl 
    Date:   Fri Feb 19 17:32:31 2010 +0000
    
        Fix icc warnings, as per #1179
    

    1ac3f936

    commit 1ac3f9368c1453487cfea8334ba310c339552ede
    Author: rhl 
    Date:   Wed Jan 6 19:59:28 2010 +0000
    
        Initial version of Raft code
    

    78652121

    commit 78652121c24a3aeaddbbbeecdbced15c38140e08
    Author: rhl 
    Date:   Fri Jan 8 19:08:35 2010 +0000
    
        Get detector centres right
    

    f3c9341f

    commit f3c9341fa4bb1f322df3de025bb1aad936224ac0
    Author: Steven Bickerton 
    Date:   Thu Feb 2 10:33:55 2012 -0600
    
        continuing work on the master merge
    

    4b6acf34

    commit 4b6acf347c723a61081eb7211584ce7712372ddb
    Author: rhl 
    Date:   Wed Jan 13 06:32:59 2010 +0000
    
        Got rotation of detectors by 90n degrees (and non-square dataSecs) working
    

    e88ff0cd

    commit e88ff0cd6d8b7e3b4173c8fd71f33e78b407c782
    Author: Steven Bickerton 
    Date:   Tue Jan 31 10:02:20 2012 -0600
    
        split FpPosition to FpPoint/Extent.
    

    d95640da

    commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
    Author: Kendrick Smith 
    Date:   Tue Feb 19 23:44:14 2013 -0500
    
        move afw::image::XYTransform -> afw::geom::XYTransform
             afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
             afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
        
        wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom
    

    53f42b75

    commit 53f42b7570a1dc0914481f5557b0715606290286
    Author: rhl 
    Date:   Sun Jan 17 14:40:22 2010 +0000
    
        Make icc less unhappy; mostly unused variable and LsstImpl::toString not being virtual
    

    06309dc2

    commit 06309dc2c9dbc3abe69f66c040ae75a1950eee14
    Author: Russell Owen 
    Date:   Thu Jun 13 16:25:55 2013 -0700
    
        Fix the remaining build warning (for rotateBBoxBy90, which was due to prepending
        lsst::afw::cameraGeom to the name in the .cc file) and centralize the doxygen documentation
        for it in the .h file (the documentation was shared between the .cc and .h files
        and the former was more complete).
    

    e3c14206

    commit e3c14206282f922b11613a08ddf4fac57f4ca4a8
    Author: Jim Bosch 
    Date:   Thu Feb 28 15:41:36 2013 +0900
    
        Disable setting center pixel in cameraGeom.
        
        The parts of cameraGeom that are known to work - getPixelFromPosition and getPositionFromPixel - do not make use of the _centerPixel data member; instead they compute the center pixel directly from the bounding boxes.  That makes being able to set the center pixel a potention source of errors, as it seems to affect some operations but does not in fact modify the all-important coordinate transformations.  This change removes setCenterPixel and the _centerPixel data member, and instead implements getCenterPixel by computing the center pixel of the bounding box, just as getPixelFromPosition and getPositionFromPixel do.
        
        I have also removed methods that relied on the old, inconsistent definition of _centerPixel, including DetectorMosaic::findDetectorPixel, which purports to find the detector that contains a point in pixel coordinates.  At some level, that's clearly nonsensical, because e.g. all CCDs in a camera will have a (0,0) pixel.  I'm not sure it was used for anything other than circular unit tests.
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    3b753c09

    commit 3b753c09a2fa2a7f1bd340d31ea887c754ffe781
    Author: rhl 
    Date:   Sat Apr 17 23:58:26 2010 +0000
    
        Make Detector derive from Citizen.  N.b. this fact is hidden from Swig as it causes swig 1.3.36 to generate Wcs-to-Citizen casts in cameraGeom_wrap.cc;  this in turn requires more files to be included to compile.  I'd way that it was a swig bug
    

    60edffcc

    commit 60edffccd7fc85402e9e6f1c0e5fa0021f9af237
    Author: rhl 
    Date:   Tue Jan 5 22:24:46 2010 +0000
    
        Initial implementation of cameraGeom up to Ccd/Detector
    

    85c4c76e

    commit 85c4c76e09060f18e330cc23ba9f59d214b844d7
    Author: rhl 
    Date:   Wed Jan 6 23:40:06 2010 +0000
    
        Added DetectorLayout; misc
    

    2ebad60d

    commit 2ebad60ddfd2a217aa139655a0e6e7e578da48d2
    Author: rhl 
    Date:   Fri Jan 15 07:57:27 2010 +0000
    
        Started adding Defect support;  make Amp inherit from Detector
    

    f846bf5f

    commit f846bf5f70d586fbc1d57759baddd6182dbf4c6a
    Author: rhl 
    Date:   Thu Jan 7 14:14:46 2010 +0000
    
        Worked on camera geometry and building a Camera as an Raft of Rafts
    

    9cee260a

    commit 9cee260ab479f59cf80910271f615464bbe66e5c
    Author: Steven Bickerton 
    Date:   Thu Dec 22 19:18:55 2011 -0500
    
        additional work for 1753
    

    ffc2778f

    commit ffc2778fcf414a7bf95fdcb429cc5d14c8a079e6
    Author: rhl 
    Date:   Sat Jan 9 14:45:15 2010 +0000
    
        Got pixel -> position working.  Position -> pixel is still broken
    

    9964091c

    commit 9964091c98bc6b9daa98b6379ea1b22c6fa85e91
    Author: rowen 
    Date:   Wed Mar 16 23:04:33 2011 +0000
    
        I tried to eliminate doxygen warnings in afw 1556. I came pretty close. There are two known issues:
        - Doxygen has a bug that prevents documenting template specializations. There are two of these in
           src/geom/Extent.cc
           that I hide from Doxygen with a note and \cond BUG406027
        - src/coord/Coord.cc produces two Doxygen warnings that I've not been able to eliminate. I don't have any idea what is causing them.
        
        Unfortunately, fixing Doxygen warnings requires some cluttering up the the code, in particular spelling out namespaces in arguments.
        
        
        Other changes:
        - std::osstream operator<< functions in AffineTransform.h and LinearTransform.h were friend functions, but did not need to be. I changed this, partly because Doxygen was unhappy.
        - I removed all use of "namespace foo=lsst::..."  in header files.
        - I replaced daf::base:: with lsst::daf::base:: in some header files. I'm surprised the former worked; I've reported it as a bug against daf_base.
        
        BTW: this code fails on Mac OS X Leopard; the tests/footprintArray.cc fails to compile.
    

    e193729a

    commit e193729ad24e2b0d48b1abcd0ddb2aaad6ba4188
    Author: rhl 
    Date:   Wed Feb 23 12:27:29 2011 +0000
    
        Worked on cameraGeom; all pixel positions are now floating (to permit transfer of centroids to boresight coordinates)
    

    Commits in /Users/nate/repos_lsst/afw/

    9a0b3ed0

    commit 9a0b3ed09fa81b663487c75696e7198af0cf257d
    Author: bick 
    Date:   Fri Aug 26 23:03:09 2011 +0000
    
        #1753 (not yet working) distortion stuff initial check-in.
    

    20ea8e44

    commit 20ea8e447836046d5e9c15511e9221e2119dfa64
    Author: rhl 
    Date:   Wed Feb 10 21:34:03 2010 +0000
    
        Sort components by Id; #1168
    

    3b7632d5

    commit 3b7632d513621faf8a3357e5519e7504f2ccd4fd
    Author: Russell Owen 
    Date:   Mon Jan 27 17:03:04 2014 -0800
    
        Added DetectorType enum and fleshed out Detector
    

    465c0d6c

    commit 465c0d6c6c86fc81c101ad4aecfb7b0dee13afeb
    Author: Russell Owen 
    Date:   Fri Jan 24 18:08:12 2014 -0800
    
        Use CoordSys as the key in TransformRegistry.
        Applied Jim's idea of a separate class for detector-specific coordinate system prefixes.
        For now I have not gotten hashing to compile, so I commented it out and am using std::map.
    

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    dabee87e

    commit dabee87ebd82283629d6941dd0786857aea304ca
    Author: Russell Owen 
    Date:   Sat Jan 25 15:26:33 2014 -0800
    
        Removed old code and fixed many C++ errors in the new code.
    

    e6a90084

    commit e6a90084e77396fe175f998cf9c3dd13a175ff4f
    Author: Russell Owen 
    Date:   Fri Jan 31 11:11:19 2014 -0800
    
        Fixed Detector.convert's handling of CameraSysPrefix.
        Improved SWIG files, getting rename and ignore to work in most cases
        (TransformRegistry still needs %extend to handle operator[] for reasons I don't understand).
        Finished detector unit test.
    

    d1426bf7

    commit d1426bf78a5f78cf0d9487ac3fc83f75c66a01d1
    Author: Russell Owen 
    Date:   Mon Mar 10 14:28:23 2014 -0700
    
        Added id field to Detector and propagated the changes through to DetectorCollection.
    

    47d30d84

    commit 47d30d844a0771f579a125f7d2af3497c76f9420
    Author: Russell Owen 
    Date:   Fri Mar 7 16:18:26 2014 -0800
    
        I implemented most of Jim's C++ suggestions from his second C++ review.
        I also broke out most of the Orientation implementation into a separate .cc file.
    

    6f5ea58d

    commit 6f5ea58df69e1713505a44d25dbbd0e121bd6aff
    Author: Russell Owen 
    Date:   Tue Feb 18 11:25:54 2014 -0800
    
        Rename TransformRegistry to TransformMap and TransformMap to TransformMap::Transforms
    

    18439e6c

    commit 18439e6c1fd05dc7d44b17a6178ef0de5c1b7e38
    Author: Russell Owen 
    Date:   Fri Feb 14 09:30:39 2014 -0800
    
        Detector tests pass.
    

    ac97fc48

    commit ac97fc48802ae9a8b7333ddf8a8ab51bea064133
    Author: rhl 
    Date:   Tue Apr 6 22:03:14 2010 +0000
    
        Added Id.getIndex(); Detector.getParent()
    

    5046e7f3

    commit 5046e7f3f0a4f8591e21a396b1e1ee0dd205f659
    Author: Russell Owen 
    Date:   Thu Feb 13 17:35:58 2014 -0800
    
        Got the basics of AmpInfo catalogs working.
        However, I don't know how to SWIG-wrap ConstAmpInfoCatalog, and it looks messy,
        so I will try making Detector's constructor take a non-const catalog
        and copying that internally to a const catalog. (I should then test that
        changing the original catalog does not change the one inside Detector).
    

    44c74a49

    commit 44c74a49e5cbbf2ec64c2b868c64d116bd2c1779
    Author: Russell Owen 
    Date:   Tue Mar 11 09:52:15 2014 -0700
    
        Improve documentation for Detector.h
    

    3754257c

    commit 3754257cb567d226cff0e6bfa6750b2fd1a0986e
    Author: Russell Owen 
    Date:   Thu Jan 30 17:59:20 2014 -0800
    
        cameraGeomLib.i: %rename of Detector.size->__len__ was silently failing (and %ignore also silently failed),
        so use %extend and live with the duplicate.
        Added some missing getters to Detector.h.
        Minor updates to Detector unit test (it still need much more).
    

    03b91f22

    commit 03b91f2271b901654ac340375900e33df79d669c
    Author: Russell Owen 
    Date:   Mon Mar 3 13:17:43 2014 -0800
    
        Allow == and != comparisons of CameraSys and CameraSysPrefix instances (which always return False
        if the classes are different). The SWIG is a bit verbose, but it works.
        Test this change.
        Add Detector.getCenter(CameraSys) and a test for it.
    

    4384a0a2

    commit 4384a0a2406e91369beef236ede8a30bff0b122a
    Author: Russell Owen 
    Date:   Tue Jan 28 12:33:00 2014 -0800
    
        Detector: added missing accessors for amplifiers (including adding an internal unordered_map
        for fast access by name).
        Amplifier and RawAmplifier: marked methods const.
        TransformRegistry: switched to explicitly using boost::unordered_map.
    

    3d477d32

    commit 3d477d32c28c5b73a3b31aa42c9794a7fdcfcc68
    Author: Russell Owen 
    Date:   Thu Jan 30 17:14:39 2014 -0800
    
        Add CameraSys(CameraSysPrefix, detectorName) constructor to simplify constructing transform maps for Detector.
        Added a very preliminary unit test for Detector.
    

    5caed4f7

    commit 5caed4f7bfef8ecaf1daec5e793c09f9d0ca990a
    Author: Russell Owen 
    Date:   Wed Feb 19 17:51:36 2014 -0800
    
        Fixed a bug in the list version of TransformMap.transform
        Added a unit test for the above.
        Added bbox argument to Detector's constructor.
        Added getBBox and getCorners methods to Detector, and unit tests for same.
    

    dab65f42

    commit dab65f422ed168d8b81f8b23fad67b62dca8b506
    Author: Russell Owen 
    Date:   Thu Apr 2 14:03:20 2015 -0700
    
        Add hasTransform and getTransform to cameraGeom Detector
        
        Add overloaded member functions hasTransform and getTransform to cameraGeom Detector,
        which accept a CameraSys or a CameraSysPrefix. This greatly simplifies getting
        appropriate transforms from the detector's transform map, since one need not explicitly
        first generate a CameraSys for that detector.
        Added a test for the new functions to testDetector.py.
        Made a minor improvement to documentation in TransformMap.h
        
        Fix grammatical errors in two doc strings.
    

    60edffcc

    commit 60edffccd7fc85402e9e6f1c0e5fa0021f9af237
    Author: rhl 
    Date:   Tue Jan 5 22:24:46 2010 +0000
    
        Initial implementation of cameraGeom up to Ccd/Detector
    

    d95640da

    commit d95640daf1f951da4dea18c31f5259ae8ac1cb39
    Author: Kendrick Smith 
    Date:   Tue Feb 19 23:44:14 2013 -0500
    
        move afw::image::XYTransform -> afw::geom::XYTransform
             afw::image::XYTransformFromWcsPair -> afw::image::XYTransformFromWcsPair
             afw::image::DetectorXYTransform -> afw::cameraGeom::DetectorXYTransform
        
        wrap cameraGeom/Detector.cc in namespace lsst::afw::cameraGeom
    

    1aa18059

    commit 1aa180592875198f7c6202343ca999bafc5bdc4c
    Author: Russell Owen 
    Date:   Sat Jan 25 08:44:11 2014 -0800
    
        CameraSys now has two fields: sysName and detectorName. This avoids the need for Camera.convert
        to tease out the detector name. To avoid over-specializing TransformRegistry I templated it on key type.
    

    d2d7f999

    commit d2d7f9994b5c420d3941696c2381026557395de8
    Author: Russell Owen 
    Date:   Wed Jan 29 07:31:32 2014 -0800
    
        Fixes to cameraGeomLib and a start on a unit test for TransformRegistry.
        Next step: switch using lists of (CoordSys, XYTransform) to build XYTransform
        to using maps; SWIG knows how to wrap std::map, and the I/O might as well match the internals.
    

    e60c1c57

    commit e60c1c57f2d0957d5c0b15228ad3d3800bb8b45b
    Author: Russell Owen 
    Date:   Sun Jan 26 17:27:54 2014 -0800
    
        The C++ code compiles, but cameraGeom's SWIG files have not been updated
    

    17788019

    commit 177880194dbef837de5d2d6de9effe6e0420436e
    Author: Russell Owen 
    Date:   Fri Jan 31 14:35:52 2014 -0800
    
        Renamed Detector.getCameraSys to makeCameraSys, since that is more accurate.
        Added missing Detector.makeCameraPoint specialization.
        Added unit test for Detector.makeCameraPoint.
    

    Return to list

    python/lsst/afw/geom/geomLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
    
    5 a6d55f08 - * Copyright 2008, 2009, 2010 LSST Corporation.
    5 bba97267 + * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014 LSST Corporation.
    ? ++++++++++++++++++++++++ * * This product includes software developed by the * LSST Project (http://www.lsst.org/). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the LSST License Statement and * the GNU General Public License along with this program. If not, * see . */ %define geomLib_DOCSTRING " Python interface to lsst::afw::geom classes " %enddef %feature("autodoc", "1"); %module(package="lsst.afw.geom",docstring=geomLib_DOCSTRING) geomLib #pragma SWIG nowarn=381 // operator&& ignored #pragma SWIG nowarn=382 // operator|| ignored #pragma SWIG nowarn=361 // operator! ignored #pragma SWIG nowarn=503 // comparison operators ignored %{
    41 5caed4f7 + #include
    #include "lsst/daf/base.h" #include "lsst/afw/geom.h"
    43 16e03911 - #define PY_ARRAY_UNIQUE_SYMBOL LSST_AFW_GEOM_NUMPY_ARRAY_API
    44 16e03911 - #include "numpy/arrayobject.h"
    44 6fc1c3d1 + #include "lsst/pex/exceptions.h"
    45 747f909d + %}
    46 747f909d +
    47 853c5734 + %include "lsst/p_lsstSwig.i"
    48 853c5734 + %lsst_exceptions();
    49 853c5734 +
    50 853c5734 + %initializeNumPy(afw_geom)
    51 853c5734 + %{
    #include "ndarray/swig.h" #include "ndarray/swig/eigen.h" %}
    55 853c5734 + %include "ndarray.i"
    49 16e03911 - %init %{
    50 16e03911 - import_array();
    51 16e03911 - %}
    52 16e03911 -
    53 16e03911 - %include "lsst/p_lsstSwig.i"
    %import "lsst/daf/base/baseLib.i"
    56 747f909d - %lsst_exceptions();
    57 747f909d -
    58 a7ce1e71 - %include "ndarray.i"
    59 94d9538d + %include "std_vector.i"
    60 94d9538d + %template(Point2IVector) std::vector >;
    61 94d9538d + %template(Point2DVector) std::vector >;
    %declareNumPyConverters(Eigen::Matrix); %declareNumPyConverters(Eigen::Matrix); %declareNumPyConverters(Eigen::Matrix); %declareNumPyConverters(Eigen::Matrix); %include "CoordinateBase.i" %include "CoordinateExpr.i" %include "Extent.i" %include "Point.i" %Extent_PREINCLUDE(int,2); %Extent_PREINCLUDE(int,3); %Extent_PREINCLUDE(double,2); %Extent_PREINCLUDE(double,3); %Point_PREINCLUDE(int,2); %Point_PREINCLUDE(int,3); %Point_PREINCLUDE(double,2); %Point_PREINCLUDE(double,3); %include "lsst/afw/geom/CoordinateBase.h" %include "lsst/afw/geom/CoordinateExpr.h" %include "lsst/afw/geom/Extent.h" %include "lsst/afw/geom/Point.h"
    85 25e61ab4 - %Extent_POSTINCLUDE(int,2,I);
    ? ---- --
    88 4567a4cd + %ExtentI_POSTINCLUDE(2);
    ? +
    86 25e61ab4 - %Extent_POSTINCLUDE(int,3,I);
    ? ---- --
    89 4567a4cd + %ExtentI_POSTINCLUDE(3);
    ? +
    87 25e61ab4 - %Extent_POSTINCLUDE(double,2,D);
    ? ------- --
    90 4567a4cd + %ExtentD_POSTINCLUDE(2);
    ? +
    88 25e61ab4 - %Extent_POSTINCLUDE(double,3,D);
    ? ------- --
    91 4567a4cd + %ExtentD_POSTINCLUDE(3);
    ? +
    90 25e61ab4 - %Point_POSTINCLUDE(int,2,I);
    ? ---- --
    93 4567a4cd + %PointI_POSTINCLUDE(2);
    ? +
    91 25e61ab4 - %Point_POSTINCLUDE(int,3,I);
    ? ---- --
    94 4567a4cd + %PointI_POSTINCLUDE(3);
    ? +
    92 25e61ab4 - %Point_POSTINCLUDE(double,2,D);
    ? ------- --
    95 4567a4cd + %PointD_POSTINCLUDE(2);
    ? +
    93 25e61ab4 - %Point_POSTINCLUDE(double,3,D);
    ? ------- --
    96 4567a4cd + %PointD_POSTINCLUDE(3);
    ? + %CoordinateExpr_POSTINCLUDE(2); %CoordinateExpr_POSTINCLUDE(3); %extend lsst::afw::geom::Point { %template(Point2I) Point;
    100 086a11c4 - %pythoncode {
    103 81c3bd10 + %pythoncode %{
    ? + def __reduce__(self): return (Point2I, (self.getX(), self.getY()))
    103 086a11c4 - }
    106 81c3bd10 + %}
    ? + }; %extend lsst::afw::geom::Point { %template(Point3I) Point;
    108 086a11c4 - %pythoncode {
    111 81c3bd10 + %pythoncode %{
    ? + def __reduce__(self): return (Point3I, (self.getX(), self.getY(), self.getZ()))
    111 086a11c4 - }
    114 81c3bd10 + %}
    ? + }; %extend lsst::afw::geom::Point { %template(Point2D) Point;
    116 086a11c4 - %pythoncode {
    119 81c3bd10 + %pythoncode %{
    ? + def __reduce__(self): return (Point2D, (self.getX(), self.getY()))
    119 086a11c4 - }
    122 81c3bd10 + %}
    ? + }; %extend lsst::afw::geom::Point { %template(Point3D) Point;
    124 086a11c4 - %pythoncode {
    127 81c3bd10 + %pythoncode %{
    ? + def __reduce__(self): return (Point3D, (self.getX(), self.getY(), self.getZ()))
    127 086a11c4 - }
    130 81c3bd10 + %}
    ? + }; %extend lsst::afw::geom::Extent { %template(Extent2D) Extent;
    132 086a11c4 - %pythoncode {
    135 81c3bd10 + %pythoncode %{
    ? + def __reduce__(self): return (Extent2D, (self.getX(), self.getY()))
    135 086a11c4 - }
    138 81c3bd10 + %}
    ? + }; %extend lsst::afw::geom::Extent { %template(Extent3D) Extent;
    140 086a11c4 - %pythoncode {
    143 81c3bd10 + %pythoncode %{
    ? + def __reduce__(self): return (Extent3D, (self.getX(), self.getY(), self.getZ()))
    143 086a11c4 - }
    146 81c3bd10 + %}
    ? + }; %extend lsst::afw::geom::Extent {
    147 b2b5e594 - %pythoncode {
    150 81c3bd10 + %pythoncode %{
    ? + def __reduce__(self): return (Extent2I, (self.getX(), self.getY()))
    150 b2b5e594 - }
    153 81c3bd10 + %}
    ? + }; %extend lsst::afw::geom::Extent {
    154 b2b5e594 - %pythoncode {
    157 81c3bd10 + %pythoncode %{
    ? + def __reduce__(self): return (Extent3I, (self.getX(), self.getY(), self.getZ()))
    157 b2b5e594 - }
    160 81c3bd10 + %}
    ? + }; %returnCopy(lsst::afw::geom::AffineTransform::getTranslation); %returnCopy(lsst::afw::geom::AffineTransform::getLinear); %include "LinearTransform.i" %include "AffineTransform.i" %include "Box.i" %include "Angle.i" %include "Span.i" %include "XYTransform.i"
    172 3d6fb300 + %include "Polygon.i"
    173 6f5ea58d + %include "TransformMap.i"
    174 6fc1c3d1 +
    175 6fc1c3d1 + %import "lsst/pex/exceptions/exceptionsLib.i"
    176 6fc1c3d1 +
    177 6fc1c3d1 + %declareException(SingularTransformException, lsst.pex.exceptions.RuntimeError,
    178 6fc1c3d1 + lsst::afw::geom::SingularTransformException)
    179 6fc1c3d1 + %declareException(SinglePolygonException, lsst.pex.exceptions.RuntimeError,
    180 6fc1c3d1 + lsst::afw::geom::SinglePolygonException)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b2b5e594

    commit b2b5e594c165edab0e1f13ba5aa806ce04fe3716
    Author: Jim Bosch 
    Date:   Tue Jun 12 12:00:06 2012 -0400
    
        Add __reduce__ for int instantiations of Extent.
    

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    16e03911

    commit 16e03911e90bd0a5d07e13337eaf7f8381bdcb54
    Author: jbosch 
    Date:   Wed Jan 13 09:42:05 2010 +0000
    
        afw/#0 - completed temporary replacement Eigen/SWIG typemaps, miscellaneous minor fixes to AffineTransform
    

    a7ce1e71

    commit a7ce1e71d391ee1b194eabea9cead705bd9858da
    Author: Jim Bosch 
    Date:   Mon Mar 19 16:09:24 2012 -0400
    
        moved ndarray out of lsst namespace and header directories
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    086a11c4

    commit 086a11c4ec9573ee5ca310af499eef1b53398fa2
    Author: Steven Bickerton 
    Date:   Mon Jun 11 20:59:13 2012 -0500
    
        added __reduce__ for Point, Extent, Box, Linear/AffineTrans, Quadrupole, and Axes.
    

    747f909d

    commit 747f909d1d90b2597c9daf7151f661639cf63a71
    Author: jbosch 
    Date:   Thu Dec 17 03:45:00 2009 +0000
    
        afw/#892 - swig wrappers for Point and Extent
    

    Commits in /Users/nate/repos_lsst/afw/

    6f5ea58d

    commit 6f5ea58df69e1713505a44d25dbbd0e121bd6aff
    Author: Russell Owen 
    Date:   Tue Feb 18 11:25:54 2014 -0800
    
        Rename TransformRegistry to TransformMap and TransformMap to TransformMap::Transforms
    

    bba97267

    commit bba972679fb3ee4bf127299af2d1b8f875f82c2e
    Author: Russell Owen 
    Date:   Thu Jan 30 09:13:26 2014 -0800
    
        TransformRegistry.__iter__ returns coordSys, not xyTransforms (since the one can be used to find the other).
        Improved class documentation for TransformRegistry
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    94d9538d

    commit 94d9538dae14f769425472a29b29594202c4c998
    Author: Russell Owen 
    Date:   Thu Feb 20 14:54:27 2014 -0600
    
        Fix SWIG issue with master stack by spelling out Point instead of using Point2D
        in the vector template.
    

    4567a4cd

    commit 4567a4cdaf47bd681c10f45fe79a9627e3ced4cf
    Author: Jim Bosch 
    Date:   Fri Apr 3 17:47:06 2015 -0400
    
        Support for mixed-type operations in Point and Extent
        
        This adds mixed-type operators for Point and Extent, as well as new
        floor, ceil, and truncate functions for Extent, to help deal with some
        unfortunate differences between C++ and Python in how division
        is expected to behave for integers.
    

    747f909d

    commit 747f909d1d90b2597c9daf7151f661639cf63a71
    Author: jbosch 
    Date:   Thu Dec 17 03:45:00 2009 +0000
    
        afw/#892 - swig wrappers for Point and Extent
    

    853c5734

    commit 853c5734ee13f55fd35e9e18ed5ac69a0073b97f
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:18:28 2015 -0400
    
        Utilize new numeric scalar typemaps and NumPy import macro.
    

    5caed4f7

    commit 5caed4f7bfef8ecaf1daec5e793c09f9d0ca990a
    Author: Russell Owen 
    Date:   Wed Feb 19 17:51:36 2014 -0800
    
        Fixed a bug in the list version of TransformMap.transform
        Added a unit test for the above.
        Added bbox argument to Detector's constructor.
        Added getBBox and getCorners methods to Detector, and unit tests for same.
    

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    3d6fb300

    commit 3d6fb3001856d9c793c9e6291ea65ccb9e252e7f
    Author: Paul Price 
    Date:   Mon Feb 10 17:50:34 2014 -0500
    
        add CartesianPolygon class (#3139)
    

    Return to list

    tests/convolveGPU.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                    * @file
                    *
                    * @brief Tests GPU accelerated convolution
                    *
                    * @author Kresimir Cosic
                    *
                    * @ingroup afw
                    */
                    
                    
                    #include 
                    #include 
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
    
    45 0930ac63 + #include "lsst/daf/base.h"
    #include "lsst/utils/ieee.h"
    47 a9aec7fc + #include "lsst/utils/Utils.h"
    46 0930ac63 -
    47 0930ac63 - #include "lsst/daf/base.h"
    #include "lsst/pex/exceptions.h" #include "lsst/pex/logging/Trace.h" #include "lsst/afw/image.h" #include "lsst/afw/geom.h" #include "lsst/afw/math.h" #include "lsst/afw/gpu/IsGpuBuild.h" #include "lsst/afw/gpu/DevicePreference.h" //Just for PrintCudaDeviceInfo #include "lsst/afw/gpu/detail/CudaQueryDevice.h" using namespace std; using lsst::pex::logging::Trace; namespace pexEx = lsst::pex::exceptions; namespace afwImage = lsst::afw::image; namespace afwMath = lsst::afw::math; namespace afwGeom = lsst::afw::geom; typedef int TestResult; typedef afwMath::Kernel::Pixel KerPixel; typedef afwImage::VariancePixel VarPixel; typedef afwImage::MaskPixel MskPixel; // returns time difference in seconds double DiffTime(clock_t start, clock_t end) { double tm; tm = (double)difftime(end, start); tm = abs(tm); tm /= CLOCKS_PER_SEC; return tm; } //Calculates relative RMSD (coefficient of variation of the root-mean-square deviation) template double CvRmsd(afwImage::Image& imgA, afwImage::Image& imgB) { const int dimX = imgA.getWidth(); const int dimY = imgA.getHeight(); if (dimX != imgB.getWidth() || dimY != imgB.getHeight()) return NAN; double sqSum = 0; double avgSum = 0; int cnt = 0; for (int x = 0; x < dimX; x++) { for (int y = 0; y < dimY; y++) { const double valA = imgA(x, y); const double valB = imgB(x, y); if (lsst::utils::isnan(valA) && lsst::utils::isnan(valB)) continue; if (lsst::utils::isinf(valA) && lsst::utils::isinf(valB)) continue; cnt++; avgSum += (valA + valB) / 2; const double diff = valA - valB; sqSum += diff * diff; } } double rmsd = sqrt(sqSum / cnt); double avg = avgSum / cnt; return rmsd / avg; } //Returns number of different values template double DiffCnt(afwImage::Mask& imgA, afwImage::Mask& imgB) { typedef long long unsigned int Bitint; const int dimX = imgA.getWidth(); const int dimY = imgA.getHeight(); if (dimX != imgB.getWidth() || dimY != imgB.getHeight()) return NAN; int cnt = 0; for (int x = 0; x < dimX; x++) { for (int y = 0; y < dimY; y++) { const T valA = imgA(x, y); const T valB = imgB(x, y); if (valA != valB) cnt++; } } return cnt; } string NumToStr(double num) { if (lsst::utils::isnan(num)) return string("NAN!!!"); else if (lsst::utils::isinf(num)) return string("INF!!!"); else { stringstream ss; ss << num; return ss.str(); } } void PrintSeparator() { for (int i = 0; i < 79; i++) cout << "="; cout << endl; } void PrintKernelSize(afwMath::Kernel::Ptr kernel) { cout << " Kernel size: " << kernel->getWidth() << " x " << kernel->getHeight() << endl; } typedef afwMath::LinearCombinationKernel LinearCombinationKernel; afwMath::LinearCombinationKernel::Ptr ConstructLinearCombinationKernel( const unsigned kernelW, const unsigned kernelH, const int basisKernelN, const int order, int sizeX, int sizeY, const bool isPolynomial = false, const bool isGaussian = false ) { double const MinSigma = 1.5; double const MaxSigma = 4.5; // construct basis kernels const int kernelN = basisKernelN; afwMath::KernelList kernelList; for (int ii = 0; ii < kernelN; ++ii) { double majorSigma = (ii == 1) ? MaxSigma : MinSigma; double minorSigma = (ii == 2) ? MinSigma : MaxSigma; double angle = 0.0; if (ii > 2) angle = ii / 10; afwMath::GaussianFunction2 gaussFunc(majorSigma, minorSigma, angle); afwMath::Kernel::Ptr basisKernelPtr( new afwMath::AnalyticKernel(kernelW, kernelH, gaussFunc) ); kernelList.push_back(basisKernelPtr); } // construct spatially varying linear combination kernel afwMath::LinearCombinationKernel::Ptr kernelPtr; if (isPolynomial) { afwMath::PolynomialFunction2 polyFunc(order); kernelPtr = afwMath::LinearCombinationKernel::Ptr( new LinearCombinationKernel(kernelList, polyFunc) ); } if (isGaussian) { afwMath::GaussianFunction2 gaussFunc(1.3, 2.3, 23.0); kernelPtr = afwMath::LinearCombinationKernel::Ptr( new LinearCombinationKernel(kernelList, gaussFunc) ); } else { afwMath::Chebyshev1Function2 chebyFunc(order, lsst::afw::geom::Box2D( lsst::afw::geom::Point2D(-sizeX / 3.0, -sizeY / 4.0), lsst::afw::geom::Point2D( sizeX + 100.0, sizeY + 200.0) ) ); kernelPtr = afwMath::LinearCombinationKernel::Ptr( new LinearCombinationKernel(kernelList, chebyFunc) ); } LinearCombinationKernel& kernel = *kernelPtr; // Get copy of spatial parameters (all zeros), set and feed back to the kernel vector > polyParams = kernel.getSpatialParameters(); // Set spatial parameters for basis kernel 0 polyParams[0][0] = 1.0; polyParams[0][1] = -0.5 / 100; polyParams[0][2] = -0.5 / 100; if (order > 1 && !isGaussian) { polyParams[0][3] = -0.1 / sizeX; polyParams[0][4] = -0.2 / sizeY; polyParams[0][5] = 0.4 / sizeX; } for (int i = 1; i < kernelN; i++) { // Set spatial function parameters of other basis kernels polyParams[i][0] = polyParams[0][0] - i * 0.2; polyParams[i][1] = polyParams[0][1] + i * 0.1; polyParams[i][2] = polyParams[0][2] + i * 0.1; if (isGaussian) continue; for (int jj = 3; jj < (order + 1)*(order + 2) / 2; jj++) { polyParams[i][jj] = i * jj * 0.1 / 600; } } kernel.setSpatialParameters(polyParams); PrintKernelSize(kernelPtr); cout << " Number of basis kernels: " << kernel.getNBasisKernels() << endl; cout << " Spatial order: " << order << endl; cout << "Coef. count per basis kernel: " << polyParams[0].size() << endl; return kernelPtr; }
    254 0930ac63 - string GetInputFileName(int argc, char **argv)
    ? ^^^ ^ ^^
    254 a9aec7fc + string GetInputImagePath(int argc, char **argv)
    ? ^^^^ ^ ^^ {
    256 5b522953 - string imgFileName;
    ? --- ^ ^^
    256 a9aec7fc + string inImagePath;
    ? ++ + ^ ^^ if (argc < 2) {
    258 0930ac63 - string afwdata = getenv("AFWDATA_DIR");
    259 0930ac63 - if (afwdata.empty()) {
    258 a9aec7fc + try {
    259 7cbb2bb9 + string dataDir = lsst::utils::getPackageDir("afwdata");
    260 a9aec7fc + inImagePath = dataDir + "/data/med.fits";
    261 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    260 0930ac63 - std::cerr << "Usage: convolveGPU fitsFile" << endl;
    ? -----
    262 a9aec7fc + cerr << "Usage: convolveGPU [fitsFile]" << endl;
    ? + +
    263 a9aec7fc + cerr << "Warning: tests not run! Setup afwdata if you wish to use the default fitsFile." << endl;
    261 0930ac63 - std::cerr << "fitsFile excludes the \"_img.fits\" suffix" << endl;
    262 0930ac63 - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << endl;
    263 0930ac63 - std::cerr << "Is afwdata set up?\n" << endl;
    exit(EXIT_FAILURE); }
    266 0930ac63 - else {
    267 5b522953 - imgFileName = afwdata + "/data/medexp.fits";
    268 5b522953 - //imgFileName = afwdata + "/data/medsub.fits";
    269 5b522953 - //imgFileName = afwdata + "/data/871034p_1_MI.fits";
    270 5b522953 - cout << "Using image: " << imgFileName << endl;
    271 0930ac63 - }
    } else {
    274 5b522953 - imgFileName = string(argv[1]);
    ? --- ^ ^^
    268 a9aec7fc + inImagePath = string(argv[1]);
    ? ++ + ^ ^^ }
    276 5b522953 - return imgFileName;
    ? --- ^ ^^
    270 a9aec7fc + return inImagePath;
    ? ++ + ^ ^^ } afwMath::FixedKernel::Ptr ConstructKernel( const double kernelCols, const double kernelRows, const double majorSigma = 2.5, const double minorSigma = 2.0, const double angle = 0.5, const double denormalizationFactor = 47.3 ) { afwMath::GaussianFunction2 gaussFunc(majorSigma, minorSigma, angle); afwMath::AnalyticKernel analyticKernel(kernelCols, kernelRows, gaussFunc); lsst::afw::image::Image analyticImage(analyticKernel.getDimensions()); (void)analyticKernel.computeImage(analyticImage, true); analyticImage *= denormalizationFactor; afwMath::FixedKernel::Ptr fixedKernel(new afwMath::FixedKernel(analyticImage)); return fixedKernel; } string Sel(bool b, const char* onTrue, const char* onFalse) { return b ? string(onTrue) : string(onFalse); } bool IsErrorAcceptable(double val, double limit) { if (lsst::utils::isnan(val)) return false; if (lsst::utils::isinf(val)) return false; return val < limit; } bool TestConvGpu( const afwImage::MaskedImage inImgDbl, const afwImage::MaskedImage inImgFlt, afwMath::Kernel::Ptr kernel, string kernelStr, bool doNormalizeKernel ) { const afwImage::MaskedImage inMIDbl = inImgDbl; const afwImage::MaskedImage inMIFlt = inImgFlt; const int sizeX = inMIDbl.getWidth(); const int sizeY = inMIDbl.getHeight(); const afwImage::Image inPIDbl = *inMIDbl.getImage(); const afwImage::Image inPIFlt = *inMIFlt.getImage(); cout << "Image size: " << sizeX << " x " << sizeY; cout << " Kernel normalization: " << Sel(doNormalizeKernel, "on", "off") << endl; afwMath::ConvolutionControl cctrlXGpu (doNormalizeKernel, false, 0, lsst::afw::gpu::USE_GPU); afwMath::ConvolutionControl cctrlXCpu (doNormalizeKernel, false, 0, lsst::afw::gpu::USE_CPU); afwImage::MaskedImage resMIDbl(inMIDbl.getDimensions()); afwImage::MaskedImage resMIFlt(inMIDbl.getDimensions()); afwImage::MaskedImage resMIDblGpu(inMIDbl.getDimensions()); afwImage::MaskedImage resMIFltGpu(inMIDbl.getDimensions()); afwImage::Image resPIDbl(inMIDbl.getDimensions()); afwImage::Image resPIFlt(inMIDbl.getDimensions()); afwImage::Image resPIDblGpu(inMIDbl.getDimensions()); afwImage::Image resPIFltGpu(inMIDbl.getDimensions()); for (int i = 0; i < int(kernelStr.size()); i++) cout << " "; cout << " Planes Image Variance Mask" << endl; for (int i = 0; i < 79; i++) cout << "-"; cout << endl; bool isSuccess = true; // convolve afwMath::convolve(resPIDbl , inPIDbl, *kernel, cctrlXCpu); afwMath::convolve(resPIDblGpu, inPIDbl, *kernel, cctrlXGpu); afwMath::convolve(resPIFlt , inPIFlt, *kernel, cctrlXCpu); afwMath::convolve(resPIFltGpu, inPIFlt, *kernel, cctrlXGpu); const double errDbl = 5e-16; const double errFlt = 5e-7; double diffPIDbl = CvRmsd(resPIDbl, resPIDblGpu); double diffPIFlt = CvRmsd(resPIFlt, resPIFltGpu); if ( !IsErrorAcceptable(diffPIDbl, errDbl) ) isSuccess = false; if ( !IsErrorAcceptable(diffPIFlt, errFlt) ) isSuccess = false; cout << " Plain Image Dbl " << kernelStr << " Dev: " << setw(11) << diffPIDbl << Sel(diffPIDbl > errDbl, "*", " ") << endl; cout << " Plain Image Flt " << kernelStr << " Dev: " << setw(11) << diffPIFlt << Sel(diffPIFlt > errFlt, "*", " ") << endl; afwMath::convolve(resMIDbl , inMIDbl, *kernel, cctrlXCpu); afwMath::convolve(resMIDblGpu, inMIDbl, *kernel, cctrlXGpu); afwMath::convolve(resMIFlt , inMIFlt, *kernel, cctrlXCpu); afwMath::convolve(resMIFltGpu, inMIFlt, *kernel, cctrlXGpu); double diffMIImgDbl = CvRmsd(*resMIDbl.getImage() , *resMIDblGpu.getImage()); double diffMIVarDbl = CvRmsd(*resMIDbl.getVariance(), *resMIDblGpu.getVariance()); double diffMIMskDbl = DiffCnt(*resMIDbl.getMask() , *resMIDblGpu.getMask()); double diffMIImgFlt = CvRmsd(*resMIFlt.getImage() , *resMIFltGpu.getImage()); double diffMIVarFlt = CvRmsd(*resMIFlt.getVariance(), *resMIFltGpu.getVariance()); double diffMIMskFlt = DiffCnt(*resMIFlt.getMask() , *resMIFltGpu.getMask()); if ( !IsErrorAcceptable(diffMIImgDbl, errDbl) ) isSuccess = false; if ( !IsErrorAcceptable(diffMIVarDbl, errFlt) ) isSuccess = false; if ( diffMIMskDbl > 0) isSuccess = false; if ( !IsErrorAcceptable(diffMIImgFlt, errFlt) ) isSuccess = false; if ( !IsErrorAcceptable(diffMIVarFlt, errFlt) ) isSuccess = false; if ( diffMIMskFlt > 0) isSuccess = false; cout << "Masked Image Dbl " << kernelStr << " Dev: " << setw(11) << diffMIImgDbl << Sel(diffMIImgDbl > errDbl, "* ", " ") << setw(11) << diffMIVarDbl << Sel(diffMIVarDbl > errFlt, "* ", " ") << setw( 6) << diffMIMskDbl << Sel(diffMIMskDbl > 0 , "* ", " ") << endl; cout << "Masked Image Flt " << kernelStr << " Dev: " << setw(11) << diffMIImgFlt << Sel(diffMIImgFlt > errFlt, "* ", " ") << setw(11) << diffMIVarFlt << Sel(diffMIVarFlt > errFlt, "* ", " ") << setw( 6) << diffMIMskFlt << Sel(diffMIMskFlt > 0 , "* ", " ") << endl; if (!isSuccess) { cout << "ERROR: Unacceptaby large deviation found!" << endl; cout << "The failed tests are marked with *" << endl; } return isSuccess; } bool GpuTestAccuracy(string imgFileName) { lsst::pex::logging::Trace::setDestination(std::cout); lsst::pex::logging::Trace::setVerbosity("lsst.afw.kernel", 5); afwGeom::Box2I inputBBox(afwGeom::Point2I(52, 574), afwGeom::Extent2I(76, 80)); afwImage::MaskedImage inImgFlt(imgFileName); afwImage::MaskedImage inImgDbl(imgFileName); const int sizeX = inImgFlt.getWidth(); const int sizeY = inImgFlt.getHeight(); if (sizeX < 500 || sizeY < 700) { std::cerr << "Minimum image size is 500 x 700" << endl; exit(EXIT_FAILURE); } bool isSuccess = true; for (int i = 0; i < 4; i++) { bool doNormalizeKernel = i % 2 == 0; bool isBoundedBoxKernel = i / 2 == 0; const afwImage::MaskedImage inMIDblBoxed(inImgDbl, inputBBox, afwImage::LOCAL, true); const afwImage::MaskedImage inMIFltBoxed(inImgFlt, inputBBox, afwImage::LOCAL, true); const afwImage::MaskedImage inMIDbl = isBoundedBoxKernel ? inMIDblBoxed : inImgDbl;; const afwImage::MaskedImage inMIFlt = isBoundedBoxKernel ? inMIFltBoxed : inImgFlt; PrintSeparator(); LinearCombinationKernel::Ptr linCoKernelCheb = ConstructLinearCombinationKernel( 4, 5, //size 4, //basis kernel count 3, //order sizeX, sizeY, //image size false //chebyshev ); const bool isSuccessCheb = TestConvGpu(inMIDbl, inMIFlt, linCoKernelCheb, "cheby LC kernel", doNormalizeKernel); PrintSeparator(); LinearCombinationKernel::Ptr linCoKernelPoly = ConstructLinearCombinationKernel( 6, 4, //size 3, //basis kernel count 2, //order sizeX, sizeY, //image size true //polynomial ); const bool isSuccessPoly = TestConvGpu(inMIDbl, inMIFlt, linCoKernelPoly, " poly LC kernel", doNormalizeKernel); PrintSeparator(); LinearCombinationKernel::Ptr linCoKernelCheb11 = ConstructLinearCombinationKernel( 3, 3, //size 1, //basis kernel count 1, //order sizeX, sizeY, //image size false //chebyshev ); const bool isSuccessCheb11 = TestConvGpu(inMIDbl, inMIFlt, linCoKernelCheb11, " cheby LC kernel", doNormalizeKernel); PrintSeparator(); afwMath::FixedKernel::Ptr fixedKernel1 = ConstructKernel(5, 7); PrintKernelSize(fixedKernel1); const bool isSuccessFixed1 = TestConvGpu(inMIDbl, inMIFlt, fixedKernel1, "invariant kernel", doNormalizeKernel); PrintSeparator(); afwMath::FixedKernel::Ptr fixedKernel2 = ConstructKernel(8, 3, 3.5, 1.3, 9.0, 11); PrintKernelSize(fixedKernel2); const bool isSuccessFixed2 = TestConvGpu(inMIDbl, inMIFlt, fixedKernel2, "invariant kernel", doNormalizeKernel); isSuccess = isSuccess && isSuccessCheb && isSuccessPoly && isSuccessCheb11 && isSuccessFixed1 && isSuccessFixed2; } return isSuccess; } bool GpuTestExceptions(const string imgFileName) { lsst::pex::logging::Trace::setDestination(std::cout); lsst::pex::logging::Trace::setVerbosity("lsst.afw.kernel", 5); afwImage::MaskedImage inImg(imgFileName); afwImage::MaskedImage resImg(inImg.getDimensions()); bool isSuccess = true; PrintSeparator(); afwMath::ConvolutionControl cctrlFGpu (false, false, 0, lsst::afw::gpu::USE_GPU); afwMath::ConvolutionControl cctrlFCpu (false, false, 0, lsst::afw::gpu::USE_CPU); afwMath::ConvolutionControl cctrlThrw (false, false, 0, lsst::afw::gpu::AUTO); afwMath::ConvolutionControl cctrlSafe (false, false, 0, lsst::afw::gpu::AUTO_WITH_CPU_FALLBACK); afwMath::FixedKernel::Ptr fixedKernel = ConstructKernel(5, 7); afwMath::GaussianFunction2 gaussFunc(0.8, 0.7, 30); afwMath::AnalyticKernel analyticKernel(7, 7, gaussFunc); afwMath::DeltaFunctionKernel deltaFKernel(11, 17, lsst::afw::geom::Point2I(1)); LinearCombinationKernel::Ptr linCoKernelGauss = ConstructLinearCombinationKernel( 4, 5, //size 4, //basis kernel count 3, //order 1, 1, //image size false, //not polynomial true //gaussian ); cout << endl; bool isThrown; isThrown = false; try { afwMath::convolve(resImg, inImg, *fixedKernel, cctrlThrw); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with fixed kernel with AUTO " << "should have not thrown an exception" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, deltaFKernel, cctrlFGpu); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with delta function kernel with USE_GPU" << "should have thrown an exception because it's acceleration is not supported" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, deltaFKernel, cctrlSafe); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with delta function kernel with AUTO_WITH_CPU_FALLBACK" << "should not have thrown an exception because it should have fell back to CPU code path" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, deltaFKernel, cctrlThrw); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with delta function kernel with AUTO" << "should not have thrown an exception because it should have fell back to CPU code path" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, deltaFKernel, cctrlFCpu); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with delta function kernel with USE_CPU" << "should not have thrown an exception because it should have used CPU code path" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, analyticKernel, cctrlFGpu); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with analytic kernel with USE_GPU " << "should have not thrown an exception because this specific kernel was spatially invariant" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, *linCoKernelGauss, cctrlFGpu); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with linear combination kernel " << "with gaussian spatial function with USE_GPU " << "should have thrown an exception because gaussian spatial function is not supported" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, *linCoKernelGauss, cctrlThrw); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with linear combination kernel " << "with gaussian spatial function with AUTO " << "should not have thrown an exception because it should have fell back to CPU execution" << endl; } if (isSuccess) { cout << "All GPU exception tests passed." << endl; } cout << endl; return isSuccess; } bool CpuTestExceptions(const string imgFileName) { lsst::pex::logging::Trace::setDestination(std::cout); lsst::pex::logging::Trace::setVerbosity("lsst.afw.kernel", 5); afwImage::MaskedImage inImg(imgFileName); afwImage::MaskedImage resImg(inImg.getDimensions()); bool isSuccess = true; PrintSeparator(); afwMath::ConvolutionControl cctrlFGpu (false, false, 0, lsst::afw::gpu::USE_GPU); afwMath::ConvolutionControl cctrlFCpu (false, false, 0, lsst::afw::gpu::USE_CPU); afwMath::ConvolutionControl cctrlThrw (false, false, 0, lsst::afw::gpu::AUTO); afwMath::ConvolutionControl cctrlSafe (false, false, 0, lsst::afw::gpu::AUTO_WITH_CPU_FALLBACK); afwMath::FixedKernel::Ptr fixedKernel = ConstructKernel(5, 7); afwMath::GaussianFunction2 gaussFunc(0.8, 0.7, 30); afwMath::AnalyticKernel analyticKernel(7, 7, gaussFunc); afwMath::DeltaFunctionKernel deltaFKernel(11, 17, lsst::afw::geom::Point2I(1)); LinearCombinationKernel::Ptr linCoKernelGauss = ConstructLinearCombinationKernel( 4, 5, //size 4, //basis kernel count 3, //order 1, 1, //image size false, //not polynomial true //gaussian ); cout << endl; bool isThrown; isThrown = false; try { afwMath::convolve(resImg, inImg, *fixedKernel, cctrlThrw); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with fixed kernel with AUTO " << "should have not thrown an exception" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, deltaFKernel, cctrlFGpu); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with delta function kernel with USE_GPU" << "should have thrown an exception because AFW was not compiled with GPU support" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, deltaFKernel, cctrlSafe); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with delta function kernel with AUTO_WITH_CPU_FALLBACK" << "should not have thrown an exception because it should have used to CPU execution" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, deltaFKernel, cctrlThrw); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with delta function kernel with AUTO" << "should not have thrown an exception because it should have fell back to CPU execution" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, deltaFKernel, cctrlFCpu); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with delta function kernel with USE_CPU" << "should not have thrown an exception because it should have used CPU execution" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, analyticKernel, cctrlFGpu); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with analytic kernel with USE_GPU " << "should have thrown an exception because AFW was not compiled with GPU support" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, *linCoKernelGauss, cctrlFGpu); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with linear combination kernel " << "with gaussian spatial function with USE_GPU " << "should have thrown an exception because AFW was not compiled with GPU support" << endl; } isThrown = false; try { afwMath::convolve(resImg, inImg, *linCoKernelGauss, cctrlThrw); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU convolution with linear combination kernel " << "with gaussian spatial function with AUTO " << "should not have thrown an exception because it should have used CPU execution" << endl; } if (isSuccess) { cout << "All GPU exception tests passed (but AFW was not compiled with GPU support!!)." << endl; cout << "Additional tests will be performed when GPU acceleration is available." << endl; } cout << endl; return isSuccess; } TestResult TestGpu(int argc, char**argv) { lsst::afw::gpu::detail::PrintCudaDeviceInfo();
    782 978b368a - string baseFileName = GetInputFileName(argc, argv);
    ? ^ ^^^^^ ^^^ ^ ^^
    776 a9aec7fc + string inImageName = GetInputImagePath(argc, argv);
    ? ^^^^ ^ ^^^^ ^ ^^
    784 0930ac63 - const bool isSuccess1 = GpuTestAccuracy(baseFileName);
    ? ^ ^^^^^
    778 a9aec7fc + const bool isSuccess1 = GpuTestAccuracy(inImageName);
    ? ^^^^ ^
    785 0930ac63 - const bool isSuccess2 = GpuTestExceptions(baseFileName);
    ? ^ ^^^^^
    779 a9aec7fc + const bool isSuccess2 = GpuTestExceptions(inImageName);
    ? ^^^^ ^ const bool isSuccess = isSuccess1 && isSuccess2; return isSuccess ? EXIT_SUCCESS : EXIT_FAILURE; } TestResult TestCpu(int argc, char**argv) {
    793 0930ac63 - string baseFileName = GetInputFileName(argc, argv);
    ? ^ ^^^^^ ^^^ ^ ^^
    787 a9aec7fc + string inImageName = GetInputImagePath(argc, argv);
    ? ^^^^ ^ ^^^^ ^ ^^
    795 0930ac63 - const bool isSuccess = CpuTestExceptions(baseFileName);
    ? ^ ^^^^^
    789 a9aec7fc + const bool isSuccess = CpuTestExceptions(inImageName);
    ? ^^^^ ^ return isSuccess ? EXIT_SUCCESS : EXIT_FAILURE; } int main(int argc, char **argv) { cout << endl; cout << "Note: Dev = coefficient of variation of RMSD" << endl; cout << endl;
    800 0930ac63 +
    801 a9aec7fc + GetInputImagePath(argc, argv); // if afwdata not setup then exit
    int status = EXIT_SUCCESS; try { if (lsst::afw::gpu::isGpuBuild()) { status = TestGpu(argc, argv); } else { status = TestCpu(argc, argv); } } catch (pexEx::Exception &e) { clog << e.what() << endl; status = EXIT_FAILURE; } PrintSeparator(); cout << endl; if (status == EXIT_FAILURE) { cout << "Some tests have failed." << endl; } else { cout << "All tests passed OK." << endl; } cout << endl; // Check for memory leaks if (lsst::daf::base::Citizen::census(0) == 0) { cerr << "No leaks detected" << endl; } else { cerr << "Leaked memory blocks:" << endl; lsst::daf::base::Citizen::census(cerr); status = EXIT_FAILURE; } return status; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0930ac63

    commit 0930ac63373c05e0d936dcb19795df4c8fc806b6
    Author: Kresimir Cosic 
    Date:   Thu Nov 24 05:28:27 2011 +0100
    
        Added a unit test and an example
        - example is timeConvolveGpu.cc, it displays speedup for various cases
        - unit test is convolveGpu.cc
        - also fixed a bug in nvcc command line
        - also made some additional functions visible to CPU-only build
    

    978b368a

    commit 978b368a4497bfd0a6d0ee9f3d98263c8b44594f
    Author: Kresimir Cosic 
    Date:   Mon Feb 27 13:24:37 2012 +0100
    
        Slight improvement to the convolveGPU test
    

    5b522953

    commit 5b522953c3a80b54c7832793f353c7e00d3b5ea7
    Author: Jim Bosch 
    Date:   Tue Nov 20 14:53:52 2012 -0500
    
        Convert tests to use MEFs (requires afwdata update), remove a worthless one.
    

    Commits in /Users/nate/repos_lsst/afw/

    0930ac63

    commit 0930ac63373c05e0d936dcb19795df4c8fc806b6
    Author: Kresimir Cosic 
    Date:   Thu Nov 24 05:28:27 2011 +0100
    
        Added a unit test and an example
        - example is timeConvolveGpu.cc, it displays speedup for various cases
        - unit test is convolveGpu.cc
        - also fixed a bug in nvcc command line
        - also made some additional functions visible to CPU-only build
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    tests/imagePca.py

    Diff:

    1 e56adc6b - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for PCA on Images Run with: python imagePca.py or python >>> import imagePca; imagePca.run() """ import unittest import numpy as np import random import math import itertools import lsst.utils.tests as utilsTests import lsst.pex.exceptions as pexExcept
    44 e56adc6b - import lsst.daf.base
    import lsst.afw.geom as afwGeom import lsst.afw.image.imageLib as afwImage import lsst.afw.display.utils as displayUtils import lsst.afw.display.ds9 as ds9 try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ImagePcaTestCase(unittest.TestCase): """A test case for ImagePca""" def setUp(self): self.ImageSet = afwImage.ImagePcaF() def tearDown(self): del self.ImageSet def testInnerProducts(self): """Test inner products""" width, height = 10, 20 im1 = afwImage.ImageF(afwGeom.Extent2I(width, height)) val1 = 10 im1.set(val1) im2 = im1.Factory(im1.getDimensions()) val2 = 20 im2.set(val2) self.assertEqual(afwImage.innerProduct(im1, im1), width*height*val1*val1) self.assertEqual(afwImage.innerProduct(im1, im2), width*height*val1*val2) im2.set(0, 0, 0) self.assertEqual(afwImage.innerProduct(im1, im2), (width*height - 1)*val1*val2) im2.set(0, 0, val2) # reinstate value im2.set(width - 1, height - 1, 1) self.assertEqual(afwImage.innerProduct(im1, im2), (width*height - 1)*val1*val2 + val1) def testAddImages(self): """Test adding images to a PCA set""" nImage = 3 for i in range(nImage): im = afwImage.ImageF(afwGeom.Extent2I(21, 21)) val = 1 im.set(val) self.ImageSet.addImage(im, 1.0) vec = self.ImageSet.getImageList() self.assertEqual(len(vec), nImage) self.assertEqual(vec[nImage - 1].get(0, 0), val) def tst(): """Try adding an image with no flux""" self.ImageSet.addImage(im, 0.0)
    107 0391452c - utilsTests.assertRaisesLsstCpp(self, pexExcept.OutOfRangeException, tst)
    107 6fc1c3d1 + self.assertRaises(pexExcept.OutOfRangeError, tst)
    def testMean(self): """Test calculating mean image""" width, height = 10, 20 values = (100, 200, 300) meanVal = 0 for val in values: im = afwImage.ImageF(afwGeom.Extent2I(width, height)) im.set(val) self.ImageSet.addImage(im, 1.0) meanVal += val meanVal = meanVal/len(values) mean = self.ImageSet.getMean() self.assertEqual(mean.getWidth(), width) self.assertEqual(mean.getHeight(), height) self.assertEqual(mean.get(0, 0), meanVal) self.assertEqual(mean.get(width - 1, height - 1), meanVal) def testPca(self): """Test calculating PCA""" random.seed(0) width, height = 200, 100 numBases = 3 numInputs = 3 bases = [] for i in range(numBases): im = afwImage.ImageF(width, height) array = im.getArray() x, y = np.indices(array.shape) period = 5*(i+1) fx = np.sin(2*math.pi/period*x + 2*math.pi/numBases*i) fy = np.sin(2*math.pi/period*y + 2*math.pi/numBases*i) array[x,y] = fx + fy bases.append(im) if display: mos = displayUtils.Mosaic(background=-10) ds9.mtv(mos.makeMosaic(bases), title="Basis functions", frame=1) inputs = [] for i in range(numInputs): im = afwImage.ImageF(afwGeom.Extent2I(width, height)) im.set(0) for b in bases: im.scaledPlus(random.random(), b) inputs.append(im) self.ImageSet.addImage(im, 1.0) if display: mos = displayUtils.Mosaic(background=-10) ds9.mtv(mos.makeMosaic(inputs), title="Inputs", frame=2) self.ImageSet.analyze() eImages = [] for img in self.ImageSet.getEigenImages(): eImages.append(img) if display: mos = displayUtils.Mosaic(background=-10) ds9.mtv(mos.makeMosaic(eImages), title="Eigenimages", frame=3) self.assertEqual(len(eImages), numInputs) # Test for orthogonality for i1, i2 in itertools.combinations(range(len(eImages)), 2): inner = afwImage.innerProduct(eImages[i1], eImages[i2]) norm1 = eImages[i1].getArray().sum() norm2 = eImages[i2].getArray().sum() inner /= norm1*norm2 self.assertAlmostEqual(inner, 0) def testPcaNaN(self): """Test calculating PCA when the images can contain NaNs""" width, height = 20, 10 values = (100, 200, 300) for i, val in enumerate(values): im = afwImage.ImageF(afwGeom.Extent2I(width, height)) im.set(val) if i == 1: im.set(width//2, height//2, np.nan) self.ImageSet.addImage(im, 1.0) self.ImageSet.analyze() eImages = [] for img in self.ImageSet.getEigenImages(): eImages.append(img) if display: mos = displayUtils.Mosaic(background=-10) ds9.mtv(mos.makeMosaic(eImages), frame=1) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ImagePcaTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    0391452c

    commit 0391452c28d0db8ab5e6b6bac1118d94f9fd7251
    Author: rhl 
    Date:   Thu Mar 5 22:04:21 2009 +0000
    
        Must specify (non-zero) flux with Images
    

    e56adc6b

    commit e56adc6b781a9b8ff238752892a331f94a4a6a35
    Author: rhl 
    Date:   Tue Mar 3 05:41:30 2009 +0000
    
        Initial support for PCA of images
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    include/lsst/afw/fits.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef LSST_AFW_fits_h_INCLUDED
                    #define LSST_AFW_fits_h_INCLUDED
                    
                    /**
                     *  @file lsst/afw/fits.h
                     *
                     *  Utilities for working with FITS files.  These are mostly thin wrappers around
                     *  cfitsio calls, and their main purpose is to transform functions signatures from
                     *  void pointers and cfitsio's preprocessor type enums to a more type-safe and
                     *  convenient interface using overloads and templates.
                     *
                     *  This was written as part of implementing the afw/table library.  Someday
                     *  the afw/image FITS I/O should be modified to use some of these with the goal
                     *  of eliminating a lot of code between the two.
                     */
                    
                    #include 
                    
                    #include 
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/daf/base.h"
                    #include "ndarray.h"
                    
                    namespace lsst { namespace afw { namespace fits {
                    
                    /**
                     * @brief An exception thrown when problems are found when reading or writing FITS files.
                     */
    
    32 d5769d71 - LSST_EXCEPTION_TYPE(FitsError, lsst::pex::exceptions::IoErrorException, lsst::afw::fits::FitsError)
    ? ---------
    32 21597d88 + LSST_EXCEPTION_TYPE(FitsError, lsst::pex::exceptions::IoError, lsst::afw::fits::FitsError)
    /** * @brief An exception thrown when a FITS file has the wrong type. */ LSST_EXCEPTION_TYPE(FitsTypeError, lsst::afw::fits::FitsError, lsst::afw::fits::FitsTypeError) #ifndef SWIG // only want SWIG to see the exceptions; everything else is too low-level for Python. /** * @brief Base class for polymorphic functors used to iterator over FITS key headers. * * Subclass this, and then pass an instance to Fits::forEachKey to iterate over all the * keys in a header. */ class HeaderIterationFunctor { public: virtual void operator()( std::string const & key, std::string const & value, std::string const & comment ) = 0; virtual ~HeaderIterationFunctor() {} }; /** * @brief Return an error message reflecting FITS I/O errors. * * @param[in] fileName FITS filename to be included in the error message. * @param[in] status The last status value returned by the cfitsio library; if nonzero, * the error message will include a description from cfitsio. * @param[in] msg An additional custom message to include. */ std::string makeErrorMessage(std::string const & fileName="", int status=0, std::string const & msg=""); inline std::string makeErrorMessage(std::string const & fileName, int status, boost::format const & msg) { return makeErrorMessage(fileName, status, msg.str()); } /** * @brief Return an error message reflecting FITS I/O errors. * * @param[in] fptr A cfitsio fitsfile pointer to be inspected for a filename. * Passed as void* to avoid including fitsio.h in the header file. * @param[in] status The last status value returned by the cfitsio library; if nonzero, * the error message will include a description from cfitsio. * @param[in] msg An additional custom message to include. */ std::string makeErrorMessage(void * fptr, int status=0, std::string const & msg=""); inline std::string makeErrorMessage(void * fptr, int status, boost::format const & msg) { return makeErrorMessage(fptr, status, msg.str()); } /** * A FITS-related replacement for LSST_EXCEPT that takes an additional Fits object * and uses makeErrorMessage(fitsObj.fptr, fitsObj.status, ...) to construct the message. */ #define LSST_FITS_EXCEPT(type, fitsObj, ...) \ type(LSST_EXCEPT_HERE, lsst::afw::fits::makeErrorMessage((fitsObj).fptr, (fitsObj).status, __VA_ARGS__)) /** * Throw a FitsError exception if the status of the given Fits object is nonzero. */ #define LSST_FITS_CHECK_STATUS(fitsObj, ...) \ if ((fitsObj).status != 0) throw LSST_FITS_EXCEPT(lsst::afw::fits::FitsError, fitsObj, __VA_ARGS__) /// Return the cfitsio integer BITPIX code for the given data type. template int getBitPix(); /** * @brief Lifetime-management for memory that goes into FITS memory files. */ class MemFileManager : private boost::noncopyable { public: /** * @brief Construct a MemFileManager with no initial memory buffer. * * The manager will still free the memory when it goes out of scope, but all allocation * and reallocation will be performed by cfitsio as needed. */ MemFileManager() : _ptr(0), _len(0), _managed(true) {} /** * @brief Construct a MemFileManager with (len) bytes of initial memory. * * The manager will free the memory when it goes out of scope, and cfitsio will be allowed * to reallocate the internal memory as needed. */ explicit MemFileManager(std::size_t len) : _ptr(0), _len(0), _managed(true) { reset(len); } /** * @brief Construct a MemFileManager that references and does not manage external memory. * * The manager will not manage the given pointer, and it will not allow cfitsio to do so * either. The user must provide enough initial memory and is responsible for freeing * it manually after the FITS file has been closed. */ MemFileManager(void * ptr, std::size_t len) : _ptr(ptr), _len(len), _managed(false) {} /** * @brief Return the manager to the same state it would be if default-constructed. * * This must not be called while a FITS file that uses this memory is open. */ void reset(); /** * @brief Set the size of the internal memory buffer, freeing the current buffer if necessary. * * This must not be called while a FITS file that uses this memory is open. * * Memory allocated with this overload of reset can be reallocated by cfitsio * and will be freed when the manager goes out of scope or is reset. */ void reset(std::size_t len); /** * @brief Set the internal memory buffer to an manually-managed external block. * * This must not be called while a FITS file that uses this memory is open. * * Memory passed to this overload of reset cannot be reallocated by cfitsio * and will not be freed when the manager goes out of scope or is reset. */ void reset(void * ptr, std::size_t len) { reset(); _ptr = ptr; _len = len; _managed = false; } ~MemFileManager() { reset(); } /// @brief Return the buffer void* getData() const { return _ptr; } /// @brief Return the buffer length std::size_t getLength() const { return _len; } private: friend class Fits; void * _ptr; std::size_t _len; bool _managed; }; /** * @brief A simple struct that combines the two arguments that must be passed to most cfitsio routines * and contains thin and/or templated wrappers around common cfitsio routines. * * This is NOT intended to be an object-oriented C++ wrapper around cfitsio; it's simply a thin layer that * saves a lot of repetition, const/reinterpret casts, and replaces void pointer args and type codes * with templates and overloads. * * Like a cfitsio pointer, a Fits object always considers one HDU the "active" one, and most operations * will be applied to that HDU. * * All member functions are non-const because they may modify the 'status' data member. * * @note All functions that take a row or column number below are 0-indexed; the internal cfitsio * calls are all 1-indexed. */ class Fits : private boost::noncopyable { template void createImageImpl(int nAxis, long * nAxes); template void writeImageImpl(T const * data, int nElements); template void readImageImpl(int nAxis, T * data, long * begin, long * end, long * increment); void getImageShapeImpl(int nAxis, long * nAxes); public: enum BehaviorFlags { AUTO_CLOSE = 0x01, // Close files when the Fits object goes out of scope if fptr != NULL AUTO_CHECK = 0x02 // Call LSST_FITS_CHECK_STATUS after every cfitsio call }; /// @brief Return the file name associated with the FITS object or "" if there is none. std::string getFileName() const; /// @brief Return the current HDU (1-indexed; 1 is the Primary HDU). int getHdu(); /** * @brief Set the current HDU. * * @param[in] hdu The HDU to move to (1-indexed; 1 is the Primary HDU). * The special value of 0 moves to the first extension * if the Primary HDU is empty (has NAXIS==0) and the * the Primary HDU is the current one. * @param[in] relative If true, move relative to the current HDU. */ void setHdu(int hdu, bool relative=false); /// @brief Return the number of HDUs in the file. int countHdus(); //@{ /// @brief Set a FITS header key, editing if it already exists and appending it if not. template void updateKey(std::string const & key, T const & value, std::string const & comment); void updateKey(std::string const & key, char const * value, std::string const & comment) { updateKey(key, std::string(value), comment); } template void updateKey(std::string const & key, T const & value); void updateKey(std::string const & key, char const * value) { updateKey(key, std::string(value)); } //@} //@{ /** * @brief Add a FITS header key to the bottom of the header. * * If the key is HISTORY or COMMENT and the value is a std::string or C-string, * a special HISTORY or COMMENT key will be appended (and the comment argument * will be ignored if present). */ template void writeKey(std::string const & key, T const & value, std::string const & comment); void writeKey(std::string const & key, char const * value, std::string const & comment) {
    251 9aed7dca - updateKey(key, std::string(value), comment);
    ? ^^^^
    251 f0bfbada + writeKey(key, std::string(value), comment);
    ? ^^^ } template void writeKey(std::string const & key, T const & value); void writeKey(std::string const & key, char const * value) {
    256 9aed7dca - updateKey(key, std::string(value));
    ? ^^^^
    256 f0bfbada + writeKey(key, std::string(value));
    ? ^^^ } //@} //@{ /// @brief Update a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number. template void updateColumnKey(std::string const & prefix, int n, T const & value, std::string const & comment); void updateColumnKey(std::string const & prefix, int n, char const * value, std::string const & comment) { updateColumnKey(prefix, n, std::string(value), comment); } template void updateColumnKey(std::string const & prefix, int n, T const & value); void updateColumnKey(std::string const & prefix, int n, char const * value) { updateColumnKey(prefix, n, std::string(value)); } //@} //@{ /// @brief Write a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number. template void writeColumnKey(std::string const & prefix, int n, T const & value, std::string const & comment); void writeColumnKey(std::string const & prefix, int n, char const * value, std::string const & comment) { writeColumnKey(prefix, n, std::string(value), comment); } template void writeColumnKey(std::string const & prefix, int n, T const & value); void writeColumnKey(std::string const & prefix, int n, char const * value) { writeColumnKey(prefix, n, std::string(value)); } //@} /** * @brief Read a FITS header into a PropertySet or PropertyList. * * @param[in] metadata A PropertySet or PropertyList whose items will be appended * to the FITS header. * * All keys will be appended to the FITS header rather than used to update existing keys. Order of keys * will be preserved if and only if the metadata object is actually a PropertyList. */ void writeMetadata(daf::base::PropertySet const & metadata); /** * @brief Read a FITS header into a PropertySet or PropertyList. * * @param[in,out] metadata A PropertySet or PropertyList that FITS header items will be added to. * @param[in] strip If true, common FITS keys that usually have non-metadata intepretations * (e.g. NAXIS, BITPIX) will be ignored. * * Order will preserved if and only if the metadata object is actually a PropertyList. */ void readMetadata(daf::base::PropertySet & metadata, bool strip=false); /// @brief Read a FITS header key into the given reference. template void readKey(std::string const & key, T & value); /** * @brief Call a polymorphic functor for every key in the header. * * Each value is passed in as a string, and the single quotes that mark an actual * string value are not removed (neither are extra spaces). However, long strings * that make use of the CONTINUE keyword are concatenated to look as if they were * on a single line. */ void forEachKey(HeaderIterationFunctor & functor); /** * @brief Create an empty image HDU with NAXIS=0 at the end of the file. * * This is primarily useful to force the first "real" HDU to be an extension HDU by creating * an empty Primary HDU. The new HDU is set as the active one. */ void createEmpty(); /** * @brief Create an image with pixel type provided by the given explicit PixelT template parameter * and shape defined by an ndarray index. * * @note The shape parameter is ordered fastest-dimension last (i.e. [y, x]) as is conventional * with ndarray. * * The new image will be in a new HDU at the end of the file, which may be the Primary HDU * if the FITS file is empty. */ template void createImage(ndarray::Vector const & shape) { ndarray::Vector nAxes(shape.reverse()); createImageImpl(N, nAxes.elems); } /** * @brief Create a 2-d image with pixel type provided by the given explicit PixelT template parameter. * * The new image will be in a new HDU at the end of the file, which may be the Primary HDU * if the FITS file is empty. */ template void createImage(long x, long y) { long naxes[2] = { x, y }; createImageImpl(2, naxes); } /** * @brief Write an ndarray::Array to a FITS image HDU. * * The HDU must already exist and have the correct bitpix. * * An extra deep-copy may be necessary if the array is not fully contiguous. */ template void writeImage(ndarray::Array const & array) { ndarray::Array contiguous = ndarray::dynamic_dimension_cast<2>(array); if (contiguous.empty()) contiguous = ndarray::copy(array); writeImageImpl(contiguous.getData(), contiguous.getNumElements()); } /// @brief Return the number of dimensions in the current HDU. int getImageDim(); /** * @brief Return the shape of the current (image) HDU. * * The order of dimensions is reversed from the FITS ordering, reflecting the usual * (y,x) ndarray convention. * * The template parameter must match the actual number of dimension in the image. */ template ndarray::Vector getImageShape() { ndarray::Vector nAxes(1); getImageShapeImpl(N, nAxes.elems); ndarray::Vector shape; for (int i = 0; i < N; ++i) shape[i] = nAxes[N-i-1]; return shape; } /** * @brief Return true if the current HDU has the given pixel type.. * * This takes into account the BUNIT and BSCALE keywords, which can allow integer * images to be interpreted as floating point. */ template bool checkImageType(); /** * @brief Read an array from a FITS image. * * @param[out] array Array to be filled. Must already be allocated to the desired shape. * @param[in] offset Indices of the first pixel to be read from the image. */ template void readImage( ndarray::Array const & array, ndarray::Vector const & offset ) { ndarray::Vector begin(offset.reverse()); ndarray::Vector end(begin); end += array.getShape().reverse(); ndarray::Vector increment(1); begin += increment; // first FITS pixel is 1, not 0 readImageImpl(N, array.getData(), begin.elems, end.elems, increment.elems); } /// @brief Create a new binary table extension. void createTable(); /** * @brief Add a column to a table * * If size <= 0, the field will be a variable length array, with max set by (-size), * or left unknown if size == 0. */ template int addColumn(std::string const & ttype, int size, std::string const & comment); /** * @brief Add a column to a table * * If size <= 0, the field will be a variable length array, with max set by (-size), * or left unknown if size == 0. */ template int addColumn(std::string const & ttype, int size); /// @brief Append rows to a table, and return the index of the first new row. std::size_t addRows(std::size_t nRows); /// @brief Return the number of row in a table. std::size_t countRows(); /// @brief Write an array value to a binary table. template void writeTableArray(std::size_t row, int col, int nElements, T const * value); /// @brief Write an scalar value to a binary table. template void writeTableScalar(std::size_t row, int col, T value) { writeTableArray(row, col, 1, &value); } /// @brief Write a string to a binary table. void writeTableScalar(std::size_t row, int col, std::string const & value); /// @brief Read an array value from a binary table. template void readTableArray(std::size_t row, int col, int nElements, T * value); /// @brief Read an array scalar from a binary table. template void readTableScalar(std::size_t row, int col, T & value) { readTableArray(row, col, 1, &value); } /// @brief Read a string from a binary table. void readTableScalar(std::size_t row, int col, std::string & value); /// @brief Return the size of an array column. long getTableArraySize(int col); /// @brief Return the size of an variable-length array field. long getTableArraySize(std::size_t row, int col); /// @brief Default constructor; set all data members to 0. Fits() : fptr(0), status(0), behavior(0) {} /// @brief Open or create a FITS file from disk. Fits(std::string const & filename, std::string const & mode, int behavior); /// @brief Open or create a FITS file from an in-memory file. Fits(MemFileManager & manager, std::string const & mode, int behavior); /// @brief Close a FITS file. void closeFile(); ~Fits() { if ((fptr) && (behavior & AUTO_CLOSE)) closeFile(); } void * fptr; // the actual cfitsio fitsfile pointer; void to avoid including fitsio.h here. int status; // the cfitsio status indicator that gets passed to every cfitsio call. int behavior; // bitwise OR of BehaviorFlags }; #endif // !SWIG }}} /// namespace lsst::afw::fits #endif // !LSST_AFW_fits_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    9aed7dca

    commit 9aed7dca2a8918e773f684864a5dd5c14cffd068
    Author: Jim Bosch 
    Date:   Tue Feb 7 18:25:38 2012 -0500
    
        reworked FITS utilities to use std::string instead of char const * across the board, added some support for long string keywords
    

    d5769d71

    commit d5769d717344b92f2c6cbb130f1e65963d6e0336
    Author: Jim Bosch 
    Date:   Wed Dec 12 12:26:31 2012 -0500
    
        FitsError now inherits from IoErrorException rather than Exception
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    f0bfbada

    commit f0bfbadaff11412a8f9be9c9343935b947ec9f77
    Author: Jim Bosch 
    Date:   Wed Jul 9 18:24:39 2014 -0400
    
        Fix copy-paste error in Fits::writeKey
    

    Return to list

    python/lsst/afw/table/Base.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    /*
                     * Wrappers for BaseTable, BaseRecord, BaseColumnView, and their dependencies (including Schema
                     * and SchemaMapper and their components).  Also includes Catalog.i and instantiates BaseCatalog.
                     *
                     * This file does not include Simple-, Source-, or Exposure- Record/Table/Catalog, or the matching
                     * functions.
                     */
                    
                    %{
    
    32 29b582cc - #define PY_ARRAY_UNIQUE_SYMBOL LSST_AFW_TABLE_NUMPY_ARRAY_API
    33 29b582cc - #include "numpy/arrayobject.h"
    34 29b582cc - #include "ndarray/swig.h"
    #include "lsst/pex/logging.h" #include "lsst/afw/geom/Angle.h" #include "lsst/afw/coord.h" #include "lsst/afw/fits.h" #include "lsst/afw/table/BaseRecord.h" #include "lsst/afw/table/BaseTable.h" #include "lsst/afw/table/SchemaMapper.h" #include "lsst/afw/table/BaseColumnView.h" #include "lsst/afw/table/Catalog.h" // This enables numpy array conversion for Angle, converting it to a regular array of double. namespace ndarray { namespace detail { template <> struct NumpyTraits : public NumpyTraits {}; }} %} // Macro that provides a Python-side dynamic cast. // The BASE argument should be the root of the class hierarchy, not the immediate base class. %define %addCastMethod(CLS, BASE) %extend CLS { static PTR(CLS) _cast(PTR(BASE) base) { return boost::dynamic_pointer_cast< CLS >(base); } } %enddef %include "ndarray.i" %init %{ import_array(); %} %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(ndarray::Array); %declareNumPyConverters(Eigen::Matrix); %declareNumPyConverters(Eigen::Matrix); %declareNumPyConverters(Eigen::Matrix); %declareNumPyConverters(Eigen::Matrix); %declareNumPyConverters(Eigen::Matrix); %declareNumPyConverters(Eigen::Matrix); %import "lsst/daf/base/baseLib.i" %import "lsst/afw/geom/geomLib.i" %import "lsst/afw/fits/fitsLib.i" %import "lsst/afw/coord/coordLib.i" %import "lsst/afw/geom/ellipses/ellipsesLib.i" // =============== miscellaneous bits ======================================================================= %pythoncode %{ from . import _syntax %} %include "lsst/afw/table/misc.h" // ---------------------------------------------------------------------------------------------------------
    126 29b582cc + // We prefer to convert std::set to a Python tuple, because SWIG's std::set wrapper
    127 29b582cc + // doesn't do many of the things a we want it do (pretty printing, comparison operators, ...),
    128 29b582cc + // and the expense of a deep copy shouldn't matter in this case. And it's easier to just do
    129 29b582cc + // the conversion than get involved in the internals's of SWIG's set wrapper to fix it.
    130 29b582cc +
    131 29b582cc + %{
    132 29b582cc + inline PyObject * convertNameSet(std::set const & input) {
    133 29b582cc + ndarray::PyPtr result(PyTuple_New(input.size()));
    134 29b582cc + if (!result) return 0;
    135 29b582cc + Py_ssize_t n = 0;
    136 29b582cc + for (std::set::const_iterator i = input.begin(); i != input.end(); ++i, ++n) {
    137 29b582cc + PyObject * s = PyString_FromStringAndSize(i->data(), i->size());
    138 29b582cc + if (!s) return 0;
    139 29b582cc + PyTuple_SET_ITEM(result.get(), n, s);
    140 29b582cc + }
    141 29b582cc + Py_INCREF(result.get());
    142 29b582cc + return result.get();
    143 29b582cc + }
    144 29b582cc +
    145 29b582cc + %}
    146 29b582cc +
    147 29b582cc + %typemap(out) std::set {
    148 29b582cc + $result = convertNameSet($1);
    149 29b582cc + }
    150 29b582cc +
    151 29b582cc + %typemap(out)
    152 29b582cc + std::set const &, std::set &, std::set const*, std::set*
    153 29b582cc + {
    154 29b582cc + // I'll never understand why swig passes pointers to reference typemaps, but it does.
    155 29b582cc + $result = convertNameSet(*$1);
    156 29b582cc + }
    157 29b582cc +
    // SWIG doesn't understand Schema::forEach, but the Schema interface provides no other // way of getting field names in definition order. This forEach functor records field names, // allowing the python asList Schema method to return schema items in an order consistent // with forEach. %{ struct _FieldNameExtractor { std::vector mutable * _vec; _FieldNameExtractor(std::vector * vec) : _vec(vec) { } template void operator()(lsst::afw::table::SchemaItem const & item) const { _vec->push_back(item.field.getName()); } }; %} // --------------------------------------------------------------------------------------------------------- // SchemaItem objects will often be temporaries, where we only want one of their members, as in // schema.find("field.name").key. That causes problems, because swig returns members by pointer // or by reference, and that reference dangles since the SchemaItem is a temporary. // In C++ it's safe, because the language guarantees that the temporaries won't be destroyed until the // end of the statement, but in Python it's guaranteed undefined behavior. // To get around this, we don't let swig see the innards of the SchemaItem definition (it's #ifdef'd out), // and we replace it with the following: %extend lsst::afw::table::SchemaItem { // these force return-by-value lsst::afw::table::Field< T > getField() const { return self->field; } lsst::afw::table::Key< T > getKey() const { return self->key; } // now some properties to make the Python interface look like the C++ one %pythoncode %{ field = property(getField) key = property(getKey) %} }
    197 7940a365 + // =============== AliasMap =================================================================================
    198 7940a365 +
    199 7940a365 + %include "std_map.i"
    200 7940a365 + %include "std_pair.i"
    201 7940a365 + %include "lsst/afw/utils.i"
    202 7940a365 + %template(AliasMapPair) std::pair;
    203 7940a365 + %template(AliasMapInternal) std::map;
    204 7940a365 + %shared_ptr(lsst::afw::table::AliasMap);
    205 7940a365 + %include "lsst/afw/table/AliasMap.h"
    206 1cdc3abd + %useValueEquality(lsst::afw::table::AliasMap)
    207 7940a365 + %extend lsst::afw::table::AliasMap {
    208 7940a365 + %pythoncode %{
    209 7940a365 +
    210 7940a365 + def iteritems(self):
    211 7940a365 + i = self.begin()
    212 7940a365 + end = self.end()
    213 7940a365 + while i != end:
    214 7940a365 + yield i.value()
    215 7940a365 + i.incr()
    216 7940a365 + def iterkeys(self):
    217 7940a365 + for k, v in self.iteritems():
    218 7940a365 + yield k
    219 7940a365 + def itervalues(self):
    220 7940a365 + for k, v in self.iteritems():
    221 7940a365 + yield v
    222 7940a365 + def __iter__(self):
    223 7940a365 + return self.iterkeys()
    224 7940a365 +
    225 7940a365 + def items(self): return list(self.iteritems())
    226 7940a365 + def keys(self): return list(self.iterkeys())
    227 7940a365 + def values(self): return list(self.itervalues())
    228 7940a365 +
    229 7940a365 + def __getitem__(self, alias): return self.get(alias)
    230 7940a365 + def __setitem__(self, alias, target): self.set(alias, target)
    231 1f4ec8d4 + def __delitem__(self, alias):
    232 1f4ec8d4 + if not self.erase(alias):
    233 1f4ec8d4 + raise KeyError(alias)
    234 7940a365 + def __len__(self): return self.size()
    235 7940a365 + def __nonzero__(self): return not self.empty()
    236 7940a365 + %}
    237 7940a365 + }
    238 7940a365 +
    // =============== Schemas and their components ============================================================= %include "lsst/afw/table/FieldBase.h" %include "lsst/afw/table/Field.h" %include "lsst/afw/table/KeyBase.h" %include "lsst/afw/table/Key.h" %include "lsst/afw/table/detail/SchemaImpl.h"
    176 057fb3c0 - %include "std_set.i"
    177 057fb3c0 - %template(NameSet) std::set;
    %rename("__eq__") lsst::afw::table::Schema::operator==; %rename("__ne__") lsst::afw::table::Schema::operator!=; %rename("__getitem__") lsst::afw::table::Schema::operator[]; %rename("__getitem__") lsst::afw::table::SubSchema::operator[]; %addStreamRepr(lsst::afw::table::Schema) %include "lsst/afw/table/Schema.h" %extend lsst::afw::table::SchemaItem { %pythoncode %{ def __getitem__(self, i): if i == 0: return self.key elif i == 1: return self.field raise IndexError("SchemaItem index must be 0 or 1") def __str__(self): return str(tuple(self)) def __repr__(self): return "SchemaItem(%r, %r)" % (self.key, self.field) %} } %extend lsst::afw::table::Schema { void reset(lsst::afw::table::Schema & other) { *self = other; } std::vector getOrderedNames() { std::vector names; self->forEach(_FieldNameExtractor(&names)); return names; } %pythoncode %{ extract = _syntax.Schema_extract def asList(self): # This should be replaced by an implementation that uses Schema::forEach directly # if/when SWIG gets better at handling templates or we switch to Boost.Python. result = [] for name in self.getOrderedNames(): result.append(self.find(name)) return result def __iter__(self): return iter(self.asList()) def __contains__(self, k): try: r = self.find(k) return True except: return False def find(self, k): if not isinstance(k, basestring): try: prefix, suffix = type(k).__name__.split("_") except Exception: raise TypeError("Argument to Schema.find must be a string or Key.") if prefix != "Key": raise TypeError("Argument to Schema.find must be a string or Key.") attr = "_find_" + suffix method = getattr(self, attr) return method(k) for suffix in _suffixes.itervalues(): attr = "_find_" + suffix method = getattr(self, attr) try: return method(k)
    249 29b582cc - except Exception:
    318 55b692d5 + except (lsst.pex.exceptions.TypeError, lsst.pex.exceptions.NotFoundError):
    pass raise KeyError("Field '%s' not found in Schema." % k) def addField(self, field, type=None, doc="", units="", size=None, doReplace=False): if type is None: try: prefix, suffix = __builtins__['type'](field).__name__.split("_") except Exception: raise TypeError("First argument to Schema.addField must be a Field if 'type' is not given.") if prefix != "Field": raise TypeError("First argument to Schema.addField must be a Field if 'type' is not given.") attr = "_addField_" + suffix method = getattr(self, attr) return method(field) if not isinstance(type, basestring): type = aliases[type] suffix = _suffixes[type] attr = "_addField_" + suffix method = getattr(self, attr) if size is None: size = globals()["FieldBase_" + suffix]() else: size = globals()["FieldBase_" + suffix](size) return method(field, doc, units, size, doReplace) %} } // %extend Schema %extend lsst::afw::table::SubSchema { %pythoncode %{ def find(self, k): for suffix in _suffixes.itervalues(): attr = "_find_" + suffix method = getattr(self, attr) try: return method(k)
    288 29b582cc - except Exception:
    357 55b692d5 + except (lsst.pex.exceptions.TypeError, lsst.pex.exceptions.NotFoundError):
    pass raise KeyError("Field '%s' not found in Schema." % self.getPrefix()) def asField(self): for suffix in _suffixes.itervalues(): attr = "_asField_" + suffix method = getattr(self, attr) try: return method()
    298 29b582cc - except Exception:
    367 55b692d5 + except (lsst.pex.exceptions.TypeError, lsst.pex.exceptions.NotFoundError):
    pass raise KeyError("Field '%s' not found in Schema." % self.getPrefix()) def asKey(self): for suffix in _suffixes.itervalues(): attr = "_asKey_" + suffix method = getattr(self, attr) try: return method()
    308 29b582cc - except Exception:
    377 55b692d5 + except (lsst.pex.exceptions.TypeError, lsst.pex.exceptions.NotFoundError):
    pass raise KeyError("Field '%s' not found in Schema." % self.getPrefix()) %} } // %extend SubSchema %ignore lsst::afw::table::SchemaMapper::operator=; %include "lsst/afw/table/SchemaMapper.h" %template(SchemaVector) std::vector; %template(SchemaMapperVector) std::vector;
    391 cfb9c7f4 + // =============== FunctorKeys ==============================================================================
    392 cfb9c7f4 +
    393 9c6a2ba4 + // We need the extend blocks in the macros below because we've removed the FunctorKey overloads of
    394 9c6a2ba4 + // get() and set() in the .h file via an #ifdef SWIG. We had to do that to avoid instantiating the
    395 9c6a2ba4 + // FunctorKey overloads for the same types we instantiate the non-FunctorKey overloads (when you use
    396 9c6a2ba4 + // Swig's %template statement on a templated function or member function, if instantiates all
    397 9c6a2ba4 + // overloads).
    398 9c6a2ba4 +
    399 cfb9c7f4 + %include "lsst/afw/table/FunctorKey.h"
    400 29b582cc +
    401 9c6a2ba4 + %define %declareOutputFunctorKey(PYNAME, U...)
    402 9c6a2ba4 + %shared_ptr(lsst::afw::table::OutputFunctorKey< U >);
    403 9c6a2ba4 + %template(OutputFunctorKey ## PYNAME) lsst::afw::table::OutputFunctorKey< U >;
    404 9c6a2ba4 + %enddef
    405 9c6a2ba4 +
    406 9c6a2ba4 + %define %declareInputFunctorKey(PYNAME, U...)
    407 9c6a2ba4 + %shared_ptr(lsst::afw::table::InputFunctorKey< U >);
    408 9c6a2ba4 + %template(InputFunctorKey ## PYNAME) lsst::afw::table::InputFunctorKey< U >;
    409 9c6a2ba4 + %enddef
    410 9c6a2ba4 +
    411 9c6a2ba4 + %define %declareFunctorKey(PYNAME, U...)
    412 9c6a2ba4 + %declareOutputFunctorKey(PYNAME, U)
    413 9c6a2ba4 + %declareInputFunctorKey(PYNAME, U)
    414 9c6a2ba4 + %shared_ptr(lsst::afw::table::FunctorKey< U >);
    415 9c6a2ba4 + %template(FunctorKey ## PYNAME) lsst::afw::table::FunctorKey< U >;
    416 9c6a2ba4 + %enddef
    417 9c6a2ba4 +
    418 e83c9f0f + %define %declareReferenceFunctorKey(PYNAME, U...)
    419 e83c9f0f + %shared_ptr(lsst::afw::table::ReferenceFunctorKey< U >);
    420 e83c9f0f + %nodefaultctor lsst::afw::table::ReferenceFunctorKey< U >;
    421 e83c9f0f + %template(ReferenceFunctorKey ## PYNAME) lsst::afw::table::ReferenceFunctorKey< U >;
    422 e83c9f0f + %enddef
    423 e83c9f0f +
    424 e83c9f0f + %define %declareConstReferenceFunctorKey(PYNAME, U...)
    425 e83c9f0f + %shared_ptr(lsst::afw::table::ConstReferenceFunctorKey< U >);
    426 e83c9f0f + %nodefaultctor lsst::afw::table::ConstReferenceFunctorKey< U >;
    427 e83c9f0f + %template(ConstReferenceFunctorKey ## PYNAME) lsst::afw::table::ConstReferenceFunctorKey< U >;
    428 e83c9f0f + %enddef
    // =============== BaseTable and BaseRecord ================================================================= %shared_ptr(lsst::afw::table::BaseTable); %shared_ptr(lsst::afw::table::BaseRecord); %include "lsst/afw/table/BaseTable.h" %extend lsst::afw::table::BaseTable { %pythoncode %{ schema = property(getSchema) def cast(self, type_): return type_._cast(self) %} } %ignore lsst::afw::table::BaseRecord::operator=; %include "lsst/afw/table/BaseRecord.h" %extend lsst::afw::table::BaseRecord { %pythoncode %{ extract = _syntax.BaseRecord_extract table = property(lambda self: self.getTable()) # extra lambda allows for polymorphism in property schema = property(getSchema) def cast(self, type_): return type_._cast(self) %}
    349 29b582cc - // Allow field name strings be used in place of keys (but only in Python)
    350 29b582cc - %pythonprepend __getitem__ %{
    456 e83c9f0f + %feature("shadow") __getitem__ %{
    457 e83c9f0f + def __getitem__(self, key):
    351 29b582cc - if isinstance(args[0], basestring):
    ? ^^^^^^^
    458 e83c9f0f + if isinstance(key, basestring):
    ? ^^^
    352 29b582cc - return self[self.schema.find(args[0]).key]
    ? ^^^^^^^
    459 e83c9f0f + return self[self.schema.find(key).key]
    ? ^^^
    460 e83c9f0f + try:
    461 e83c9f0f + return $action(self, key)
    462 e83c9f0f + except NotImplementedError:
    463 e83c9f0f + # If this doesn't work as a regular key, try it as a FunctorKey
    464 e83c9f0f + return key.get(self)
    %} %pythonprepend __setitem__ %{ if isinstance(args[0], basestring): self[self.schema.find(args[0]).key] = args[1] return %}
    359 29b582cc - %pythonprepend get %{
    471 e83c9f0f + // Allow field name strings be used in place of keys (but only in Python)
    472 9c6a2ba4 + %feature("shadow") get %{
    473 9c6a2ba4 + def get(self, key):
    360 29b582cc - if isinstance(args[0], basestring):
    ? ^^^^^^^
    474 9c6a2ba4 + if isinstance(key, basestring):
    ? ^^^
    361 29b582cc - return self.get(self.schema.find(args[0]).key)
    ? ^^^^^^^
    475 9c6a2ba4 + return self.get(self.schema.find(key).key)
    ? ^^^
    476 9c6a2ba4 + try:
    477 9c6a2ba4 + return $action(self, key)
    478 9c6a2ba4 + except NotImplementedError:
    479 9c6a2ba4 + # If this doesn't work as a regular key, try it as a FunctorKey
    480 9c6a2ba4 + return key.get(self)
    %}
    363 29b582cc - %pythonprepend set %{
    482 9c6a2ba4 + %feature("shadow") set %{
    483 9c6a2ba4 + def set(self, key, value):
    364 29b582cc - if isinstance(args[0], basestring):
    ? ^^^^^^^
    484 9c6a2ba4 + if isinstance(key, basestring):
    ? ^^^
    365 29b582cc - self.set(self.schema.find(args[0]).key, args[1])
    ? ^^^^^^^ ^^^^^^
    485 9c6a2ba4 + self.set(self.schema.find(key).key, value)
    ? ^^^ + ^^^ return
    487 9c6a2ba4 + try:
    488 9c6a2ba4 + $action(self, key, value)
    489 9c6a2ba4 + except NotImplementedError:
    490 9c6a2ba4 + # If this doesn't work as a regular key, try it as a FunctorKey
    491 9c6a2ba4 + return key.set(self, value)
    %}
    493 9c6a2ba4 +
    } %addCastMethod(lsst::afw::table::BaseTable, lsst::afw::table::BaseTable) %addCastMethod(lsst::afw::table::BaseRecord, lsst::afw::table::BaseRecord) %usePointerEquality(lsst::afw::table::BaseRecord) %usePointerEquality(lsst::afw::table::BaseTable) // =============== BaseColumnView =========================================================================== %template(FlagKeyVector) std::vector< lsst::afw::table::Key< lsst::afw::table::Flag > >; %feature("shadow") lsst::afw::table::BaseColumnView::getBits %{ def getBits(self, keys=None): if keys is None: return self.getAllBits() arg = FlagKeyVector() for k in keys: if isinstance(k, basestring): arg.append(self.schema.find(k).key) else: arg.append(k) return $action(self, arg) %} %include "lsst/afw/table/BaseColumnView.h" %extend lsst::afw::table::BitsColumn { PyObject * getSchemaItems() const { // Can't use SWIG's std::vector wrapper because SchemaItem doesn't have a default // ctor. And we want to return a list anyway, so you can print it easily and not // worry about dangling references and implicit const-casts. PyObject * result = PyList_New(0); typedef std::vector< lsst::afw::table::SchemaItem > ItemVector; for ( ItemVector::const_iterator i = self->getSchemaItems().begin(); i != self->getSchemaItems().end(); ++i ) { PyObject * pyItem = SWIG_NewPointerObj( new lsst::afw::table::SchemaItem(*i), SWIGTYPE_p_lsst__afw__table__SchemaItemT_lsst__afw__table__Flag_t, true // SWIG takes ownership of the pointer ); if (!pyItem) { Py_DECREF(result); return NULL; } if (PyList_Append(result, pyItem) != 0) { Py_DECREF(result); Py_DECREF(pyItem); return NULL; } } return result; } %pythoncode %{ array = property(getArray) %} } %extend lsst::afw::table::BaseColumnView { %pythoncode %{ extract = _syntax.BaseColumnView_extract table = property(getTable) schema = property(getSchema) def get(self, key): """Return the column for the given key or field name; synonym for __getitem__.""" return self[key] %} // Allow field name strings be used in place of keys (but only in Python) %pythonprepend __getitem__ %{ if isinstance(args[0], basestring): return self[self.schema.find(args[0]).key] %} } // =============== Field Types ============================================================================== // Must come after the FlagKeyVector %template, or SWIG bungles the generated code. %include "lsst/afw/table/Flag.h" %pythoncode %{ from ..geom import Angle, Point2D, Point2I from ..geom.ellipses import Quadrupole from ..coord import Coord, IcrsCoord import numpy Field = {} Key = {} SchemaItem = {} _suffixes = {} aliases = { int: "I", long: "L", float: "D", str: "String", numpy.uint16: "U", numpy.int32: "I", numpy.int64: "L", numpy.float32: "F", numpy.float64: "D", Angle: "Angle", Coord: "Coord", IcrsCoord: "Coord", Point2I: "PointI", Point2D: "PointD", Quadrupole: "MomentsD", } %} %define %declareFieldType(CNAME, PYNAME) %rename("_eq_impl") lsst::afw::table::Key< CNAME >::operator==; %extend lsst::afw::table::Key< CNAME > { %pythoncode %{ def __eq__(self, other): if type(other) != type(self): return NotImplemented return self._eq_impl(other) def __ne__(self, other): return not self == other %} } %template(FieldBase_ ## PYNAME) lsst::afw::table::FieldBase< CNAME >; %template(Field_ ## PYNAME) lsst::afw::table::Field< CNAME >; %template(KeyBase_ ## PYNAME) lsst::afw::table::KeyBase< CNAME >; %template(Key_ ## PYNAME) lsst::afw::table::Key< CNAME >; %template(SchemaItem_ ## PYNAME) lsst::afw::table::SchemaItem< CNAME >; %addStreamRepr(lsst::afw::table::Field< CNAME >); %addStreamRepr(lsst::afw::table::Key< CNAME >); %pythoncode %{ Field[FieldBase_ ## PYNAME.getTypeString()] = Field_ ## PYNAME Key[FieldBase_ ## PYNAME.getTypeString()] = Key_ ## PYNAME SchemaItem[FieldBase_ ## PYNAME.getTypeString()] = SchemaItem_ ## PYNAME _suffixes[FieldBase_ ## PYNAME.getTypeString()] = #PYNAME %} %extend lsst::afw::table::Schema { %template(_find_ ## PYNAME) find< CNAME >; %template(_addField_ ## PYNAME) addField< CNAME >; %template(replaceField) replaceField< CNAME >; } %extend lsst::afw::table::SubSchema { %template(_find_ ## PYNAME) find< CNAME >; lsst::afw::table::Field< CNAME > _asField_ ## PYNAME() const { return *self; } lsst::afw::table::Key< CNAME > _asKey_ ## PYNAME() const { return *self; } } %extend lsst::afw::table::SchemaMapper { %template(addOutputField) addOutputField< CNAME >; %template(addMapping) addMapping< CNAME >; %template(getMapping) getMapping< CNAME >; } %implicitconv FieldBase_ ## PYNAME; %enddef %declareFieldType(boost::uint16_t, U) %declareFieldType(boost::int32_t, I) %declareFieldType(boost::int64_t, L) %declareFieldType(float, F) %declareFieldType(double, D) %declareFieldType(std::string, String) %declareFieldType(lsst::afw::table::Flag, Flag) %declareFieldType(lsst::afw::geom::Angle, Angle) %declareFieldType(lsst::afw::coord::Coord, Coord) %declareFieldType(lsst::afw::table::Point, PointI) %declareFieldType(lsst::afw::table::Point, PointD) %declareFieldType(lsst::afw::table::Moments, MomentsD) %declareFieldType(lsst::afw::table::Array, ArrayU) %declareFieldType(lsst::afw::table::Array, ArrayI) %declareFieldType(lsst::afw::table::Array, ArrayF) %declareFieldType(lsst::afw::table::Array, ArrayD) %declareFieldType(lsst::afw::table::Covariance, CovF) %declareFieldType(lsst::afw::table::Covariance< lsst::afw::table::Point >, CovPointF) %declareFieldType(lsst::afw::table::Covariance< lsst::afw::table::Moments >, CovMomentsF) %include "lsst/afw/table/specializations.i" %pythoncode %{ # underscores here prevent these from becoming global names for _d in (Field, Key, SchemaItem, _suffixes): for _k, _v in aliases.iteritems(): _d[_k] = _d[_v] %} // =============== Catalogs ================================================================================= %include "lsst/afw/table/Catalog.i" namespace lsst { namespace afw { namespace table { %declareCatalog(CatalogT, Base) }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    29b582cc

    commit 29b582ccfe0b1381c2876ac1a58f43ce23550f9e
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:52:56 2013 -0500
    
        Overhaul afw::table SWIG to enable more fine-grained %imports.
    

    057fb3c0

    commit 057fb3c0581c512d5664f1883a72da950c9eae9d
    Author: Jim Bosch 
    Date:   Tue Jun 24 09:54:51 2014 -0400
    
        Remove customization of std::set wrappers.
        
        This made for a nicer Python interface, but it was blocking downstream packages
        from using std::set at all.
    

    Commits in /Users/nate/repos_lsst/afw/

    29b582cc

    commit 29b582ccfe0b1381c2876ac1a58f43ce23550f9e
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:52:56 2013 -0500
    
        Overhaul afw::table SWIG to enable more fine-grained %imports.
    

    1cdc3abd

    commit 1cdc3abd3e98c1e71e2a76754e02ece73b08230c
    Author: Jim Bosch 
    Date:   Wed Jan 21 16:56:28 2015 -0500
    
        Include aliases in Schema comparison methods.
    

    55b692d5

    commit 55b692d5d02e72b84aa9efe49e1d212f0a807db5
    Author: Jim Bosch 
    Date:   Mon Oct 6 12:51:46 2014 -0400
    
        Be more consistent about exceptions thrown/caught in Schema::find
        
        The Python-level code, which loops over all the C++ template instantiations until it
        finds one that doesn't throw, was catching all Exceptions, not just those that meant
        the field couldn't be found with the given type.
    

    9c6a2ba4

    commit 9c6a2ba4aa3f22cc3d4a5e264855029dd6a73ea7
    Author: Jim Bosch 
    Date:   Thu Apr 10 15:00:34 2014 -0400
    
        Python interface for FunctorKeys
    

    1f4ec8d4

    commit 1f4ec8d43083ba12f4896c8e05727435de82247b
    Author: Jim Bosch 
    Date:   Fri Jul 11 18:26:39 2014 -0400
    
        Minor tweaks to AliasMap for review of DM-417
    

    cfb9c7f4

    commit cfb9c7f46b1c0486102a1eb7e2caa7032eee2efc
    Author: Jim Bosch 
    Date:   Wed Apr 9 11:41:43 2014 -0400
    
        Started work on FunctorKey
    

    e83c9f0f

    commit e83c9f0fc32ce0bd64230bb765cbdb28e06916b2
    Author: Jim Bosch 
    Date:   Sat Sep 20 08:24:50 2014 -0400
    
        Add base classes for FunctorKeys that return reference objects
    

    7940a365

    commit 7940a365d3229ef5de7be5ab6fc57ba5fbcaa2b1
    Author: Jim Bosch 
    Date:   Thu Jul 10 17:27:08 2014 -0400
    
        Better Swig, unit tests, and implementation fixes for AliasMap
    

    Return to list

    python/lsst/afw/math/background.py

    Diff:

                    # 
                    # LSST Data Management System
                    # Copyright 2008, 2009, 2010 LSST Corporation.
                    # 
                    # This product includes software developed by the
                    # LSST Project (http://www.lsst.org/).
                    #
                    # This program is free software: you can redistribute it and/or modify
                    # it under the terms of the GNU General Public License as published by
                    # the Free Software Foundation, either version 3 of the License, or
                    # (at your option) any later version.
                    # 
                    # This program is distributed in the hope that it will be useful,
                    # but WITHOUT ANY WARRANTY; without even the implied warranty of
                    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    # GNU General Public License for more details.
                    # 
                    # You should have received a copy of the LSST License Statement and 
                    # the GNU General Public License along with this program.  If not, 
                    # see .
                    #
                    import os
                    import sys
                    import lsst.daf.base as dafBase
                    import lsst.pex.exceptions as pexExcept
                    import lsst.afw.geom as afwGeom
                    import lsst.afw.image as afwImage
                    from lsst.afw.fits import FitsError, MemFileManager, reduceToFits
                    import mathLib as afwMath
                    
                    class BackgroundList(object):
                        """A list-like class to contain a list of (afwMath.Background, interpStyle, undersampleStyle) tuples
                    
                    In deference to the deprecated-but-not-yet-removed Background.getImage() API, we also accept a single
                    afwMath.Background and extract the interpStyle and undersampleStyle from the as-used values
                        """
                        
                        def __init__(self, *args):
                            self._backgrounds = []
                            for a in args:
                                self.append(a)
                    
                        def __getitem__(self, *args):
                            """Return an item"""
                            #
                            # Set any previously-unknown Styles (they are set by bkgd.getImage())
                            #
                            for i, val in enumerate(self._backgrounds):
    
    49 264e671e - bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY = val
    49 c16ef84d + bkgd, interpStyle, undersampleStyle = val
    if interpStyle is None or undersampleStyle is None: interpStyle = bkgd.getAsUsedInterpStyle() undersampleStyle = bkgd.getAsUsedUndersampleStyle()
    53 13cd7b6a - actrl = bkgd.getBackgroundControl().getApproximateControl()
    54 13cd7b6a - approxStyle = actrl.getStyle()
    55 264e671e - approxOrderX = actrl.getOrderX()
    56 264e671e - approxOrderY = actrl.getOrderY()
    57 264e671e - self._backgrounds[i] = (bkgd, interpStyle, undersampleStyle,
    ? ^
    53 c16ef84d + self._backgrounds[i] = (bkgd, interpStyle, undersampleStyle)
    ? ^
    58 264e671e - approxStyle, approxOrderX, approxOrderY)
    # # And return what they wanted # return self._backgrounds.__getitem__(*args) def __len__(self, *args): return self._backgrounds.__len__(*args) def append(self, val): try:
    69 264e671e - bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY = val
    64 c16ef84d + bkgd, interpStyle, undersampleStyle = val
    except TypeError: bkgd = val interpStyle = None undersampleStyle = None
    74 13cd7b6a - approxStyle = None
    75 264e671e - approxOrderX = None
    76 264e671e - approxOrderY = None
    # Check to see if the Background is actually a BackgroundMI. # Such special treatment is not generally a good idea as it is against the whole idea of subclassing. # However, lsst.afw.math.makeBackground() returns a Background, even though it's really a BackgroundMI # under the covers. Persistence requires that the type python sees is the actual type under the covers # (or it will call the wrong python class's python persistence methods). # The real solution is to not use makeBackground() in python but call the constructor directly; # however there is already code using makeBackground(), so this is an attempt to assist the user. subclassed = afwMath.cast_BackgroundMI(bkgd) if subclassed is not None: bkgd = subclassed else: from lsst.pex.logging import getDefaultLog getDefaultLog().warn("Unrecognised Background object %s may be unpersistable." % (bkgd,))
    84 65b8e9b5 + self._backgrounds.append((bkgd, interpStyle, undersampleStyle))
    92 264e671e - bgInfo = (bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY)
    93 264e671e - self._backgrounds.append(bgInfo)
    def writeFits(self, fileName, flags=0): """Save our list of Backgrounds to a file @param fileName FITS file to write @param flags Flags to control details of writing; currently unused, but present for consistency with afw.table.BaseCatalog.writeFits. """ for i, bkgd in enumerate(self):
    104 264e671e - bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY = bkgd
    95 c16ef84d + bkgd, interpStyle, undersampleStyle = bkgd
    statsImage = bkgd.getStatsImage() md = dafBase.PropertyList() md.set("INTERPSTYLE", interpStyle) md.set("UNDERSAMPLESTYLE", undersampleStyle)
    111 13cd7b6a - md.set("APPROXSTYLE", approxStyle)
    112 264e671e - md.set("APPROXORDERX", approxOrderX)
    113 264e671e - md.set("APPROXORDERY", approxOrderY)
    bbox = bkgd.getImageBBox() md.set("BKGD_X0", bbox.getMinX()) md.set("BKGD_Y0", bbox.getMinY()) md.set("BKGD_WIDTH", bbox.getWidth()) md.set("BKGD_HEIGHT", bbox.getHeight()) statsImage.getImage().writeFits( fileName, md, "w" if i == 0 else "a") statsImage.getMask().writeFits( fileName, md, "a") statsImage.getVariance().writeFits(fileName, md, "a") @staticmethod def readFits(fileName, hdu=0, flags=0): """Read a our list of Backgrounds from a file @param fileName FITS file to read @param hdu First Header/Data Unit to attempt to read from @param flags Flags to control details of reading; currently unused, but present for consistency with afw.table.BaseCatalog.readFits. See also getImage() """ if not isinstance(fileName, MemFileManager) and not os.path.exists(fileName): raise RuntimeError("File not found: %s" % fileName) self = BackgroundList() while True: hdu += 1 md = dafBase.PropertyList() try: img = afwImage.ImageF(fileName, hdu, md); hdu += 1
    134 6fc1c3d1 + except FitsError as e:
    146 883e4114 - except pexExcept.LsstCppException, e:
    147 883e4114 - if isinstance(e.args[0], FitsError):
    148 883e4114 - break
    ? ----
    135 6fc1c3d1 + break
    149 883e4114 - raise
    msk = afwImage.MaskU( fileName, hdu); hdu += 1 var = afwImage.ImageF(fileName, hdu) statsImage = afwImage.makeMaskedImage(img, msk, var) x0 = md.get("BKGD_X0") y0 = md.get("BKGD_Y0") width = md.get("BKGD_WIDTH") height = md.get("BKGD_HEIGHT") imageBBox = afwGeom.BoxI(afwGeom.PointI(x0, y0), afwGeom.ExtentI(width, height)) interpStyle = md.get("INTERPSTYLE") undersampleStyle = md.get("UNDERSAMPLESTYLE")
    165 264e671e - # older outputs won't have APPROX* settings. Provide alternative defaults.
    166 13cd7b6a - approxStyle = md.get("APPROXSTYLE") if "APPROXSTYLE" in md.names() \
    167 13cd7b6a - else afwMath.ApproximateControl.UNKNOWN
    168 264e671e - approxOrderX = md.get("APPROXORDERX") if "APPROXORDERX" in md.names() else 1
    169 264e671e - approxOrderY = md.get("APPROXORDERY") if "APPROXORDERY" in md.names() else -1
    170 883e4114 -
    bkgd = afwMath.BackgroundMI(imageBBox, statsImage)
    152 883e4114 + self.append((bkgd, interpStyle, undersampleStyle,))
    172 264e671e - bctrl = bkgd.getBackgroundControl()
    173 264e671e - bctrl.setInterpStyle(interpStyle)
    174 264e671e - bctrl.setUndersampleStyle(undersampleStyle)
    175 264e671e - actrl = afwMath.ApproximateControl(approxStyle, approxOrderX, approxOrderY)
    176 264e671e - bctrl.setApproximateControl(actrl)
    177 264e671e - bgInfo = (bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY)
    178 264e671e - self.append(bgInfo)
    return self def getImage(self): """ Compute and return a full-resolution image from our list of (Background, interpStyle, undersampleStyle) """ bkgdImage = None
    188 264e671e - for bkgd, interpStyle, undersampleStyle, approxStyle, approxOrderX, approxOrderY in self:
    162 883e4114 + for bkgd, interpStyle, undersampleStyle in self:
    if not bkgdImage:
    190 130966a3 - if approxStyle != afwMath.ApproximateControl.UNKNOWN:
    191 130966a3 - bkgdImage = bkgd.getImageF()
    192 130966a3 - else:
    193 130966a3 - bkgdImage = bkgd.getImageF(interpStyle, undersampleStyle)
    ? ----
    164 883e4114 + bkgdImage = bkgd.getImageF(interpStyle, undersampleStyle)
    ? + else:
    195 130966a3 - if approxStyle != afwMath.ApproximateControl.UNKNOWN:
    196 130966a3 - bkgdImage += bkgd.getImageF()
    197 130966a3 - else:
    198 130966a3 - bkgdImage += bkgd.getImageF(interpStyle, undersampleStyle)
    ? ----
    166 883e4114 + bkgdImage += bkgd.getImageF(interpStyle, undersampleStyle)
    return bkgdImage def __reduce__(self): return reduceToFits(self)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    13cd7b6a

    commit 13cd7b6a7bcaaed466148aa40fa2db5fc4809d28
    Author: Steven Bickerton 
    Date:   Thu Oct 16 19:23:42 2014 +0900
    
        Allow background to persist info about approx
    

    883e4114

    commit 883e41145dc276f8fd42185b7cc16c26d6ddebdc
    Author: Robert Lupton the Good 
    Date:   Tue Mar 12 06:37:25 2013 +0900
    
        Add BackgroundList object so as to allow the butler to handle I/O
    

    130966a3

    commit 130966a325fa622e486c1e5a049cea9da5a1520b
    Author: Steven Bickerton 
    Date:   Mon Oct 27 14:48:35 2014 +0900
    
        Handle BackgroundList properly with approx code (from code review)
    

    264e671e

    commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
    Author: Steven Bickerton 
    Date:   Fri Oct 24 14:37:15 2014 +0900
    
        Use shared_ptr.  Add test.  Disable double,int backgrounds.
    

    Commits in /Users/nate/repos_lsst/afw/

    65b8e9b5

    commit 65b8e9b522cb4d92402c3272872d57d1e832ce29
    Author: Paul Price 
    Date:   Fri Feb 7 16:11:23 2014 -0500
    
        Background: make BackgroundMI and BackgroundList picklable
        
        Note that an item returned by lsst.afw.math.makeBackground() cannot be
        pickled directly (it's difficult to properly pickle SWIGed polymorphic
        objects).  The current workaround is to cast it to a BackgroundMI; best
        would be to not use polymorphism from python.
    

    c16ef84d

    commit c16ef84dbc57a40a79480b3b277261cb6bbe22c6
    Author: Robert Lupton the Good 
    Date:   Wed Apr 3 16:45:18 2013 -0400
    
        Cleanups as proposed by REO in code review for #2732
    

    883e4114

    commit 883e41145dc276f8fd42185b7cc16c26d6ddebdc
    Author: Robert Lupton the Good 
    Date:   Tue Mar 12 06:37:25 2013 +0900
    
        Add BackgroundList object so as to allow the butler to handle I/O
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    python/lsst/afw/geom/Angle.i

    Diff:

                    // -*- lsst-c++ -*-
                    %{
                        #include 
                        #include 
                        #include "lsst/afw/geom/Angle.h"
                    
                        using namespace lsst::afw::geom;
                    %}
                    
                    %ignore operator<<(std::ostream &s, Angle const a);
                    
                    %rename(__float__) lsst::afw::geom::Angle::operator double() const;
                    %rename(Angle_add) lsst::afw::geom::operator+;
                    %rename(Angle_sub) lsst::afw::geom::operator-;
                    %rename(Angle_mul) lsst::afw::geom::operator*;
                    %rename(Angle_div) lsst::afw::geom::operator/;
                    
                    %inline %{
                        lsst::afw::geom::Angle AngleUnit_mul(lsst::afw::geom::AngleUnit const& lhs, double rhs) {
                            return rhs*lhs;
                        }
                        lsst::afw::geom::Angle AngleUnit_mul(double lhs, lsst::afw::geom::AngleUnit const& rhs) {
                            return lhs*rhs;
                        }
                    %}
                    
                    %addStreamRepr(lsst::afw::geom::Angle)
                    
                    %extend lsst::afw::geom::Angle {
                        %pythoncode %{
                             def __reduce__(self):
                                 return (Angle, (self.asRadians(),))
                             def __abs__(self):
                                 return abs(self.asRadians())*radians;
                             def __add__(self, rhs):
                                 return Angle_add(self, rhs)
                             def __radd__(self, lhs):
                                 return Angle_add(lhs, self)
                             def __sub__(self, rhs):
                                 return Angle_sub(self, rhs)
                             def __rsub__(self, lhs):
                                 return Angle_sub(lhs, self)
                             def __mul__(self, rhs):
                                 return Angle_mul(self, rhs)
                             def __rmul__(self, lhs):
                                 return Angle_mul(lhs, self)
                             def __div__(self, rhs):
                                 return Angle_div(self, rhs)
                             def __rdiv__(self, lhs):
                                 return Angle_div(lhs, self)
                             def __eq__(self, rhs):
                                 try:
                                     return float(self) == float(rhs)
                                 except Exception:
                                     return NotImplemented
                             def __ne__(self, rhs):
                                 return not self == rhs
    
    58 b80fe1d3 + # support "__from__ future import division" in Python 2; not needed for Python 3
    59 b80fe1d3 + __truediv__ = __div__
    %} } %extend lsst::afw::geom::AngleUnit { %pythoncode %{ def __reduce__(self): return (AngleUnit, (1.0*self,)) def __mul__(self, rhs): return AngleUnit_mul(self, rhs) def __rmul__(self, lhs): return AngleUnit_mul(lhs, self) %} } %include "lsst/afw/geom/Angle.h" %template(isAngle) lsst::afw::geom::isAngle;

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    python/lsst/afw/utils.i

    Diff:

                    // -*- lsst-c++  -*-
                    //
                    // This should be in lsst/p_lsstSwig.i
                    //
                    //
                    // We'd like to just say
                    //  def __iter__(self):
                    //      return next()
                    // but this crashes, at least with swig 1.3.36
                    //
                    %define %definePythonIterator(TYPE...)
                    %extend TYPE {
    
    13 15272073 - %pythoncode {
    13 81c3bd10 + %pythoncode %{
    ? + def __iter__(self): ptr = self.begin() end = self.end() while True: if ptr == end: raise StopIteration yield ptr.value() ptr.incr() def __getitem__(self, i): return [e for e in self][i]
    26 15272073 - }
    26 81c3bd10 + %}
    ? + } %enddef

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    15272073

    commit 15272073e88db0b67866807af0e2f12edda8fae9
    Author: rhl 
    Date:   Fri Mar 26 17:14:01 2010 +0000
    
        Utils that should move to p_lsstSwig.i
    

    Commits in /Users/nate/repos_lsst/afw/

    81c3bd10

    commit 81c3bd106e6aa66e68d569426b87862d5d10f844
    Author: Russell Owen 
    Date:   Fri Mar 13 10:47:12 2015 -0700
    
        Change %python { to %python %{ in swig .i files
        
        Also outdent some cases where the resulting python
        appeared at the wrong indentation level in the interface file
        or a comment was chopped off at the beginning (including
        the leading #, resulting in comment text being treated as commands).
        
        Fix indentation errors
        
        SWIG 3.0.2 indents python code differently when using
        %pythoncode %{...%} instead of the deprecated %pythoncode {...}
        This fixes most known issues, but image slicing doesn't yet work.
        
        Make indentation of %pythoncode more robust in imageLib.i
    

    Return to list

    tests/testWarpGpu.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                    * @file
                    *
                    * @brief Times the speedup of GPU accelerated convolution
                    *
                    * @author Kresimir Cosic
                    *
                    * @ingroup afw
                    */
                    
    
    35 09e1306e -
    #include #include
    38 09e1306e -
    #include #include #include #include
    42 09e1306e + #include "lsst/daf/base.h"
    #include "lsst/utils/ieee.h"
    45 09e1306e - #include "lsst/daf/base.h"
    44 a9aec7fc + #include "lsst/utils/Utils.h"
    45 a9aec7fc + #include "lsst/pex/exceptions.h"
    #include "lsst/pex/exceptions.h" #include "lsst/pex/logging/Trace.h" #include "lsst/afw/image.h" #include "lsst/afw/geom.h" #include "lsst/afw/math.h" #include "lsst/afw/gpu/IsGpuBuild.h" #include "lsst/afw/gpu/DevicePreference.h" //Just for PrintCudaDeviceInfo #include "lsst/afw/gpu/detail/CudaQueryDevice.h" int const defaultInterpLen = 20; typedef int TestResult; using namespace std; using lsst::pex::logging::Trace; namespace pexEx = lsst::pex::exceptions; namespace afwImage = lsst::afw::image; namespace afwMath = lsst::afw::math; namespace afwGeom = lsst::afw::geom; //Calculates relative RMSD (coefficient of variation of the root-mean-square deviation) template double CvRmsd(const afwImage::Image& imgA, const afwImage::Image& imgB) { int const dimX = imgA.getWidth(); int const dimY = imgA.getHeight(); if (dimX != imgB.getWidth() || dimY != imgB.getHeight()) return NAN; double sqSum = 0; double avgSum = 0; int cnt = 0; for (int x = 0; x < dimX; x++) { for (int y = 0; y < dimY; y++) { const double valA = imgA(x, y); const double valB = imgB(x, y); if (lsst::utils::isnan(valA) || lsst::utils::isnan(valB)) continue; if (lsst::utils::isinf(valA) || lsst::utils::isinf(valB)) continue; cnt++; avgSum += (valA + valB) / 2; double const diff = valA - valB; sqSum += diff * diff; } } double rmsd = sqrt(sqSum / cnt); double avg = avgSum / cnt; return rmsd / avg; } //Returns number of different values template double DiffCnt(afwImage::Mask const& imgA, afwImage::Mask const& imgB) {
    103 09e1306e - typedef long long unsigned int Bitint;
    104 09e1306e -
    int const dimX = imgA.getWidth(); int const dimY = imgA.getHeight(); if (dimX != imgB.getWidth() || dimY != imgB.getHeight()) return NAN; int cnt = 0; for (int x = 0; x < dimX; x++) { for (int y = 0; y < dimY; y++) { const T valA = imgA(x, y); const T valB = imgB(x, y); if (valA != valB) cnt++; } } return cnt; } void PrintSeparator() { for (int i = 0; i < 79; i++) cout << "="; cout << endl; }
    131 09e1306e - string GetInputFileName(int argc, char **argv)
    ? ^^^ ^ ^^
    129 a9aec7fc + string GetInputImagePath(int argc, char **argv)
    ? ^^^^ ^ ^^ {
    133 5b522953 - string imgFileName;
    ? --- ^ ^^
    131 a9aec7fc + string inImagePath;
    ? ++ + ^ ^^ if (argc < 2) {
    135 09e1306e - string afwdata = getenv("AFWDATA_DIR");
    136 09e1306e - if (afwdata.empty()) {
    133 a9aec7fc + try {
    134 7cbb2bb9 + string dataDir = lsst::utils::getPackageDir("afwdata");
    135 a9aec7fc + inImagePath = dataDir + "/data/med.fits";
    136 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    137 09e1306e - std::cerr << "Usage: convolveGPU fitsFile" << endl;
    ? -----
    137 a9aec7fc + cerr << "Usage: convolveGPU [fitsFile]" << endl;
    ? + +
    138 a9aec7fc + cerr << "Warning: tests not run! Setup afwdata if you wish to use the default fitsFile." << endl;
    138 09e1306e - std::cerr << "fitsFile excludes the \"_img.fits\" suffix" << endl;
    139 09e1306e - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << endl;
    140 09e1306e - std::cerr << "Is afwdata set up?\n" << endl;
    exit(EXIT_FAILURE); }
    143 09e1306e - else {
    144 5b522953 - imgFileName = afwdata + "/data/medexp.fits";
    145 5b522953 - //imgFileName = afwdata + "/data/medsub.fits";
    146 5b522953 - //imgFileName = afwdata + "/data/871034p_1_MI.fits";
    147 5b522953 - cout << "Using image: " << imgFileName << endl;
    148 09e1306e - }
    } else {
    151 5b522953 - imgFileName = string(argv[1]);
    ? --- ^ ^^
    143 a9aec7fc + inImagePath = string(argv[1]);
    ? ++ + ^ ^^ }
    153 5b522953 - return imgFileName;
    ? --- ^ ^^
    145 a9aec7fc + return inImagePath;
    ? ++ + ^ ^^ } string Sel(bool b, const char* onTrue, const char* onFalse) { return b ? string(onTrue) : string(onFalse); } string DecimalPlaces(int places, double val) { stringstream ss; ss << fixed << showpoint << setprecision(places) << val; return ss.str(); } bool IsErrorAcceptable(double val, double limit) { if (lsst::utils::isnan(val)) return false; if (lsst::utils::isinf(val)) return false; return val < limit; } template typename T::SinglePixel const GetEdgePixel(T& x) { return afwMath::edgePixel< T >( typename afwImage::detail::image_traits< T >::image_category() ); } bool TestWarpGpu( const afwImage::MaskedImage inImgDbl, const afwImage::MaskedImage inImgFlt, afwImage::Wcs::Ptr wcs1, afwImage::Wcs::Ptr wcs2, const afwMath::WarpingControl& wctrCPU, const afwMath::WarpingControl& wctrGPU, string wcsStr, string maskKernelStr ) { const afwImage::MaskedImage inMIDbl = inImgDbl; const afwImage::MaskedImage inMIFlt = inImgFlt; int const sizeX = inMIDbl.getWidth(); int const sizeY = inMIDbl.getHeight(); const afwImage::Image inPIDbl = *inMIDbl.getImage(); const afwImage::Image inPIFlt = *inMIFlt.getImage(); boost::shared_ptr const lanczosKernelPtr = boost::dynamic_pointer_cast(wctrCPU.getWarpingKernel()); cout << "Image size: " << sizeX << " x " << sizeY << " "; cout << "Interpolation length: " << wctrCPU.getInterpLength() << " " << endl; cout << "Main (Lanczos) Kernel order: " << lanczosKernelPtr->getOrder() << " "; cout << "Mask Kernel: " << maskKernelStr << " "; cout << endl; afwImage::MaskedImage resMIDbl(inMIDbl.getDimensions()); afwImage::MaskedImage resMIFlt(inMIDbl.getDimensions()); afwImage::MaskedImage resMIDblGpu(inMIDbl.getDimensions()); afwImage::MaskedImage resMIFltGpu(inMIDbl.getDimensions()); afwImage::Image resPIDbl(inMIDbl.getDimensions()); afwImage::Image resPIFlt(inMIDbl.getDimensions()); afwImage::Image resPIDblGpu(inMIDbl.getDimensions()); afwImage::Image resPIFltGpu(inMIDbl.getDimensions()); for (int i = 0; i < int(wcsStr.size()); i++) cout << " "; cout << " Planes Image Variance Mask Ret" << endl; for (int i = 0; i < 79; i++) cout << "-"; cout << endl; bool isSuccess = true; // warp int retPIDblCpu = afwMath::warpImage(resPIDbl , *wcs1, inPIDbl, *wcs2, wctrCPU); int retPIDblGpu = afwMath::warpImage(resPIDblGpu, *wcs1, inPIDbl, *wcs2, wctrGPU); int retPIFltCpu = afwMath::warpImage(resPIFlt , *wcs1, inPIFlt, *wcs2, wctrCPU); int retPIFltGpu = afwMath::warpImage(resPIFltGpu, *wcs1, inPIFlt, *wcs2, wctrGPU); double const errDbl = 5e-13; double const errFlt = 5e-7; int const maxRetDiff = sqrt(sqrt(sizeX*sizeY))/3; int const maxMskDiff = sqrt(sqrt(sizeX*sizeY))/3; double diffPIDbl = CvRmsd(resPIDbl, resPIDblGpu); double diffPIFlt = CvRmsd(resPIFlt, resPIFltGpu); int dretPIDbl = retPIDblCpu-retPIDblGpu; int dretPIFlt = retPIFltCpu-retPIFltGpu; if ( !IsErrorAcceptable(diffPIDbl, errDbl) ) isSuccess = false; if ( !IsErrorAcceptable(diffPIFlt, errFlt) ) isSuccess = false; if ( abs(dretPIDbl) > maxRetDiff) isSuccess = false; if ( abs(dretPIFlt) > maxRetDiff) isSuccess = false; cout << "P. Image Dbl " << wcsStr << " Dev: " << setw(11) << diffPIDbl << Sel(diffPIDbl > errDbl , "* ", " ") << setw(14+9+6) << dretPIDbl << Sel(abs(dretPIDbl) > maxRetDiff , "*", " ") << endl; cout << "P. Image Flt " << wcsStr << " Dev: " << setw(11) << diffPIFlt << Sel(diffPIFlt > errFlt , "* ", " ") << setw(14+9+6) << dretPIFlt << Sel(abs(dretPIFlt) > maxRetDiff , "*", " ") << endl; int retMIDblCpu = afwMath::warpImage(resMIDbl , *wcs1, inMIDbl, *wcs2, wctrCPU); int retMIDblGpu = afwMath::warpImage(resMIDblGpu, *wcs1, inMIDbl, *wcs2, wctrGPU); int retMIFltCpu = afwMath::warpImage(resMIFlt , *wcs1, inMIFlt, *wcs2, wctrCPU); int retMIFltGpu = afwMath::warpImage(resMIFltGpu, *wcs1, inMIFlt, *wcs2, wctrGPU); double diffMIImgDbl = CvRmsd(*resMIDbl.getImage() , *resMIDblGpu.getImage()); double diffMIVarDbl = CvRmsd(*resMIDbl.getVariance(), *resMIDblGpu.getVariance()); double diffMIMskDbl = DiffCnt(*resMIDbl.getMask() , *resMIDblGpu.getMask()); int dretMIDbl = retMIDblCpu-retMIDblGpu; double diffMIImgFlt = CvRmsd(*resMIFlt.getImage() , *resMIFltGpu.getImage()); double diffMIVarFlt = CvRmsd(*resMIFlt.getVariance(), *resMIFltGpu.getVariance()); double diffMIMskFlt = DiffCnt(*resMIFlt.getMask() , *resMIFltGpu.getMask()); int dretMIFlt = retMIFltCpu-retMIFltGpu; if ( !IsErrorAcceptable(diffMIImgDbl, errDbl) ) isSuccess = false; if ( !IsErrorAcceptable(diffMIVarDbl, errFlt) ) isSuccess = false; if ( diffMIMskDbl > maxMskDiff) isSuccess = false; if ( abs(dretMIDbl) > maxRetDiff) isSuccess = false; if ( !IsErrorAcceptable(diffMIImgFlt, errFlt) ) isSuccess = false; if ( !IsErrorAcceptable(diffMIVarFlt, errFlt) ) isSuccess = false; if ( diffMIMskFlt > maxMskDiff) isSuccess = false; if ( abs(dretMIFlt) > maxRetDiff) isSuccess = false; cout << "M. Image Dbl " << wcsStr << " Dev: " << setw(11) << diffMIImgDbl << Sel(diffMIImgDbl > errDbl , "* ", " ") << setw(11) << diffMIVarDbl << Sel(diffMIVarDbl > errFlt , "* ", " ") << setw( 6) << diffMIMskDbl << Sel(diffMIMskDbl > maxMskDiff , "* ", " ") << setw( 6) << dretMIDbl << Sel(abs(dretMIDbl) > maxRetDiff , "*", " ") << endl; cout << "M. Image Flt " << wcsStr << " Dev: " << setw(11) << diffMIImgFlt << Sel(diffMIImgFlt > errFlt , "* ", " ") << setw(11) << diffMIVarFlt << Sel(diffMIVarFlt > errFlt , "* ", " ") << setw( 6) << diffMIMskFlt << Sel(diffMIMskFlt > maxMskDiff , "* ", " ") << setw( 6) << dretMIFlt << Sel(abs(dretMIFlt) > maxRetDiff , "*", " ") << endl; if (!isSuccess) { cout << "ERROR: Unacceptaby large deviation found!" << endl; cout << "The failed tests are marked with *" << endl; } return isSuccess; } bool TestWarpGpuKernels( const afwImage::MaskedImage inImgDbl, const afwImage::MaskedImage inImgFlt, afwImage::Wcs::Ptr wcs1, afwImage::Wcs::Ptr wcs2, int const kernelOrder, int const interpLen, string wcsStr ) { bool isSuccess = true; afwMath::LanczosWarpingKernel lanKernel(kernelOrder); const lsst::afw::gpu::DevicePreference useGpu = lsst::afw::gpu::USE_GPU; const lsst::afw::gpu::DevicePreference useCpu = lsst::afw::gpu::USE_CPU; { afwMath::WarpingControl wctrCPU(lanKernel,interpLen, useCpu); afwMath::WarpingControl wctrGPU(lanKernel,interpLen, useGpu); isSuccess = TestWarpGpu(inImgDbl,inImgFlt,wcs1,wcs2, wctrCPU, wctrGPU, wcsStr, "not set (same as main)"); } if ( (kernelOrder==4 || kernelOrder==5) && (interpLen==1 || interpLen==7 || interpLen==11)) { bool isSuccess2=true, isSuccess3=true, isSuccess4=true, isSuccess5=true, isSuccess6=true; char lanczosNameBuf[30]; sprintf(lanczosNameBuf, "lanczos%d", kernelOrder); char lanczosNameM1Buf[30]; sprintf(lanczosNameM1Buf, "lanczos%d", kernelOrder-1); { afwMath::WarpingControl wctrCPU(lanczosNameBuf,"",0,interpLen, useCpu); afwMath::WarpingControl wctrGPU(lanczosNameBuf,"",0,interpLen, useGpu); isSuccess2 = TestWarpGpu(inImgDbl,inImgFlt,wcs1,wcs2, wctrCPU, wctrGPU, wcsStr, "empty string (same as main)"); } { afwMath::WarpingControl wctrCPU(lanczosNameBuf,"bilinear",0,interpLen, useCpu); afwMath::WarpingControl wctrGPU(lanczosNameBuf,"bilinear",0,interpLen, useGpu); isSuccess3 = TestWarpGpu(inImgDbl,inImgFlt,wcs1,wcs2, wctrCPU, wctrGPU, wcsStr, "bilinear"); } { afwMath::WarpingControl wctrCPU(lanczosNameBuf,"nearest",0,interpLen, useCpu); afwMath::WarpingControl wctrGPU(lanczosNameBuf,"nearest",0,interpLen, useGpu); isSuccess4 = TestWarpGpu(inImgDbl,inImgFlt,wcs1,wcs2, wctrCPU, wctrGPU, wcsStr, "nearest"); } { afwMath::WarpingControl wctrCPU(lanczosNameBuf,lanczosNameBuf,0,interpLen, useCpu); afwMath::WarpingControl wctrGPU(lanczosNameBuf,lanczosNameBuf,0,interpLen, useGpu); isSuccess5 = TestWarpGpu(inImgDbl,inImgFlt,wcs1,wcs2, wctrCPU, wctrGPU, wcsStr, "identical string (same as main)"); } { afwMath::WarpingControl wctrCPU(lanczosNameBuf,lanczosNameM1Buf,0,interpLen, useCpu); afwMath::WarpingControl wctrGPU(lanczosNameBuf,lanczosNameM1Buf,0,interpLen, useGpu); isSuccess6 = TestWarpGpu(inImgDbl,inImgFlt,wcs1,wcs2, wctrCPU, wctrGPU, wcsStr, "lanczos, one order less than main"); } isSuccess = isSuccess && isSuccess2 && isSuccess3 && isSuccess4 && isSuccess5 && isSuccess6; } return isSuccess; } afwImage::Wcs::Ptr GetLinWcs(double x1, double y1, double x2, double y2, afwGeom::Point2D o1=afwGeom::Point2D(0,0), afwGeom::Point2D o2=afwGeom::Point2D(0,0) ) { Eigen::Matrix2d m1(2,2); m1 << x1 ,y1, x2, y2; return afwImage::Wcs::Ptr(new afwImage::Wcs(o1, o2, m1)); } bool GpuTestAccuracy( const afwImage::MaskedImage& inImgDblFull, const afwImage::MaskedImage& inImgFltFull ) { lsst::pex::logging::Trace::setDestination(std::cout); lsst::pex::logging::Trace::setVerbosity("lsst.afw.kernel", 5); afwGeom::Box2I inputBBox(afwGeom::Point2I(11, 19), afwGeom::Extent2I(40, 61)); const afwImage::MaskedImage inMIDbl(inImgDblFull, inputBBox,afwImage::LOCAL, true); const afwImage::MaskedImage inMIFlt(inImgFltFull, inputBBox,afwImage::LOCAL, true); bool isSuccess = true; for (int order=1; order < 7; order++){ for (int interpLen=1; interpLen < 12; interpLen++){ PrintSeparator(); afwImage::Wcs::Ptr wcs1_1=GetLinWcs(1.3 , -0.2, -0.4, 0.8 ); afwImage::Wcs::Ptr wcs1_2=GetLinWcs(0.88 ,0.2, -0.4, 1.12); const bool isSuccessLin1 = TestWarpGpuKernels(inMIDbl, inMIFlt, wcs1_1, wcs1_2, order, interpLen, "[Linear WCS 1]" ); PrintSeparator(); afwImage::Wcs::Ptr wcs2_1=GetLinWcs(0.1, 1.1, -1.1, 0.3, afwGeom::Point2D(3,5) , afwGeom::Point2D(2,11) ); afwImage::Wcs::Ptr wcs2_2=GetLinWcs(0.88 ,-0.2, 0.4, -1.12, afwGeom::Point2D(2,1), afwGeom::Point2D(-14,9)); const bool isSuccessLin2 = TestWarpGpuKernels(inMIDbl, inMIFlt, wcs2_1, wcs2_2, order, interpLen, "[Linear WCS 2]" ); isSuccess = isSuccess && isSuccessLin1 && isSuccessLin2; } } return isSuccess; } bool GpuTestExceptions(const afwImage::MaskedImage& inImg) { lsst::pex::logging::Trace::setVerbosity("lsst.afw.kernel", 5); afwImage::MaskedImage resImg(inImg.getDimensions()); bool isSuccess = true; PrintSeparator(); lsst::afw::gpu::DevicePreference devPrefUGpu = lsst::afw::gpu::USE_GPU; lsst::afw::gpu::DevicePreference devPrefUCpu = lsst::afw::gpu::USE_CPU; lsst::afw::gpu::DevicePreference devPrefAuto = lsst::afw::gpu::AUTO; lsst::afw::gpu::DevicePreference devPrefSafe = lsst::afw::gpu::AUTO_WITH_CPU_FALLBACK; afwMath::LanczosWarpingKernel lanKernel(2); afwMath::BilinearWarpingKernel bilKernel; afwMath::WarpingControl wctrLanGPU( lanKernel, defaultInterpLen, devPrefUGpu); afwMath::WarpingControl wctrLanCPU( lanKernel, defaultInterpLen, devPrefUCpu); afwMath::WarpingControl wctrLanAUTO(lanKernel, defaultInterpLen, devPrefAuto); afwMath::WarpingControl wctrLanSAFE(lanKernel, defaultInterpLen, devPrefSafe); afwImage::Wcs::Ptr wcs1=GetLinWcs(1 , -1, -0.5, 1 ); afwImage::Wcs::Ptr wcs2=GetLinWcs(2.2, 1.3, 3.4, -1.1); cout << endl; bool isThrown; isThrown = false; try { afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLanAUTO); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with Lanczos kernel with AUTO " << "should have not thrown an exception" << endl; } isThrown = false; try { afwMath::WarpingControl wctrBilGPU( bilKernel, defaultInterpLen, devPrefUGpu); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrBilGPU); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU warping with bilinear kernel with USE_GPU" << "should have thrown an exception because acceleration of bilinear kernel is not supported" << endl; } isThrown = false; try { afwMath::WarpingControl wctrBilSAFE(bilKernel, defaultInterpLen, devPrefSafe); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrBilSAFE); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with bilinear function kernel with AUTO_WITH_CPU_FALLBACK" << "should not have thrown an exception because it should have fell back to CPU code path" << endl; } isThrown = false; try { afwMath::WarpingControl wctrLan0AUTO(lanKernel, 0, devPrefAuto); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLan0AUTO); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with no interpolation with AUTO" << "should not have thrown an exception because it should have used CPU code path" << endl; } isThrown = false; try { afwMath::WarpingControl wctrLan0CPU(lanKernel, 0, devPrefUCpu); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLan0CPU); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with no interpolation kernel with USE_CPU" << "should not have thrown an exception because it should have used CPU code path" << endl; } isThrown = false; try { afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLanGPU); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with Lanczos kernel with USE_GPU " << "should not have thrown an exception" << endl; } isThrown = false; try { afwMath::WarpingControl wctrLan0GPU( lanKernel, 0, devPrefUGpu); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLan0GPU); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU warping with no interpolation " << "with Lanczos kernel with USE_GPU " << "should have thrown an exception because interpolation is obligatory for GPU acceleration" << endl; } isThrown = false; try { afwMath::WarpingControl wctrBilAUTO(bilKernel, defaultInterpLen, devPrefSafe); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrBilAUTO); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with bilinear kernel with AUTO " << "should not have thrown an exception because it should have used CPU code path" << endl; } if (isSuccess) { cout << "All GPU exception tests passed." << endl; } cout << endl; return isSuccess; } bool CpuTestExceptions(const afwImage::MaskedImage& inImg) { lsst::pex::logging::Trace::setVerbosity("lsst.afw.kernel", 5); afwImage::MaskedImage resImg(inImg.getDimensions()); bool isSuccess = true; PrintSeparator(); lsst::afw::gpu::DevicePreference devPrefUGpu = lsst::afw::gpu::USE_GPU; lsst::afw::gpu::DevicePreference devPrefUCpu = lsst::afw::gpu::USE_CPU; lsst::afw::gpu::DevicePreference devPrefAuto = lsst::afw::gpu::AUTO; lsst::afw::gpu::DevicePreference devPrefSafe = lsst::afw::gpu::AUTO_WITH_CPU_FALLBACK; afwMath::LanczosWarpingKernel lanKernel(2); afwMath::BilinearWarpingKernel bilKernel; afwImage::Wcs::Ptr wcs1=GetLinWcs(1 , -1, -0.5, 1 ); afwImage::Wcs::Ptr wcs2=GetLinWcs(2.2, 1.3, 3.4, -1.1); cout << endl; bool isThrown; isThrown = false; try { afwMath::WarpingControl wctrLanAUTO( lanKernel, defaultInterpLen, devPrefAuto); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLanAUTO); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with Lanczos kernel with AUTO " << "should have not thrown an exception" << endl; } isThrown = false; try { afwMath::WarpingControl wctrLanGPU( lanKernel, defaultInterpLen, devPrefUGpu); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLanGPU); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU warping with Lanczos kernel with USE_GPU" << "should have thrown an exception because AFW was not compiled with GPU support" << endl; } isThrown = false; try { afwMath::WarpingControl wctrLan0SAFE( lanKernel, 0, devPrefSafe); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLan0SAFE); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with Lanczos kernel with AUTO_WITH_CPU_FALLBACK" << "should not have thrown an exception because it should have used CPU code path" << endl; } isThrown = false; try { afwMath::WarpingControl wctrLan0AUTO( lanKernel, 0, devPrefAuto); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLan0AUTO); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with Lanczos kernel with AUTO" << "should not have thrown an exception because it should have used CPU code path" << endl; } isThrown = false; try { afwMath::WarpingControl wctrLan0CPU( lanKernel, 0, devPrefUCpu); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLan0CPU); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with Lanczos kernel with USE_CPU" << "should not have thrown an exception because it should have used CPU code path" << endl; } isThrown = false; try { afwMath::WarpingControl wctrLan0GPU( lanKernel, 0, devPrefUGpu); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrLan0GPU); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU warping with Lanczos kernel with USE_GPU " << "should have thrown an exception because AFW was not compiled with GPU support" << endl; } isThrown = false; try { afwMath::WarpingControl wctrBil2GPU( bilKernel, 2, devPrefUGpu); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrBil2GPU); } catch(pexEx::Exception) { isThrown = true; } if (lsst::afw::gpu::isGpuEnabled() && !isThrown) { isSuccess = false; cout << "ERROR: GPU warping with bilinear kernel with USE_GPU " << "should have thrown an exception because AFW was not compiled with GPU support" << endl; } isThrown = false; try { afwMath::WarpingControl wctrBil2AUTO( bilKernel, 2, devPrefAuto); afwMath::warpImage(resImg, *wcs1, inImg, *wcs2, wctrBil2AUTO); } catch(pexEx::Exception) { isThrown = true; } if (isThrown) { isSuccess = false; cout << "ERROR: GPU warping with bilinear kernel with AUTO " << "should not have thrown an exception because it should have used CPU code path" << endl; } if (isSuccess) { cout << "All GPU exception tests passed (but AFW was not compiled with GPU support!!)." << endl; cout << "Additional tests will be performed when GPU acceleration is available." << endl; } cout << endl; return isSuccess; } TestResult TestGpu(int argc, char**argv) { lsst::afw::gpu::detail::PrintCudaDeviceInfo();
    706 09e1306e - string baseFileName = GetInputFileName(argc, argv);
    698 a9aec7fc + string inImagePath = GetInputImagePath(argc, argv);
    708 09e1306e - const afwImage::MaskedImage inImgFlt(baseFileName);
    ? ^ ^ ^^^^^ ^^
    700 a9aec7fc + const afwImage::MaskedImage inImgFlt(inImagePath);
    ? ^^^^ ^ ^ ^^
    709 09e1306e - const afwImage::MaskedImage inImgDbl(baseFileName);
    ? ^ ^ ^^^^^ ^^
    701 a9aec7fc + const afwImage::MaskedImage inImgDbl(inImagePath);
    ? ^^^^ ^ ^ ^^ const bool isSuccess1 = GpuTestAccuracy(inImgDbl, inImgFlt); const bool isSuccess2 = GpuTestExceptions(inImgDbl); const bool isSuccess = isSuccess1 && isSuccess2; return isSuccess ? EXIT_SUCCESS : EXIT_FAILURE; } TestResult TestCpu(int argc, char**argv) {
    720 09e1306e - string baseFileName = GetInputFileName(argc, argv);
    712 a9aec7fc + string inImagePath = GetInputImagePath(argc, argv);
    721 09e1306e - const afwImage::MaskedImage inImgDbl(baseFileName);
    ? ^ ^ ^^^^^ ^^
    713 a9aec7fc + const afwImage::MaskedImage inImgDbl(inImagePath);
    ? ^^^^ ^ ^ ^^ const bool isSuccess = CpuTestExceptions(inImgDbl); return isSuccess ? EXIT_SUCCESS : EXIT_FAILURE; } int main(int argc, char **argv) { int status = EXIT_SUCCESS; PrintSeparator(); cout << endl; cout << "Note: Dev = coefficient of variation of RMSD" << endl; cout << "Note: Interpolation length set to " << defaultInterpLen << endl; cout << endl;
    730 09e1306e +
    731 a9aec7fc + GetInputImagePath(argc, argv); // if afwdata not setup then exit
    try { if (lsst::afw::gpu::isGpuBuild()) { status = TestGpu(argc, argv); } else { status = TestCpu(argc, argv); } } catch (pexEx::Exception &e) { clog << e.what() << endl; status = EXIT_FAILURE; } PrintSeparator(); cout << endl; if (status == EXIT_FAILURE) { cout << "Some tests have failed." << endl; } else { cout << "All tests passed OK." << endl; } cout << endl; // Check for memory leaks if (lsst::daf::base::Citizen::census(0) == 0) { cerr << "No leaks detected" << endl; } else { cerr << "Leaked memory blocks:" << endl; lsst::daf::base::Citizen::census(cerr); status = EXIT_FAILURE; } return status; }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    09e1306e

    commit 09e1306ec775c2dc0e80262686dcb1c1cf1ba72a
    Author: Kresimir Cosic 
    Date:   Fri Mar 2 08:21:30 2012 +0100
    
        Added a test and some interface changes
    

    5b522953

    commit 5b522953c3a80b54c7832793f353c7e00d3b5ea7
    Author: Jim Bosch 
    Date:   Tue Nov 20 14:53:52 2012 -0500
    
        Convert tests to use MEFs (requires afwdata update), remove a worthless one.
    

    Commits in /Users/nate/repos_lsst/afw/

    09e1306e

    commit 09e1306ec775c2dc0e80262686dcb1c1cf1ba72a
    Author: Kresimir Cosic 
    Date:   Fri Mar 2 08:21:30 2012 +0100
    
        Added a test and some interface changes
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    examples/timeConvolve.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    #include 
                    
    
    27 a9aec7fc + #include "lsst/utils/Utils.h"
    28 a9aec7fc + #include "lsst/pex/exceptions.h"
    #include "lsst/afw/math/FunctionLibrary.h" #include "lsst/afw/image/Image.h" #include "lsst/afw/image/MaskedImage.h" #include "lsst/afw/math/Kernel.h" #include "lsst/afw/math/KernelFunctions.h" namespace afwImage = lsst::afw::image; namespace afwMath = lsst::afw::math; typedef float ImageType; typedef double KernelType; const double Sigma = 3; const unsigned DefNIter = 10; const unsigned MinKernelSize = 5; const unsigned MaxKernelSize = 15; const unsigned DeltaKernelSize = 5; template void timeConvolution(ImageClass &image, unsigned int nIter) { typedef double KernelType; unsigned imWidth = image.getWidth(); unsigned imHeight = image.getHeight(); ImageClass resImage(image.getDimensions()); std::cout << std::endl << "Analytic Kernel" << std::endl; std::cout << "ImWid\tImHt\tKerWid\tKerHt\tMOps\tCnvSec\tMOpsPerSec" << std::endl; for (unsigned kSize = MinKernelSize; kSize <= MaxKernelSize; kSize += DeltaKernelSize) { // construct kernel afwMath::GaussianFunction2 gaussFunc(Sigma, Sigma, 0); afwMath::AnalyticKernel analyticKernel(kSize, kSize, gaussFunc); clock_t startTime = clock(); for (unsigned int iter = 0; iter < nIter; ++iter) { // convolve afwMath::convolve(resImage, image, analyticKernel, true); } double secPerIter = (clock() - startTime) / static_cast (nIter * CLOCKS_PER_SEC); double mOps = static_cast( (imHeight + 1 - kSize) * (imWidth + 1 - kSize) * kSize * kSize) / 1.0e6; double mOpsPerSec = mOps / secPerIter; std::cout << imWidth << "\t" << imHeight << "\t" << kSize << "\t" << kSize << "\t" << mOps << "\t" << secPerIter << "\t" << mOpsPerSec << std::endl; } std::cout << std::endl << "Separable Kernel" << std::endl; std::cout << "ImWid\tImHt\tKerWid\tKerHt\tMOps\tCnvSec\tMOpsPerSec" << std::endl; for (unsigned kSize = MinKernelSize; kSize <= MaxKernelSize; kSize += DeltaKernelSize) { // construct kernel afwMath::GaussianFunction1 gaussFunc(Sigma); afwMath::SeparableKernel separableKernel(kSize, kSize, gaussFunc, gaussFunc); clock_t startTime = clock(); for (unsigned int iter = 0; iter < nIter; ++iter) { // convolve afwMath::convolve(resImage, image, separableKernel, true); } double secPerIter = (clock() - startTime) / static_cast (nIter * CLOCKS_PER_SEC); double mOps = static_cast(( imHeight + 1 - kSize) * (imWidth + 1 - kSize) * kSize * kSize) / 1.0e6; double mOpsPerSec = mOps / secPerIter; std::cout << imWidth << "\t" << imHeight << "\t" << kSize << "\t" << kSize << "\t" << mOps << "\t" << secPerIter << "\t" << mOpsPerSec << std::endl; } } int main(int argc, char **argv) {
    100 33d30816 -
    101 8c6c0d93 -
    102 8c6c0d93 - std::string mimg;
    ? ^^
    102 a9aec7fc + std::string inImagePath;
    ? +++ ^ +++++ if (argc < 2) {
    104 8c6c0d93 - std::string afwdata = getenv("AFWDATA_DIR");
    105 8c6c0d93 - if (afwdata.empty()) {
    106 8c6c0d93 - std::cout << "Time convolution with a spatially invariant kernel" << std::endl << std::endl;
    104 a9aec7fc + try {
    105 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
    106 a9aec7fc + inImagePath = dataDir + "/data/small.fits";
    107 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    107 8c6c0d93 - std::cout << "Usage: timeConvolve fitsFile [nIter]" << std::endl;
    ? ^^^
    108 a9aec7fc + std::cerr << "Usage: timeConvolve [fitsFile [nIter]]" << std::endl;
    ? ^^^ + +
    108 8c6c0d93 - std::cout << "fitsFile excludes the \"_img.fits\" suffix" << std::endl;
    109 a9aec7fc + std::cerr << "fitsFile is the path to a masked image" << std::endl;
    109 8c6c0d93 - std::cout << "nIter (default " << DefNIter
    ? ^^^
    110 a9aec7fc + std::cerr << "nIter (default " << DefNIter
    ? ^^^ << ") is the number of iterations per kernel size" << std::endl;
    111 8c6c0d93 - std::cout << "Kernel size ranges from " << MinKernelSize << " to " << MaxKernelSize
    112 8c6c0d93 - << " in steps of " << DeltaKernelSize << " pixels on a side" << std::endl;
    113 8c6c0d93 - std::cerr << "I can take a default file from AFWDATA_DIR, but it's not defined." << std::endl;
    114 8c6c0d93 - std::cerr << "Is afwdata set up?\n" << std::endl;
    ? ^ ^^^^
    112 a9aec7fc + std::cerr << "\nError: setup afwdata or specify fitsFile.\n" << std::endl;
    ? ^^^^^^^^^ ++++ +++ + +++++++ ^^^^^^ exit(EXIT_FAILURE);
    116 8c6c0d93 - } else {
    117 8c6c0d93 - mimg = afwdata + "/small_MI";
    118 8c6c0d93 - std::cerr << "Using " << mimg << std::endl;
    } } else {
    121 8c6c0d93 - mimg = std::string(argv[1]);
    ? ^^
    116 a9aec7fc + inImagePath = std::string(argv[1]);
    ? +++ ^ +++++ } unsigned int nIter = DefNIter; if (argc > 2) { std::istringstream(argv[2]) >> nIter; } std::cout << "Timing convolution with a spatially invariant kernel" << std::endl; std::cout << "Columns:" << std::endl; std::cout << "* MOps: the number of operations of a kernel pixel on a masked pixel / 10e6." << std::endl; std::cout << " One operation includes the all of the following:" << std::endl; std::cout << " * two multiplies and two additions (one image, one for variance)," << std::endl; std::cout << " * one OR (for the mask)" << std::endl; std::cout << " * four pixel pointer increments (for image, variance, mask and kernel)" << std::endl; std::cout << "* CnvSec: time to perform one convolution (sec)" << std::endl;
    138 8c6c0d93 - std::string maskedImagePath(mimg);
    139 33d30816 - std::string imagePath = maskedImagePath + "_img.fits";
    140 33d30816 -
    141 33d30816 - std::cout << std::endl << "Image " << imagePath << std::endl;
    133 a9aec7fc + std::cout << std::endl << "Image " << inImagePath << std::endl;
    ? ++
    142 33d30816 - afwImage::Image image(imagePath);
    134 a9aec7fc + afwImage::Image image(inImagePath);
    ? ++ timeConvolution(image, nIter);
    145 33d30816 - std::cout << std::endl << "MaskedImage " << maskedImagePath << std::endl;
    ? ^^^^^^
    137 a9aec7fc + std::cout << std::endl << "MaskedImage " << inImagePath << std::endl;
    ? ^^
    146 8c6c0d93 - afwImage::MaskedImage mImage(mimg);
    ? ^^
    138 a9aec7fc + afwImage::MaskedImage mImage(inImagePath);
    ? +++ ^ +++++ timeConvolution(mImage, nIter); }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    33d30816

    commit 33d30816eeb07d526d83213bfa03f270061a85e1
    Author: rowen 
    Date:   Tue Dec 9 00:04:26 2008 +0000
    
        Updated timeConvolve to test image and masked image
    

    8c6c0d93

    commit 8c6c0d93eaf03478cc6379a16055c3ae6119aa35
    Author: bick 
    Date:   Fri Jan 8 21:49:43 2010 +0000
    
        #1113 Changed examples to default to afwdata fits files with no arguments.
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    tests/footprint2.py

    Diff:

    1 e6fac15b - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Footprints, and FootprintSets Run with: footprint2.py or python >>> import footprint2; footprint2.run() """
    35 e6fac15b - import sys
    import unittest
    37 61b6195c - import numpy as np
    import lsst.utils.tests as tests import lsst.pex.logging as logging import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom
    42 20c2c467 - import lsst.afw.math as afwMath
    import lsst.afw.detection as afwDetect
    44 e6fac15b - import lsst.afw.detection.utils as afwDetectUtils
    import lsst.afw.display.ds9 as ds9
    46 61b6195c - import lsst.afw.display.utils as dispUtils
    try: type(verbose) except NameError: verbose = 0 logging.Debug("afwDetect.Footprint", verbose) try: type(display) except NameError: display = False def toString(*args): """toString written in python""" if len(args) == 1: args = args[0] y, x0, x1 = args return "%d: %d..%d" % (y, x0, x1) def cmpPeaks(im, a, b): """Comparison function to sort by (decreasing) peak height""" ai = im.get(a[0], a[1])[0] bi = im.get(b[0], b[1])[0] val = cmp(bi, ai) if val: return val return cmp(a, b) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class Object(object): def __init__(self, val, spans): self.val = val self.spans = spans def insert(self, im): """Insert self into an image""" for sp in self.spans: y, x0, x1 = sp for x in range(x0, x1+1): im.set(x, y, self.val) def __eq__(self, other): for osp, sp in zip(other.getSpans(), self.spans): if osp.toString() != toString(sp): return False return True #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class FootprintSetTestCase(unittest.TestCase): """A test case for FootprintSet""" def setUp(self): self.im = afwImage.ImageU(afwGeom.Extent2I(12, 8)) # # Objects that we should detect # self.objects = [] self.objects += [Object(10, [(1, 4, 4), (2, 3, 5), (3, 4, 4)])] self.objects += [Object(20, [(5, 7, 8), (5, 10, 10), (6, 8, 9)])] self.objects += [Object(20, [(6, 3, 3)])] self.im.set(0) # clear image for obj in self.objects: obj.insert(self.im) if False and display: ds9.mtv(self.im, frame=0) def tearDown(self): del self.im def testGC(self): """Check that FootprintSets are automatically garbage collected (when MemoryTestCase runs)""" ds = afwDetect.FootprintSet(afwImage.ImageU(afwGeom.Extent2I(10, 20)), afwDetect.Threshold(10)) def testFootprints(self): """Check that we found the correct number of objects and that they are correct""" ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i]) def testFootprints2(self): """Check that we found the correct number of objects using FootprintSet""" ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i]) def testFootprintsImageId(self): """Check that we can insert footprints into an Image""" ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() idImage = afwImage.ImageU(self.im.getDimensions()) idImage.set(0) for foot in objects: foot.insertIntoImage(idImage, foot.getId()) if False: ds9.mtv(idImage, frame=2) for i in range(len(objects)): for sp in objects[i].getSpans(): for x in range(sp.getX0(), sp.getX1() + 1): self.assertEqual(idImage.get(x, sp.getY()), objects[i].getId()) def testFootprintSetImageId(self): """Check that we can insert a FootprintSet into an Image, setting relative IDs""" ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() idImage = ds.insertIntoImage(True) if display: ds9.mtv(idImage, frame=2) for i in range(len(objects)): for sp in objects[i].getSpans(): for x in range(sp.getX0(), sp.getX1() + 1): self.assertEqual(idImage.get(x, sp.getY()), i + 1) def testFootprintsImage(self): """Check that we can search Images as well as MaskedImages""" ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10)) objects = ds.getFootprints() self.assertEqual(len(objects), len(self.objects)) for i in range(len(objects)): self.assertEqual(objects[i], self.objects[i]) def testGrow2(self): """Grow some more interesting shaped Footprints. Informative with display, but no numerical tests""" #Can't set mask plane as the image is not a masked image. ds = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10)) idImage = afwImage.ImageU(self.im.getDimensions()) idImage.set(0) i = 1 for foot in ds.getFootprints()[0:1]: gfoot = afwDetect.growFootprint(foot, 3, False) gfoot.insertIntoImage(idImage, i) i += 1 if display: ds9.mtv(self.im, frame=0) ds9.mtv(idImage, frame=1) def testGrow(self): """Grow footprints using the FootprintSet constructor""" fs = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10)) self.assertEqual(len(fs.getFootprints()), len(self.objects)) for isotropic in (True, False, afwDetect.FootprintControl(True),): grown = afwDetect.FootprintSet(fs, 1, isotropic) self.assertEqual(len(fs.getFootprints()), len(self.objects)) self.assertGreater(len(grown.getFootprints()), 0) self.assertLessEqual(len(grown.getFootprints()), len(fs.getFootprints()))
    222 b513fa75 -
    223 61b6195c - def testGrow0(self):
    224 61b6195c - """Test that we can grow a Footprint by 0 pixels"""
    225 61b6195c - # N.b. we make use of this in testNonContiguous()
    226 61b6195c -
    227 61b6195c - fs = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10))
    228 61b6195c - foot = fs.getFootprints()[0]
    229 61b6195c - gfoot = afwDetect.growFootprint(foot, 0)
    230 61b6195c -
    231 61b6195c - self.assertNotEqual(foot.getId(), gfoot.getId()) # i.e. grow(foot, 0) doesn't return foot
    232 61b6195c - for s, gs in zip(foot.getSpans(), gfoot.getSpans()):
    233 61b6195c - self.assertEqual(gs, s)
    def testFootprintControl(self): """Test the FootprintControl constructor""" fctrl = afwDetect.FootprintControl() self.assertFalse(fctrl.isCircular()[0]) # not set self.assertFalse(fctrl.isIsotropic()[0]) # not set fctrl.growIsotropic(False) self.assertTrue(fctrl.isCircular()[0]) self.assertTrue(fctrl.isIsotropic()[0]) self.assertTrue(fctrl.isCircular()[1]) self.assertFalse(fctrl.isIsotropic()[1]) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- fctrl = afwDetect.FootprintControl() fctrl.growLeft(False) self.assertTrue(fctrl.isLeft()[0]) # it's now set self.assertFalse(fctrl.isLeft()[1]) # ... but False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- fctrl = afwDetect.FootprintControl(True, False, False, False) self.assertTrue(fctrl.isLeft()[0]) self.assertTrue(fctrl.isRight()[0]) self.assertTrue(fctrl.isUp()[0]) self.assertTrue(fctrl.isDown()[0]) self.assertTrue(fctrl.isLeft()[1]) self.assertFalse(fctrl.isRight()[1]) def testGrowCircular(self): """Grow footprints in all 4 directions using the FootprintSet/FootprintControl constructor """ im = afwImage.MaskedImageF(11, 11) im.set(5, 5, (10,)) fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10)) self.assertEqual(len(fs.getFootprints()), 1) radius = 3 # How much to grow by for fctrl in (afwDetect.FootprintControl(), afwDetect.FootprintControl(True), afwDetect.FootprintControl(True, True), ): grown = afwDetect.FootprintSet(fs, radius, fctrl) afwDetect.setMaskFromFootprintList(im.getMask(), grown.getFootprints(), 0x10) if display: ds9.mtv(im) foot = grown.getFootprints()[0] if not fctrl.isCircular()[0]: self.assertEqual(foot.getNpix(), 1) elif fctrl.isCircular()[0]: assert radius == 3 if fctrl.isIsotropic()[1]: self.assertEqual(foot.getNpix(), 29) else: self.assertEqual(foot.getNpix(), 25) def testGrowLRUD(self): """Grow footprints in various directions using the FootprintSet/FootprintControl constructor """ im = afwImage.MaskedImageF(11, 11) x0, y0, ny = 5, 5, 3 for y in range(y0 - ny//2, y0 + ny//2 + 1): im.set(x0, y, (10,)) fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10)) self.assertEqual(len(fs.getFootprints()), 1) ngrow = 2 # How much to grow by # # Test growing to the left and/or right # for fctrl in ( afwDetect.FootprintControl(False, True, False, False), afwDetect.FootprintControl(True, False, False, False), afwDetect.FootprintControl(True, True, False, False), ): grown = afwDetect.FootprintSet(fs, ngrow, fctrl) im.getMask().set(0) afwDetect.setMaskFromFootprintList(im.getMask(), grown.getFootprints(), 0x10) if display: ds9.mtv(im) foot = grown.getFootprints()[0] nextra = 0 if fctrl.isLeft()[1]: nextra += ngrow for y in range(y0 - ny//2, y0 + ny//2 + 1): self.assertNotEqual(im.getMask().get(x0 - 1, y), 0) if fctrl.isRight()[1]: nextra += ngrow for y in range(y0 - ny//2, y0 + ny//2 + 1): self.assertNotEqual(im.getMask().get(x0 + 1, y), 0) self.assertEqual(foot.getNpix(), (1 + nextra)*ny) # # Test growing to up and/or down # for fctrl in ( afwDetect.FootprintControl(False, False, True, False), afwDetect.FootprintControl(False, False, False, True), afwDetect.FootprintControl(False, False, True, True), ): grown = afwDetect.FootprintSet(fs, ngrow, fctrl) im.getMask().set(0) afwDetect.setMaskFromFootprintList(im.getMask(), grown.getFootprints(), 0x10) if display: ds9.mtv(im) foot = grown.getFootprints()[0] nextra = 0 if fctrl.isUp()[1]: nextra += ngrow for y in range(y0 + ny//2 + 1, y0 + ny//2 + ngrow + 1): self.assertNotEqual(im.getMask().get(x0, y), 0) if fctrl.isDown()[1]: nextra += ngrow for y in range(y0 - ny//2 - 1, y0 - ny//2 - ngrow - 1): self.assertNotEqual(im.getMask().get(x0, y), 0) self.assertEqual(foot.getNpix(), ny + nextra) def testGrowLRUD2(self): """Grow footprints in various directions using the FootprintSet/FootprintControl constructor Check that overlapping grown Footprints give the expected answers """ ngrow = 3 # How much to grow by for fctrl, xy in [ (afwDetect.FootprintControl(True, True, False, False), [(4, 5), (5, 6), (6, 5)]), (afwDetect.FootprintControl(False, False, True, True), [(5, 4), (6, 5), (5, 6)]), ]: im = afwImage.MaskedImageF(11, 11) for x, y in xy: im.set(x, y, (10,)) fs = afwDetect.FootprintSet(im, afwDetect.Threshold(10)) self.assertEqual(len(fs.getFootprints()), 1) grown = afwDetect.FootprintSet(fs, ngrow, fctrl) im.getMask().set(0) afwDetect.setMaskFromFootprintList(im.getMask(), grown.getFootprints(), 0x10) if display: ds9.mtv(im) self.assertEqual(len(grown.getFootprints()), 1) foot = grown.getFootprints()[0] npix = 1 + 2*ngrow npix += 3 + 2*ngrow # 3: distance between pair of set pixels 000X0X000 self.assertEqual(foot.getNpix(), npix) def testInf(self): """Test detection for images with Infs""" im = afwImage.MaskedImageF(afwGeom.Extent2I(10, 20)) im.set(0) import numpy for x in range(im.getWidth()): im.set(x, im.getHeight() - 1, (numpy.Inf, 0x0, 0)) ds = afwDetect.FootprintSet(im, afwDetect.createThreshold(100)) objects = ds.getFootprints() afwDetect.setMaskFromFootprintList(im.getMask(), objects, 0x10) if display: ds9.mtv(im) self.assertEqual(len(objects), 1)
    408 61b6195c -
    409 61b6195c - def testNonContiguous(self):
    410 61b6195c - """Test non-contiguous Footprints"""
    411 61b6195c -
    412 61b6195c - for isotropic in (False, True):
    413 61b6195c - foot = afwDetect.Footprint(afwGeom.BoxI(), self.im.getBBox())
    414 61b6195c - for y, x0, x1 in [(3, 2, 3), (3, 7, 8),
    415 61b6195c - (4, 2, 3), (4, 7, 9),
    416 61b6195c - ]:
    417 61b6195c - foot.addSpan(afwGeom.Span(y, x0, x1))
    418 61b6195c -
    419 61b6195c - foot.addPeak(2.5, 3.5, 100)
    420 61b6195c - foot.addPeak(8.0, 4.0, 200)
    421 61b6195c -
    422 61b6195c - foot.normalize()
    423 61b6195c -
    424 61b6195c - gfoot = afwDetect.growFootprint(foot, 0, isotropic)
    425 61b6195c -
    426 61b6195c - im = self.im.clone(); im[:] = 0
    427 61b6195c - foot.insertIntoImage(im, 10)
    428 61b6195c - gim = self.im.clone(); gim[:] = 0
    429 61b6195c - gfoot.insertIntoImage(gim, 10)
    430 61b6195c -
    431 61b6195c - if display:
    432 61b6195c - dim = gim.clone() # image is only for display
    433 61b6195c - foot.insertIntoImage(dim, 20)
    434 61b6195c - ds9.mtv(dim, title="Grown footprint")
    435 61b6195c - del dim
    436 61b6195c -
    437 61b6195c - self.assertTrue(np.all(im.getArray() == gim.getArray()),
    438 61b6195c - "Footprint grown %sby 0 == original" % ("isotropically " if isotropic else ""))
    439 61b6195c - if False:
    440 61b6195c - print "\n", isotropic, "foot ", [p for p in foot.getPeaks()]
    441 61b6195c - print isotropic, "gfoot", [p for p in gfoot.getPeaks()]
    442 61b6195c -
    443 61b6195c - for op, gp in zip(foot.getPeaks(), gfoot.getPeaks()):
    444 61b6195c - self.assertEqual(op.getId(), gp.getId())
    445 61b6195c - self.assertEqual((op.getFx(), op.getFy()), (gp.getFx(), gp.getFy()))
    446 61b6195c - self.assertEqual((op.getIx(), op.getIy()), (gp.getIx(), gp.getIy()))
    447 61b6195c - #
    ? -
    392 e6fac15b +
    448 61b6195c - # Now try a non-trivial grow
    449 61b6195c - #
    450 61b6195c - gfoot = afwDetect.growFootprint(foot, 1, isotropic)
    451 61b6195c -
    452 61b6195c - gim = self.im.clone(); gim[:] = 0
    453 61b6195c - gfoot.insertIntoImage(gim, 20)
    454 61b6195c -
    455 61b6195c - if display:
    456 61b6195c - dim = gim.clone() # image is only for display
    457 61b6195c - foot.insertIntoImage(dim, 10)
    458 61b6195c - ds9.mtv(dim, title="Grown footprint")
    459 61b6195c - dispUtils.drawFootprint(gfoot, peaks=True)
    460 61b6195c -
    461 61b6195c - del dim
    462 61b6195c - #
    463 61b6195c - # Check that we recovered both parts of original Footprint
    464 61b6195c - #
    465 61b6195c - fs = afwDetect.FootprintSet(gim, afwDetect.Threshold(1))
    466 61b6195c - self.assertEqual(len(fs.getFootprints()), 2,
    467 61b6195c - "Found both parts of the %sgrown Footprint" %
    468 61b6195c - ("isotropically " if isotropic else ""))
    469 61b6195c -
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class PeaksInFootprintsTestCase(unittest.TestCase): """A test case for detecting Peaks within Footprints""" def doSetUp(self, dwidth=0, dheight=0, x0=0, y0=0): width, height = 14 + x0 + dwidth, 10 + y0 + dheight self.im = afwImage.MaskedImageF(afwGeom.Extent2I(width, height)) # # Objects that we should detect # self.objects, self.peaks = [], [] self.objects.append([[4, 1, 10], [3, 2, 10], [4, 2, 20], [5, 2, 10], [4, 3, 10],]) self.peaks.append([[4, 2]]) self.objects.append([[9, 7, 30], [10, 7, 29], [12, 7, 25], [10, 8, 27], [11, 8, 26],]) self.peaks.append([[9, 7]]) self.objects.append([[3, 8, 10], [4, 8, 10],]) self.peaks.append([[3, 8], [4, 8],]) for pp in self.peaks: # allow for x0, y0 for p in pp: p[0] += x0 p[1] += y0 for oo in self.objects: for o in oo: o[0] += x0 o[1] += y0 self.im.set((0, 0x0, 0)) # clear image for obj in self.objects: for x, y, I in obj: self.im.getImage().set(x, y, I) if False and display: ds9.mtv(self.im, frame=0) def setUp(self): self.im, self.fs = None, None def tearDown(self): del self.im del self.fs def doTestPeaks(self, dwidth=0, dheight=0, x0=0, y0=0, threshold=10, callback=None, polarity=True, grow=0): """Worker routine for tests polarity: True if should search for +ve pixels""" self.doSetUp(dwidth, dheight, x0, y0) if not polarity: self.im *= -1 if callback: callback() # # Sort self.peaks in decreasing peak height to match Footprint.getPeaks() # for i, peaks in enumerate(self.peaks): self.peaks[i] = sorted([(x, y, self.im.getImage().get(x, y)) for x, y in peaks], lambda x, y: cmpPeaks(self.im, x, y)) threshold = afwDetect.Threshold(threshold, afwDetect.Threshold.VALUE, polarity) fs = afwDetect.FootprintSet(self.im, threshold, "BINNED1") if grow: fs = afwDetect.FootprintSet(fs, grow, True) msk = self.im.getMask() afwDetect.setMaskFromFootprintList(msk, fs.getFootprints(), msk.getPlaneBitMask("DETECTED")) del msk self.fs = fs self.checkPeaks(dwidth, dheight, frame=3) def checkPeaks(self, dwidth=0, dheight=0, frame=3): """Check that we got the peaks right""" feet = self.fs.getFootprints() # # Check that we found all the peaks # self.assertEqual(sum([len(f.getPeaks()) for f in feet]), sum([len(f.getPeaks()) for f in feet])) if display: ds9.mtv(self.im, frame=frame) with ds9.Buffering(): for i, foot in enumerate(feet): for p in foot.getPeaks(): ds9.dot("+", p.getIx(), p.getIy(), size=0.4, frame=frame) if i < len(self.peaks): for trueX, trueY, peakVal in self.peaks[i]: ds9.dot("x", trueX, trueY, size=0.4, ctype=ds9.RED, frame=frame) for i, foot in enumerate(feet): npeak = None # # Peaks that touch the edge are handled differently, as only the single highest/lowest pixel # is treated as a Peak # if (dwidth != 0 or dheight != 0): if (foot.getBBox().getMinX() == 0 or foot.getBBox().getMaxX() == self.im.getWidth() - 1 or foot.getBBox().getMinY() == 0 or foot.getBBox().getMaxY() == self.im.getHeight() - 1): npeak = 1 if npeak is None: npeak = len(self.peaks[i]) if npeak != len(foot.getPeaks()): print "RHL", foot.repr() #print "RHL", [(p.repr().split(":")[0], p.getIx(), p.getIy()) for p in foot.getPeaks()] print "RHL", [(p.getId(), p.getIx(), p.getIy()) for p in foot.getPeaks()] print "RHL", [p[0:2] for p in self.peaks[i]] self.assertEqual(len(foot.getPeaks()), npeak) for j, p in enumerate(foot.getPeaks()): trueX, trueY, peakVal = self.peaks[i][j] if (p.getIx(), p.getIy()) != (trueX, trueY): print "RHL", [(pp.getId(), pp.getIx(), pp.getIy()) for pp in foot.getPeaks()] print "RHL", [pp[0:2] for pp in self.peaks[i]] self.assertEqual((p.getIx(), p.getIy()), (trueX, trueY)) def testSinglePeak(self): """Test that we can find single Peaks in Footprints""" self.doTestPeaks() def testSingleNegativePeak(self): """Test that we can find single Peaks in Footprints when looking for -ve detections""" self.doTestPeaks(polarity=False) def testSinglePeakAtEdge(self): """Test that we handle Peaks correctly at the edge""" self.doTestPeaks(dheight=-1) def testSingleNegativePeakAtEdge(self): """Test that we handle -ve Peaks correctly at the edge""" self.doTestPeaks(dheight=-1, polarity=False) def testMultiPeak(self): """Test that multiple peaks are handled correctly""" def callback(): x, y = 12, 7 self.im.getImage().set(x, y, 100) self.peaks[1].append((x, y)) self.doTestPeaks(callback=callback) def testMultiNegativePeak(self): """Test that multiple negative peaks are handled correctly""" def callback(): x, y = 12, 7 self.im.getImage().set(x, y, -100) self.peaks[1].append((x, y)) self.doTestPeaks(polarity=False, callback=callback) def testGrowFootprints(self): """Test that we can grow footprints, correctly merging those that now touch""" def callback(): self.im.getImage().set(10, 4, 20) self.peaks[-2].append((10, 4,)) self.doTestPeaks(dwidth=1, dheight=1, callback=callback, grow=1) def testGrowFootprints2(self): """Test that we can grow footprints, correctly merging those that now overlap N.b. this caused RHL's initial implementation to crash """ def callback(): self.im.getImage().set(10, 4, 20) self.peaks[-2].append((10, 4, )) self.peaks[0] = sorted(sum(self.peaks, []), lambda x, y: cmpPeaks(self.im, x, y)) self.doTestPeaks(x0=0, y0=2, dwidth=2, dheight=2, callback=callback, grow=2) def testGrowFootprints3(self): """Test that we can grow footprints, correctly merging those that now totally overwritten""" self.im = afwImage.MaskedImageF(14, 11) self.im.getImage().set(0) self.peaks = [] I = 11 for x, y in [(4, 7), (5, 7), (6, 7), (7, 7), (8, 7), (4, 6), (8, 6), (4, 5), (8, 5), (4, 4), (8, 4), (4, 3), (8, 3), ]: self.im.getImage().set(x, y, I) I -= 1e-3 self.im.getImage().set(4, 7, 15) self.peaks.append([(4, 7,),]) self.im.getImage().set(6, 5, 30) self.peaks[0].append((6, 5,)) self.fs = afwDetect.FootprintSet(self.im, afwDetect.Threshold(10), "BINNED1") # # The disappearing Footprint special case only shows up if the outer Footprint is grown # _after_ the inner one. So arrange the order properly feet = self.fs.getFootprints() feet[0], feet[1] = feet[1], feet[0] msk = self.im.getMask() grow = 2 self.fs = afwDetect.FootprintSet(self.fs, grow, False) afwDetect.setMaskFromFootprintList(msk, self.fs.getFootprints(), msk.getPlaneBitMask("DETECTED_NEGATIVE")) if display: frame = 0 ds9.mtv(self.im, frame=frame) with ds9.Buffering(): for i, foot in enumerate(self.fs.getFootprints()): for p in foot.getPeaks(): ds9.dot("+", p.getIx(), p.getIy(), size=0.4, frame=frame) if i < len(self.peaks): for trueX, trueY in self.peaks[i]: ds9.dot("x", trueX, trueY, size=0.4, ctype=ds9.RED, frame=frame) self.assertEqual(len(self.fs.getFootprints()), 1) self.assertEqual(len(self.fs.getFootprints()[0].getPeaks()), len(self.peaks[0])) def testMergeFootprints(self): # YYYY """Merge positive and negative Footprints""" x0, y0 = 5, 6 dwidth, dheight = 6, 7 def callback(): x, y, I = x0 + 10, y0 + 4, -20 self.im.getImage().set(x, y, I) peaks2.append((x, y, I)) for grow1, grow2 in [(1, 1), (3, 3), (6, 6), ]: peaks2 = [] self.doTestPeaks(threshold=10, callback=callback, grow=0, x0=x0, y0=y0, dwidth=dwidth, dheight=dheight) threshold = afwDetect.Threshold(10, afwDetect.Threshold.VALUE, False) fs2 = afwDetect.FootprintSet(self.im, threshold) msk = self.im.getMask() afwDetect.setMaskFromFootprintList(msk, fs2.getFootprints(), msk.getPlaneBitMask("DETECTED_NEGATIVE")) self.fs.merge(fs2, grow1, grow2) self.peaks[-2] += peaks2 if grow1 + grow2 > 2: # grow merged all peaks self.peaks[0] = sorted(sum(self.peaks, []), lambda x, y: cmpPeaks(self.im, x, y)) afwDetect.setMaskFromFootprintList(msk, self.fs.getFootprints(), msk.getPlaneBitMask("EDGE")) self.checkPeaks(frame=3) def testMergeFootprintsEngulf(self): """Merge two Footprints when growing one Footprint totally replaces the other""" def callback(): self.im.set(0) self.peaks, self.objects = [], [] for x, y, I in [[6, 4, 20], [6, 5, 10]]: self.im.getImage().set(x, y, I) self.peaks.append([[6, 4]]) x, y, I = 8, 4, -20 self.im.getImage().set(x, y, I) peaks2.append((x, y, I)) grow1, grow2 = 0, 3 peaks2 = [] self.doTestPeaks(threshold=10, callback=callback, grow=0) threshold = afwDetect.Threshold(10, afwDetect.Threshold.VALUE, False) fs2 = afwDetect.FootprintSet(self.im, threshold) msk = self.im.getMask() afwDetect.setMaskFromFootprintList(msk, fs2.getFootprints(), msk.getPlaneBitMask("DETECTED_NEGATIVE")) self.fs.merge(fs2, grow1, grow2) self.peaks[0] += peaks2 self.peaks[0] = sorted(sum(self.peaks, []), lambda x, y: cmpPeaks(self.im, x, y)) afwDetect.setMaskFromFootprintList(msk, self.fs.getFootprints(), msk.getPlaneBitMask("EDGE")) self.checkPeaks(frame=3) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" tests.init() suites = [] suites += unittest.makeSuite(FootprintSetTestCase) suites += unittest.makeSuite(PeaksInFootprintsTestCase) suites += unittest.makeSuite(tests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" tests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    20c2c467

    commit 20c2c46776ad69164993f9837f347800a80f245b
    Author: jbosch 
    Date:   Fri Mar 4 01:19:01 2011 +0000
    
        afw #1556 - fixed all python unit tests with trivial syntax-related failures, plus a few others
    

    e6fac15b

    commit e6fac15b292b2c4c91b306d1ea8bf11440966cf9
    Author: krughoff 
    Date:   Wed May 5 16:07:17 2010 +0000
    
        Added explicit instantiations of FootprintSet for ImageU and ImageI.  Added test case for ImageU.
    

    b513fa75

    commit b513fa75234309dfaf0db8025e0d4b9e2383575e
    Author: Robert Lupton the Good 
    Date:   Wed May 30 15:56:09 2012 -0400
    
        Added FootprintCtrl class to control Footprint manipulations such as growing
        
        N.b. No functionality is added yet; this is just a new API for isotropic grows
    

    61b6195c

    commit 61b6195c87e9320e84ffff47c38353a6d945d173
    Author: Robert Lupton the Good 
    Date:   Sat May 9 16:53:20 2015 -0400
    
        Overwrote master with files checked out from HSC-1246
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    e6fac15b

    commit e6fac15b292b2c4c91b306d1ea8bf11440966cf9
    Author: krughoff 
    Date:   Wed May 5 16:07:17 2010 +0000
    
        Added explicit instantiations of FootprintSet for ImageU and ImageI.  Added test case for ImageU.
    

    Return to list

    python/lsst/afw/table/Source.i

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    /*
                     * Wrappers for SourceTable, SourceRecord, and SourceColumnView (and, via Simple.i, their dependencies).
                     * Also includes SortedCatalog.i and instantiates SourceCatalog.
                     *
                     * This file does not include Exposure- Record/Table/Catalog, or the matching functions.
                     */
                    
                    %include "lsst/afw/table/Simple.i"
                    
                    %{
    
    33 0c8edce7 + #include "lsst/afw/table/slots.h"
    #include "lsst/afw/table/Source.h" %} namespace lsst { namespace afw { namespace image { class Wcs; } namespace detection { class Footprint; } }} %shared_ptr(lsst::afw::image::Wcs); %shared_ptr(lsst::afw::detection::Footprint); // =============== SourceTable and SourceRecord ============================================================= %shared_ptr(lsst::afw::table::SourceTable) %shared_ptr(lsst::afw::table::SourceRecord)
    51 0c8edce7 +
    // Workarounds for SWIG's failure to parse the Measurement template correctly. // Otherwise we'd have one place in the code that controls all the canonical measurement types. namespace lsst { namespace afw { namespace table { struct Flux { typedef Key< double > MeasKey; typedef Key< double > ErrKey; typedef double MeasValue; typedef double ErrValue; }; struct Centroid { typedef Key< Point > MeasKey; typedef Key< Covariance< Point > > ErrKey; typedef lsst::afw::geom::Point MeasValue; typedef Eigen::Matrix ErrValue; }; struct Shape { typedef Key< Moments > MeasKey; typedef Key< Covariance< Moments > > ErrKey; typedef lsst::afw::geom::ellipses::Quadrupole MeasValue; typedef Eigen::Matrix ErrValue; }; }}}
    75 0c8edce7 + %include "lsst/afw/table/slots.h"
    73 29b582cc - %define %enableSlotKwArgs(SLOT)
    74 29b582cc - %extend lsst::afw::table::SourceTable {
    75 29b582cc - %feature("shadow") define ## SLOT %{
    76 29b582cc - def define ## SLOT(self, meas, err=None, flag=None):
    77 29b582cc - if err is None:
    78 29b582cc - if flag is None:
    79 29b582cc - $action(self, meas)
    80 29b582cc - else:
    81 29b582cc - $action(self, meas, flag)
    82 29b582cc - else:
    83 29b582cc - if flag is None:
    84 29b582cc - $action(self, meas, err)
    85 29b582cc - else:
    86 29b582cc - $action(self, meas, err, flag)
    87 29b582cc - %}
    88 29b582cc - }
    89 29b582cc - %enddef
    90 29b582cc -
    91 29b582cc - %enableSlotKwArgs(PsfFlux)
    92 29b582cc - %enableSlotKwArgs(ApFlux)
    93 29b582cc - %enableSlotKwArgs(InstFlux)
    94 29b582cc - %enableSlotKwArgs(ModelFlux)
    95 29b582cc - %enableSlotKwArgs(Centroid)
    96 29b582cc - %enableSlotKwArgs(Shape)
    %include "lsst/afw/table/Source.h" %addCastMethod(lsst::afw::table::SourceTable, lsst::afw::table::BaseTable) %addCastMethod(lsst::afw::table::SourceRecord, lsst::afw::table::BaseRecord) %addCastMethod(lsst::afw::table::SourceTable, lsst::afw::table::SimpleTable) %addCastMethod(lsst::afw::table::SourceRecord, lsst::afw::table::SimpleRecord) %template(_SourceColumnViewBase) lsst::afw::table::ColumnViewT; %template(SourceColumnView) lsst::afw::table::SourceColumnViewT; // =============== Catalogs ================================================================================= %include "lsst/afw/table/SortedCatalog.i" namespace lsst { namespace afw { namespace table { %declareSortedCatalog(SortedCatalogT, Source) // n.b. can't figure out how to %extend a particular template instantiation, // but this works fine %pythoncode %{ def getChildren(self, parent, *args): """Return the subset of self for which the parent field equals the given value. In order for this method to return the correct result, it must be sorted by parent (i.e. self.isSorted(SourceTable.getParentKey()) must be True). This is naturally the case with SourceCatalogs produced by the detection and deblending tasks, but it may not be true when concatenating multiple such catalogs. Additional Catalogs or sequences whose elements correspond in order to the records of self (i.e. zip(self, *args) is valid) will be subset using the same slice object used on self, and these subsets will be returned along with the subset of self. """ s = self.equal_range(parent, SourceTable.getParentKey()) if args: return (self[s],) + tuple(arg[s] for arg in args) else: return self[s] SourceCatalog.getChildren = getChildren %} }}} // namespace lsst::afw::table

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    29b582cc

    commit 29b582ccfe0b1381c2876ac1a58f43ce23550f9e
    Author: Jim Bosch 
    Date:   Tue Jan 22 14:52:56 2013 -0500
    
        Overhaul afw::table SWIG to enable more fine-grained %imports.
    

    Commits in /Users/nate/repos_lsst/afw/

    0c8edce7

    commit 0c8edce7dfb2db4539497ac18187e75d2494f4e4
    Author: Jim Bosch 
    Date:   Mon Aug 25 01:48:39 2014 -0400
    
        Switch to new slot definition classes, using aliases for version>0
    

    Return to list

    tests/maskedImageIO.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for MaskedImages Run with: python MaskedImageIO.py or python >>> import MaskedImageIO; MaskedImageIO.run() """
    36 eb37ae8a - import os, re
    37 c605dfcd + import os.path
    import unittest import numpy
    40 43bf1bb6 - import eups
    42 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.afw.display.ds9 as ds9 import lsst.pex.exceptions as pexEx
    49 7cbb2bb9 + dataDir = lsst.utils.getPackageDir("afwdata")
    48 456d42a8 - dataDir = eups.productDir("afwdata")
    49 7a8a5f78 - if not dataDir:
    50 456d42a8 - raise RuntimeError("You must set up afwdata to run these tests")
    try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class MaskedImageTestCase(unittest.TestCase): """A test case for MaskedImage""" def setUp(self): # Set a (non-standard) initial Mask plane definition # # Ideally we'd use the standard dictionary and a non-standard file, but # a standard file's what we have # mask = afwImage.MaskU() mask.clearMaskPlaneDict() for p in ("ZERO", "BAD", "SAT", "INTRP", "CR", "EDGE"): mask.addMaskPlane(p) if False: self.fileName = os.path.join(dataDir, "Small_MI.fits") else: self.fileName = os.path.join(dataDir, "CFHT", "D4", "cal-53535-i-797722_1.fits") self.mi = afwImage.MaskedImageF(self.fileName) def tearDown(self): del self.mi def testFitsRead(self): """Check if we read MaskedImages""" image = self.mi.getImage() mask = self.mi.getMask() if display: ds9.mtv(self.mi) self.assertEqual(image.get(32, 1), 3728) self.assertEqual(mask.get(0, 0), 2) # == BAD def testFitsReadImage(self): """Check if we can read a single-HDU image as a MaskedImage, setting the mask and variance planes to zero.""" filename = os.path.join(dataDir, "data", "small_img.fits") image = afwImage.ImageF(filename) maskedImage = afwImage.MaskedImageF(filename) exposure = afwImage.ExposureF(filename) self.assertEqual(image.get(0,0), maskedImage.getImage().get(0,0)) self.assertEqual(image.get(0,0), exposure.getMaskedImage().getImage().get(0,0)) self.assert_(numpy.all(maskedImage.getMask().getArray() == 0)) self.assert_(numpy.all(exposure.getMaskedImage().getMask().getArray() == 0)) self.assert_(numpy.all(maskedImage.getVariance().getArray() == 0.0)) self.assert_(numpy.all(exposure.getMaskedImage().getVariance().getArray() == 0.0)) def testFitsReadConform(self): """Check if we read MaskedImages and make them replace Mask's plane dictionary""" metadata, bbox, conformMasks = None, afwGeom.Box2I(), True self.mi = afwImage.MaskedImageF(self.fileName, metadata, bbox, afwImage.LOCAL, conformMasks) image = self.mi.getImage() mask = self.mi.getMask() self.assertEqual(image.get(32, 1), 3728) self.assertEqual(mask.get(0, 0), 1) # i.e. not shifted 1 place to the right self.assertEqual(mask.getMaskPlane("CR"), 3, "Plane CR has value specified in FITS file") def testFitsReadNoConform2(self): """Check that reading a mask doesn't invalidate the plane dictionary""" testMask = afwImage.MaskU(self.fileName, 3) mask = self.mi.getMask() mask |= testMask def testFitsReadConform2(self): """Check that conforming a mask invalidates the plane dictionary""" hdu, metadata, bbox, conformMasks = 3, None, afwGeom.Box2I(), True testMask = afwImage.MaskU(self.fileName, hdu, metadata, bbox, afwImage.LOCAL, conformMasks) mask = self.mi.getMask() def tst(mask=mask): mask |= testMask
    141 3771b5eb - utilsTests.assertRaisesLsstCpp(self, pexEx.RuntimeErrorException, tst)
    140 6fc1c3d1 + self.assertRaises(pexEx.RuntimeError, tst)
    def testTicket617(self): """Test reading an F64 image and converting it to a MaskedImage""" im = afwImage.ImageD(afwGeom.Extent2I(100, 100)) im.set(666) mi = afwImage.MaskedImageD(im) def testReadWriteXY0(self): """Test that we read and write (X0, Y0) correctly""" im = afwImage.MaskedImageF(afwGeom.Extent2I(10, 20)) x0, y0 = 1, 2 im.setXY0(x0, y0)
    155 ded0eb52 - tmpFile = "foo.fits"
    154 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    156 4940d876 - im.writeFits(tmpFile)
    155 c605dfcd + im.writeFits(tmpFile)
    ? ++++
    158 4940d876 - im2 = im.Factory(tmpFile)
    157 c605dfcd + im2 = im.Factory(tmpFile)
    ? ++++
    159 4940d876 - self.assertEqual(im2.getX0(), x0)
    158 c605dfcd + self.assertEqual(im2.getX0(), x0)
    ? ++++
    160 4940d876 - self.assertEqual(im2.getY0(), y0)
    159 c605dfcd + self.assertEqual(im2.getY0(), y0)
    ? ++++
    162 4940d876 - self.assertEqual(im2.getImage().getX0(), x0)
    161 c605dfcd + self.assertEqual(im2.getImage().getX0(), x0)
    ? ++++
    163 4940d876 - self.assertEqual(im2.getImage().getY0(), y0)
    162 c605dfcd + self.assertEqual(im2.getImage().getY0(), y0)
    ? ++++
    165 4940d876 - self.assertEqual(im2.getMask().getX0(), x0)
    164 c605dfcd + self.assertEqual(im2.getMask().getX0(), x0)
    ? ++++
    166 4940d876 - self.assertEqual(im2.getMask().getY0(), y0)
    165 c605dfcd + self.assertEqual(im2.getMask().getY0(), y0)
    ? ++++
    167 4940d876 -
    166 c605dfcd +
    ? ++++
    168 4940d876 - self.assertEqual(im2.getVariance().getX0(), x0)
    167 c605dfcd + self.assertEqual(im2.getVariance().getX0(), x0)
    ? ++++
    169 4940d876 - self.assertEqual(im2.getVariance().getY0(), y0)
    168 c605dfcd + self.assertEqual(im2.getVariance().getY0(), y0)
    ? ++++
    170 4940d876 -
    171 ded0eb52 - os.remove(tmpFile)
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(MaskedImageTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    43bf1bb6

    commit 43bf1bb6d86108cd22d4b81089d494c3abeee859
    Author: rowen 
    Date:   Fri Mar 28 00:03:21 2008 +0000
    
        afw reorg:
        - Corrected pex/policy -> daf/policy
        - Tweaked test code to make it more uniform and fix names based on the old layout
    

    eb37ae8a

    commit eb37ae8a4a510afdfed8a5373ce1237ef2c7e38f
    Author: rhl 
    Date:   Wed May 20 22:06:40 2009 +0000
    
        Initial version
    

    4940d876

    commit 4940d876a0c927f4d36a74848ee3e542b9503fa6
    Author: rhl 
    Date:   Wed Mar 25 22:55:37 2009 +0000
    
        Save and restore Mask and Image (and thus MaskedImage and Exposure) (X0, Y0) when writing to FITS.  The information is written to an extra WCS, WCSA.  Switched WCSA and WCSB in ds9 display to be consistent with this
    

    ded0eb52

    commit ded0eb52af9b4e28790afe94d115c1d8699fa271
    Author: Jim Bosch 
    Date:   Tue Nov 20 00:46:52 2012 -0500
    
        Overhaul FITS persistence for MaskedImage and Exposure: no more appending or passing HDU to read, no more multi-file support, but we put metadata in primary HDU and use INHERIT keyword (as per discussion on lsst-data list).
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    7a8a5f78

    commit 7a8a5f780e5f21073e2c2224a5ba1a1149710580
    Author: rhl 
    Date:   Thu Mar 20 23:19:57 2008 +0000
    
        Test simply reading a single file for now
    

    456d42a8

    commit 456d42a80026bc8b0961131936d467cf68af2f68
    Author: rowen 
    Date:   Fri Mar 28 17:10:01 2008 +0000
    
        afw reorg:
        - Updated use of fwData -> afwdata
        - Fixed forward declarations of Formatter in image classes
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    include/lsst/afw/image/fits/fits_io.h

    Diff:

                    // -*- lsst-c++ -*-
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #ifndef LSST_AFW_IMAGE_fits_io_h_INCLUDED
                    #define LSST_AFW_IMAGE_fits_io_h_INCLUDED
                    
                    #include 
                    
                    #include "boost/format.hpp"
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/fits.h"
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/image/Wcs.h"
                    #include "ndarray.h"
                    
                    namespace lsst { namespace afw { namespace image {
                    
                    template 
                    inline void fits_read_array(
                        fits::Fits & fitsfile,
                        ndarray::Array & array,
                        geom::Point2I & xy0,
                        lsst::daf::base::PropertySet & metadata,
    
    44 42dadff6 - geom::Box2I bbox = geom::Box2I(),
    ? - -
    44 eea3eb4a + geom::Box2I bbox=geom::Box2I(),
    45 42dadff6 - ImageOrigin origin = LOCAL
    ? - ^^^^ ^
    45 eea3eb4a + ImageOrigin origin=PARENT
    ? ^ ^^^^ ) { if (!fitsfile.checkImageType()) { throw LSST_FITS_EXCEPT( fits::FitsTypeError, fitsfile, "Incorrect image type for FITS image" ); }
    54 f8edfe90 -
    int nAxis = fitsfile.getImageDim(); ndarray::Vector shape; if (nAxis == 2) { shape = fitsfile.getImageShape<2>(); } else if (nAxis == 3) { ndarray::Vector shape3 = fitsfile.getImageShape<3>(); if (shape3[0] != 1) { throw LSST_EXCEPT( fits::FitsError, boost::str(boost::format("3rd dimension %d is not 1") % shape3[0]) ); } shape = shape3.last<2>(); } fitsfile.readMetadata(metadata, true); // Origin of part of image to read xy0 = geom::Point2I(); geom::Extent2I xyOffset(detail::getImageXY0FromMetadata(detail::wcsNameForXY0, &metadata)); geom::Extent2I dimensions = geom::Extent2I(shape[1], shape[0]); if (!bbox.isEmpty()) {
    79 42dadff6 - if(origin == PARENT) {
    78 93994d54 + if (origin == PARENT) {
    ? + bbox.shift(-xyOffset); } xy0 = bbox.getMin(); if (bbox.getMinX() < 0 || bbox.getMinY() < 0 || bbox.getWidth() > dimensions.getX() || bbox.getHeight() > dimensions.getY() ) { throw LSST_EXCEPT(
    88 42dadff6 - lsst::pex::exceptions::LengthErrorException,
    ? ---------
    87 21597d88 + lsst::pex::exceptions::LengthError,
    (boost::format("BBox (%d,%d) %dx%d doesn't fit in image %dx%d") % bbox.getMinX() % bbox.getMinY() % bbox.getWidth() % bbox.getHeight() % dimensions.getX() % dimensions.getY()).str() ); } dimensions = bbox.getDimensions(); } array = ndarray::allocate(dimensions.getY(), dimensions.getX()); fitsfile.readImage(array, ndarray::makeVector(xy0.getY(), xy0.getX())); xy0 += xyOffset; } template inline void fits_write_image( fits::Fits & fitsfile, const ImageT & image,
    107 6ebf0bdb - CONST_PTR(daf::base::PropertySet) metadata = CONST_PTR(daf::base::PropertySet)()
    ? - -
    106 eea3eb4a + CONST_PTR(daf::base::PropertySet) metadata=CONST_PTR(daf::base::PropertySet)()
    ) { fitsfile.createImage(image.getArray().getShape()); if (metadata) { fitsfile.writeMetadata(*metadata); } fitsfile.writeImage(image.getArray()); } }}} // namespace lsst::afw::image #endif // !LSST_AFW_IMAGE_fits_io_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    42dadff6

    commit 42dadff68d69c7a54f53cc9d55fe0153e7a5b350
    Author: Jim Bosch 
    Date:   Sun Nov 18 18:50:24 2012 -0500
    
        Reimplement FITS image reading to use afw::fits
    

    6ebf0bdb

    commit 6ebf0bdb17931644394d561d985fb8804167bdf5
    Author: Jim Bosch 
    Date:   Fri Nov 16 15:10:29 2012 -0500
    
        Overhaul image FITS writing to reduce code duplication, play nicer when combining Image and Table HDUs.
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    eea3eb4a

    commit eea3eb4aaa72e0956cce3c5a4bb2c78863540dd3
    Author: Russell Owen 
    Date:   Thu Sep 18 17:23:09 2014 -0700
    
        Respond to review by restoring LOCAL where appropriate.
        Also enhanced documentation in detection.py
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    tests/image.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Images Run with: ./Image.py or python >>> import Image; Image.run() """
    35 f8edfe90 - import os
    import os.path
    38 8b486590 + import shutil
    import sys
    40 8b486590 + import tempfile
    import unittest
    43 7cbb2bb9 + import lsst.utils
    import lsst.utils.tests as utilsTests import lsst.pex.exceptions import lsst.daf.base import lsst.afw.image as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom
    47 f8edfe90 - import eups
    import lsst.afw.display.ds9 as ds9 import numpy
    53 54a43c29 +
    54 4bae7ca1 + numpy.random.seed(1)
    try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class ImageTestCase(unittest.TestCase): """A test case for Image""" def setUp(self): self.val1, self.val2 = 10, 100 self.image1 = afwImage.ImageF(afwGeom.ExtentI(100, 200)) self.image1.set(self.val1) self.image2 = afwImage.ImageF(self.image1.getDimensions()) self.image2.set(self.val2) self.function = afwMath.PolynomialFunction2D(2) self.function.setParameters(range(self.function.getNParameters())) def tearDown(self): del self.image1 del self.image2 del self.function def testArrays(self): for cls in (afwImage.ImageU, afwImage.ImageI, afwImage.ImageF, afwImage.ImageD): image1 = cls(afwGeom.Extent2I(5,6)) array1 = image1.getArray() self.assertEqual(array1.shape[0], image1.getHeight()) self.assertEqual(array1.shape[1], image1.getWidth()) image2 = cls(array1, False) self.assertEqual(array1.shape[0], image2.getHeight()) self.assertEqual(array1.shape[1], image2.getWidth()) image3 = afwImage.makeImageFromArray(array1) self.assertEqual(array1.shape[0], image2.getHeight()) self.assertEqual(array1.shape[1], image2.getWidth()) self.assertEqual(type(image3), cls) array1[:,:] = numpy.random.uniform(low=0, high=10, size=array1.shape) for j in range(image1.getHeight()): for i in range(image1.getWidth()): self.assertEqual(image1.get(i, j), array1[j, i]) self.assertEqual(image2.get(i, j), array1[j, i]) def testInitializeImages(self): val = 666 for ctor in (afwImage.ImageU, afwImage.ImageI, afwImage.ImageF, afwImage.ImageD): im = ctor(10, 10, val) self.assertEqual(im.get(0, 0), val) im2 = ctor(afwGeom.Box2I(afwGeom.Point2I(0,0), afwGeom.Extent2I(10, 10)), val) self.assertEqual(im2.get(0, 0), val) def testSetGetImages(self): self.assertEqual(self.image1.get(0, 0), self.val1) def testGetSet0Images(self): self.assertEqual(self.image1.get0(0, 0), self.val1) self.image1.setXY0(3,4) self.assertEqual(self.image1.get0(3, 4), self.val1) def f1(): return self.image1.get0(0,0)
    112 b0e0d3fb - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, f1)
    ? ^^^ ^^^^^^ ------- ------ ---------
    116 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, f1)
    ? ^^ ^ self.image1.set(0,0, 42.) self.assertEqual(self.image1.get0(3,4), 42.) self.image1.set0(3,4, self.val1) self.assertEqual(self.image1.get0(3,4), self.val1) self.assertEqual(self.image1.get(0,0), self.val1) def testAllocateLargeImages(self): """Try to allocate a Very large image""" bbox = afwGeom.BoxI(afwGeom.PointI(-1<<30, -1<<30), afwGeom.PointI(1<<30, 1<<30)) def tst(): im = afwImage.ImageF(bbox)
    126 4abc0a0c - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst)
    ? ^^^ ^^^^^^ ------- ------ ---------
    130 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst)
    ? ^^ ^ def testAddImages(self): self.image2 += self.image1 self.image1 += self.val1 self.assertEqual(self.image1.get(0, 0), 2*self.val1) self.assertEqual(self.image2.get(0, 0), self.val1 + self.val2) self.image1.set(self.val1) self.image1 += self.function for j in range(self.image1.getHeight()): for i in range(self.image1.getWidth()): self.assertEqual(self.image1.get(i, j), self.val1 + self.function(i, j)) def testBoundsChecking(self): """Check that pixel indexes are checked in python""" tsts = [] def tst(): self.image1.get(-1, 0) tsts.append(tst) def tst(): self.image1.get(0, -1) tsts.append(tst) def tst(): self.image1.get(self.image1.getWidth(), 0) tsts.append(tst) def tst(): self.image1.get(0, self.image1.getHeight()) tsts.append(tst) for tst in tsts:
    162 35b5e4e6 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst)
    ? ^^^ ^^^^^^ ------- ------ ---------
    166 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst)
    ? ^^ ^ def testAddScaledImages(self): c = 10.0 self.image1.scaledPlus(c, self.image2) self.assertEqual(self.image1.get(0, 0), self.val1 + c*self.val2) def testSubtractImages(self): self.image2 -= self.image1 self.image1 -= self.val1 self.assertEqual(self.image1.get(0, 0), 0) self.assertEqual(self.image2.get(0, 0), self.val2 - self.val1) self.image1.set(self.val1) self.image1 -= self.function for j in range(self.image1.getHeight()): for i in range(self.image1.getWidth()): self.assertEqual(self.image1.get(i, j), self.val1 - self.function(i, j)) def testArithmeticImagesMismatch(self): "Test arithmetic operations on Images of different sizes" i1 = afwImage.ImageF(100, 100) i1.set(100) i2 = afwImage.ImageF(10, 10) i2.set(10) def tst1(i1, i2): i1 -= i2 def tst2(i1, i2): i1.scaledMinus(1.0, i2) def tst3(i1, i2): i1 += i2 def tst4(i1, i2): i1.scaledPlus(1.0, i2) def tst5(i1, i2): i1 *= i2 def tst6(i1, i2): i1.scaledMultiplies(1.0, i2) def tst7(i1, i2): i1 /= i2 def tst8(i1, i2): i1.scaledDivides(1.0, i2) tsts12 = [tst1, tst3, tst5, tst7] for tst in tsts12:
    210 a7aa0c91 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst, i1, i2)
    ? ^^^ ^^^^^^ ------- ------ ---------
    214 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst, i1, i2)
    ? ^^ ^ tsts21 = [tst2, tst4, tst6, tst8] for tst in tsts21:
    214 a7aa0c91 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst, i2, i1)
    ? ^^^ ^^^^^^ ------- ------ ---------
    218 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst, i2, i1)
    ? ^^ ^ def testSubtractScaledImages(self): c = 10.0 self.image1.scaledMinus(c, self.image2) self.assertEqual(self.image1.get(0, 0), self.val1 - c*self.val2) def testMultiplyImages(self): self.image2 *= self.image1 self.image1 *= self.val1 self.assertEqual(self.image1.get(0, 0), self.val1*self.val1) self.assertEqual(self.image2.get(0, 0), self.val2*self.val1) def testMultiplesScaledImages(self): c = 10.0 self.image1.scaledMultiplies(c, self.image2) self.assertEqual(self.image1.get(0, 0), self.val1 * c*self.val2) def testDivideImages(self): self.image2 /= self.image1 self.image1 /= self.val1 self.assertEqual(self.image1.get(0, 0), 1) self.assertEqual(self.image2.get(0, 0), self.val2/self.val1) def testDividesScaledImages(self): c = 10.0 self.image1.scaledDivides(c, self.image2) self.assertAlmostEqual(self.image1.get(0, 0), self.val1/(c*self.val2)) def testCopyConstructors(self): dimage = afwImage.ImageF(self.image1, True) # deep copy simage = afwImage.ImageF(self.image1) # shallow copy self.image1 += 2 # should only change dimage self.assertEqual(dimage.get(0, 0), self.val1) self.assertEqual(simage.get(0, 0), self.val1 + 2) def testGeneralisedCopyConstructors(self): imageU = self.image1.convertU() # these are generalised (templated) copy constructors in C++ imageF = imageU.convertF() imageD = imageF.convertD() self.assertEqual(imageU.get(0, 0), self.val1) self.assertEqual(imageF.get(0, 0), self.val1) self.assertEqual(imageD.get(0, 0), self.val1) def checkImgPatch(self, img, x0=0, y0=0): """Check that a patch of an image is correct; origin of patch is at (x0, y0)""" self.assertEqual(img.get(x0 - 1, y0 - 1), self.val1) self.assertEqual(img.get(x0, y0), 666) self.assertEqual(img.get(x0 + 3, y0), self.val1) self.assertEqual(img.get(x0, y0 + 1), 666) self.assertEqual(img.get(x0 + 3, y0 + 1), self.val1) self.assertEqual(img.get(x0, y0 + 2), self.val1) def testOrigin(self): """Check that we can set and read the origin""" im = afwImage.ImageF(10, 20) x0 = y0 = 0 self.assertEqual(im.getX0(), x0) self.assertEqual(im.getY0(), y0) self.assertEqual(im.getXY0(), afwGeom.Point2I(x0, y0)) x0, y0 = 3, 5 im.setXY0(x0, y0) self.assertEqual(im.getX0(), x0) self.assertEqual(im.getY0(), y0) self.assertEqual(im.getXY0(), afwGeom.Point2I(x0, y0)) x0, y0 = 30, 50 im.setXY0(afwGeom.Point2I(x0, y0)) self.assertEqual(im.getX0(), x0) self.assertEqual(im.getY0(), y0) self.assertEqual(im.getXY0(), afwGeom.Point2I(x0, y0)) def testSubimages(self): simage1 = afwImage.ImageF( self.image1, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(10, 5)), afwImage.LOCAL) simage = afwImage.ImageF( simage1, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(3, 2)), afwImage.LOCAL ) self.assertEqual(simage.getX0(), 2) self.assertEqual(simage.getY0(), 2) # i.e. wrt self.image1 image2 = afwImage.ImageF(simage.getDimensions()) image2.set(666) simage <<= image2 del simage del image2 self.checkImgPatch(self.image1, 2, 2) self.checkImgPatch(simage1, 1, 1) def testSubimages2(self): """Test subimages when we've played with the (x0, y0) value""" self.image1.set(9, 4, 888) #printImg(afwImage.ImageF(self.image1, afwGeom.Box2I(afwGeom.Point2I(0, 0), afwGeom.Extent2I(10, 5)))); print simage1 = afwImage.ImageF( self.image1, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(10, 5)), afwImage.LOCAL ) simage1.setXY0(afwGeom.Point2I(0, 0)) # reset origin; doesn't affect pixel coordinate systems simage = afwImage.ImageF( simage1, afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(3, 2)), afwImage.LOCAL ) self.assertEqual(simage.getX0(), 1) self.assertEqual(simage.getY0(), 1) image2 = afwImage.ImageF(simage.getDimensions()) image2.set(666) simage <<= image2 del simage del image2 self.checkImgPatch(self.image1, 2, 2) self.checkImgPatch(simage1, 1, 1) def testBadSubimages(self): def tst(): simage1 = afwImage.ImageF( self.image1, afwGeom.Box2I(afwGeom.Point2I(1, -1), afwGeom.Extent2I(10, 5)), afwImage.LOCAL )
    360 39c6d678 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.LengthErrorException, tst)
    ? ^^^ ^^^^^^ ------- ------ ---------
    364 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.LengthError, tst)
    ? ^^ ^ def testImageInitialisation(self): dims = self.image1.getDimensions() factory = self.image1.Factory self.image1.set(666) del self.image1 # tempt C++ to reuse the memory self.image1 = factory(dims) self.assertEqual(self.image1.get(10, 10), 0) def testImageSlices(self): """Test image slicing, which generate sub-images using Box2I under the covers""" im = afwImage.ImageF(10, 20) im[-1, :] = -5 im[..., 18] = -5 # equivalent to im[:, 18] im[4, 10] = 10 im[-3:, -2:] = 100 im[-2, -2] = -10 sim = im[1:4, 6:10] sim[:] = -1 im[0:4, 0:4] = im[2:6, 8:12] if display: ds9.mtv(im) self.assertEqual(im.get(0, 6), 0) self.assertEqual(im.get(9, 15), -5) self.assertEqual(im.get(5, 18), -5) self.assertEqual(im.get(6, 17), 0) self.assertEqual(im.get(7, 18),100) self.assertEqual(im.get(9, 19),100) self.assertEqual(im.get(8, 18),-10) self.assertEqual(im.get(1, 6), -1) self.assertEqual(im.get(3, 9), -1) self.assertEqual(im.get(4, 10), 10) self.assertEqual(im.get(4, 9), 0) self.assertEqual(im.get(2, 2), 10) self.assertEqual(im.get(0, 0), -1) def testImageSliceFromBox(self): """Test using a Box2I to index an Image""" im = afwImage.ImageF(10, 20) bbox = afwGeom.BoxI(afwGeom.PointI(1, 3), afwGeom.PointI(6, 9)) im[bbox] = -1 if display: ds9.mtv(im) self.assertEqual(im.get(0, 6), 0) self.assertEqual(im.get(1, 6), -1) self.assertEqual(im.get(3, 9), -1) def testConversionToScalar(self): """Test that 1-pixel images can be converted to scalars""" self.assertEqual(int(afwImage.ImageI(1, 1)), 0.0) self.assertEqual(float(afwImage.ImageI(1, 1)), 0.0) im = afwImage.ImageF(10, 20) im.set(666) self.assertEqual(float(im[0,0]), 666) self.assertEqual(int(im[0,0]), 666) self.assertRaises(TypeError, int, im) # only single pixel images may be converted self.assertRaises(TypeError, float, im) # only single pixel images may be converted def testClone(self): """Test that clone works properly""" im = afwImage.ImageF(10, 20) im[0, 0] = 100 im2 = im.clone() # check that clone with no arguments makes a deep copy self.assertEqual(im.getDimensions(), im2.getDimensions()) self.assertEqual(im.get(0,0), im2.get(0,0)) im2[0, 0] += 100 self.assertNotEqual(im.get(0,0), im2.get(0,0)) # so it's a deep copy im2 = im[0:3, 0:5].clone() # check that we can slice-then-clone self.assertEqual(im2.getDimensions(), afwGeom.ExtentI(3, 5)) self.assertEqual(im.get(0,0), im2.get(0,0)) im2[0,0] += 10 self.assertNotEqual(float(im[0,0]), float(im2[0,0])) # equivalent to im.get(0, 0) etc. #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class DecoratedImageTestCase(unittest.TestCase): """A test case for DecoratedImage""" def setUp(self): self.val1, self.val2 = 10, 100 self.width, self.height = 200, 100 self.dimage1 = afwImage.DecoratedImageF( afwGeom.Extent2I(self.width, self.height) ) self.dimage1.getImage().set(self.val1)
    457 6bd29a86 - dataDir = eups.productDir("afwdata")
    458 f8edfe90 - if dataDir:
    461 7cbb2bb9 + try:
    462 7cbb2bb9 + dataDir = lsst.utils.getPackageDir("afwdata")
    463 7cbb2bb9 + except Exception:
    464 7cbb2bb9 + self.fileForMetadata = None
    465 7cbb2bb9 + else:
    self.fileForMetadata = os.path.join(dataDir, "data", "small_MI.fits") self.trueMetadata = {"RELHUMID" : 10.69}
    461 f8edfe90 - else:
    462 f8edfe90 - self.fileForMetadata = None
    def tearDown(self): del self.dimage1 def testCreateDecoratedImage(self): self.assertEqual(self.dimage1.getWidth(), self.width) self.assertEqual(self.dimage1.getHeight(), self.height) self.assertEqual(self.dimage1.getImage().get(0, 0), self.val1) def testCreateDecoratedImageFromImage(self): image = afwImage.ImageF(afwGeom.Extent2I(self.width, self.height)) image <<= self.dimage1.getImage() dimage = afwImage.DecoratedImageF(image) self.assertEqual(dimage.getWidth(), self.width) self.assertEqual(dimage.getHeight(), self.height) self.assertEqual(dimage.getImage().get(0, 0), self.val1) def testCopyConstructors(self): dimage = afwImage.DecoratedImageF(self.dimage1, True) # deep copy self.dimage1.getImage().set(0, 0, 1 + 2*self.val1) self.assertEqual(dimage.getImage().get(0, 0), self.val1) dimage = afwImage.DecoratedImageF(self.dimage1) # shallow copy self.dimage1.getImage().set(0, 0, 1 + 2*self.val1) self.assertNotEqual(dimage.getImage().get(0, 0), self.val1) def testReadFits(self): """Test reading FITS files"""
    497 7cbb2bb9 +
    498 7cbb2bb9 + try:
    499 7cbb2bb9 + dataDir = lsst.utils.getPackageDir("afwdata")
    500 7cbb2bb9 + except Exception:
    492 f8edfe90 -
    493 6bd29a86 - dataDir = eups.productDir("afwdata")
    494 6bd29a86 - if dataDir:
    495 6bd29a86 - dataDir = os.path.join(dataDir, "data")
    496 6bd29a86 - else:
    print >> sys.stderr, "Warning: afwdata is not set up; not running the FITS I/O tests" return
    503 7cbb2bb9 +
    504 7cbb2bb9 + dataDir = os.path.join(dataDir, "data")
    hdus = {} fileName = os.path.join(dataDir, "small_MI.fits") hdus["img"] = 2 # an S16 fits HDU hdus["msk"] = 3 # an U8 fits HDU hdus["var"] = 4 # an F32 fits HDU imgU = afwImage.DecoratedImageU(fileName, hdus["img"]) # read as unsigned short imgF = afwImage.DecoratedImageF(fileName, hdus["img"]) # read as float self.assertEqual(imgU.getHeight(), 256) self.assertEqual(imgF.getImage().getWidth(), 256) self.assertEqual(imgU.getImage().get(0, 0), imgF.getImage().get(0, 0)) # # Check the metadata # meta = self.trueMetadata for k in meta.keys(): self.assertEqual(imgU.getMetadata().getAsDouble(k), meta[k]) self.assertEqual(imgF.getMetadata().getAsDouble(k), meta[k]) # # Read an F32 image # varU = afwImage.DecoratedImageF(fileName, hdus["var"]) # read as unsigned short varF = afwImage.DecoratedImageF(fileName, hdus["var"]) # read as float self.assertEqual(varU.getHeight(), 256) self.assertEqual(varF.getImage().getWidth(), 256) self.assertEqual(varU.getImage().get(0, 0), varF.getImage().get(0, 0)) # # Read a char image # maskImg = afwImage.DecoratedImageU(fileName, hdus["msk"]).getImage() # read a char file self.assertEqual(maskImg.getHeight(), 256) self.assertEqual(maskImg.getWidth(), 256) self.assertEqual(maskImg.get(0, 0), 1) # # Read a U16 image #
    545 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    539 bc2593bd - tmpFile = "foo.fits"
    540 bc2593bd -
    541 bc2593bd - imgU.writeFits(tmpFile)
    546 c605dfcd + imgU.writeFits(tmpFile)
    ? ++++
    543 bc2593bd - try:
    imgU16 = afwImage.DecoratedImageF(tmpFile) # read as unsigned short
    545 bc2593bd - except:
    546 bc2593bd - os.remove(tmpFile)
    547 bc2593bd - raise
    548 bc2593bd -
    549 bc2593bd - os.remove(tmpFile)
    def testWriteFits(self): """Test writing FITS files"""
    553 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    554 f8edfe90 - tmpFile = "foo.fits"
    555 f8edfe90 -
    556 f8edfe90 - if self.fileForMetadata:
    554 c605dfcd + if self.fileForMetadata:
    ? ++++
    557 f8edfe90 - imgU = afwImage.DecoratedImageF(self.fileForMetadata)
    555 c605dfcd + imgU = afwImage.DecoratedImageF(self.fileForMetadata)
    ? ++++
    558 f8edfe90 - else:
    556 c605dfcd + else:
    ? ++++
    559 f8edfe90 - print >> sys.stderr, "Warning: afwdata is not set up; not running the FITS metadata I/O tests"
    557 c605dfcd + print >> sys.stderr, "Warning: afwdata is not set up; not running the FITS metadata I/O tests"
    ? ++++
    560 f8edfe90 - imgU = afwImage.DecoratedImageF()
    558 c605dfcd + imgU = afwImage.DecoratedImageF()
    ? ++++
    562 f8edfe90 - self.dimage1.writeFits(tmpFile, imgU.getMetadata())
    560 c605dfcd + self.dimage1.writeFits(tmpFile, imgU.getMetadata())
    ? ++++
    563 f8edfe90 - #
    561 c605dfcd + #
    ? ++++
    564 f8edfe90 - # Read it back
    562 c605dfcd + # Read it back
    ? ++++
    565 f8edfe90 - #
    563 c605dfcd + #
    ? ++++
    566 f8edfe90 - rimage = afwImage.DecoratedImageF(tmpFile)
    564 c605dfcd + rimage = afwImage.DecoratedImageF(tmpFile)
    ? ++++
    567 4940d876 - os.remove(tmpFile)
    569 a7aa0c91 - self.assertEqual(self.dimage1.getImage().get(0, 0), rimage.getImage().get(0, 0))
    566 c605dfcd + self.assertEqual(self.dimage1.getImage().get(0, 0), rimage.getImage().get(0, 0))
    ? ++++
    570 f8edfe90 - #
    567 c605dfcd + #
    ? ++++
    571 f8edfe90 - # Check that we wrote (and read) the metadata successfully
    568 c605dfcd + # Check that we wrote (and read) the metadata successfully
    ? ++++
    572 f8edfe90 - if self.fileForMetadata:
    569 c605dfcd + if self.fileForMetadata:
    ? ++++
    573 f8edfe90 - meta = self.trueMetadata
    570 c605dfcd + meta = self.trueMetadata
    ? ++++
    574 f8edfe90 - for k in meta.keys():
    571 c605dfcd + for k in meta.keys():
    ? ++++
    575 3771b5eb - self.assertEqual(rimage.getMetadata().getAsDouble(k), meta[k])
    572 c605dfcd + self.assertEqual(rimage.getMetadata().getAsDouble(k), meta[k])
    ? ++++ def testReadWriteXY0(self): """Test that we read and write (X0, Y0) correctly""" im = afwImage.ImageF(afwGeom.Extent2I(10, 20)) x0, y0 = 1, 2 im.setXY0(x0, y0)
    583 4940d876 - tmpFile = "foo.fits"
    580 c605dfcd + with utilsTests.getTempFilePath(".fits") as tmpFile:
    584 4940d876 - im.writeFits(tmpFile)
    581 c605dfcd + im.writeFits(tmpFile)
    ? ++++
    586 4940d876 - im2 = im.Factory(tmpFile)
    583 c605dfcd + im2 = im.Factory(tmpFile)
    ? ++++
    587 4940d876 - os.remove(tmpFile)
    589 4940d876 - self.assertEqual(im2.getX0(), x0)
    585 c605dfcd + self.assertEqual(im2.getX0(), x0)
    ? ++++
    590 4940d876 - self.assertEqual(im2.getY0(), y0)
    586 c605dfcd + self.assertEqual(im2.getY0(), y0)
    ? ++++ def testReadMetadata(self): if self.fileForMetadata: im = afwImage.DecoratedImageF(self.fileForMetadata) else: print >> sys.stderr, "Warning: afwdata is not set up; not running the FITS metadata I/O tests" return meta = afwImage.readMetadata(self.fileForMetadata) self.assertTrue("NAXIS1" in meta.names()) self.assertEqual(im.getWidth(), meta.get("NAXIS1")) self.assertEqual(im.getHeight(), meta.get("NAXIS2")) def testTicket1040(self): """ How to repeat from #1040""" image = afwImage.ImageD(afwGeom.Extent2I(6, 6)) image.set(2, 2, 100) bbox = afwGeom.Box2I(afwGeom.Point2I(1, 1), afwGeom.Extent2I(5, 5)) subImage = image.Factory(image, bbox) subImageF = subImage.convertFloat() if display: ds9.mtv(subImage, frame=0, title="subImage") ds9.mtv(subImageF, frame=1, title="converted subImage") self.assertEqual(subImage.get(1, 1), subImageF.get(1, 1))
    615 8b486590 + def testDM882(self):
    616 8b486590 + """Test that we can write a dotted header unit to a FITS file. See DM-882."""
    617 8b486590 + self.dimage1.getMetadata().add("A.B.C.D", 12345)
    618 8b486590 + tempdir = tempfile.mkdtemp()
    619 8b486590 + testfile = os.path.join(tempdir, "test.fits")
    620 8b486590 + try:
    621 8b486590 + self.dimage1.writeFits(testfile)
    622 8b486590 + meta = afwImage.readMetadata(testfile)
    623 8b486590 + self.assertEqual(meta.get("A.B.C.D"), 12345)
    624 8b486590 + finally:
    625 8b486590 + shutil.rmtree(tempdir)
    626 8b486590 +
    627 4c1ebf6e + def testLargeImage(self):
    628 4c1ebf6e + """Test that creating an extremely large image raises, rather than segfaulting. DM-89, -527."""
    629 4c1ebf6e + for imtype in (afwImage.ImageD, afwImage.ImageF, afwImage.ImageI, afwImage.ImageU):
    630 4c1ebf6e + self.assertRaises(lsst.pex.exceptions.LengthError, imtype, 60000, 60000)
    631 8b486590 +
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def printImg(img): print "%4s " % "", for c in range(img.getWidth()): print "%7d" % c, print for r in range(img.getHeight() - 1, -1, -1): print "%4d " % r, for c in range(img.getWidth()): print "%7.1f" % float(img.get(c, r)), print #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(ImageTestCase) suites += unittest.makeSuite(DecoratedImageTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    35b5e4e6

    commit 35b5e4e6989c4fb4200064992a6d0c3e12576081
    Author: rhl 
    Date:   Sat Aug 28 12:08:21 2010 +0000
    
        Added bounds-checking pixel assessors (#1417/#1420)
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    4abc0a0c

    commit 4abc0a0c1cb02ebb55321c22f691ceacba8c1cdd
    Author: Robert Lupton the Good 
    Date:   Sun Nov 25 21:38:46 2012 -0500
    
        Check that an image's dimensions are >= 0
    

    39c6d678

    commit 39c6d678d9b6f18b54ee394e1fc2932c9a5d2e7b
    Author: rhl 
    Date:   Tue Feb 24 20:15:26 2009 +0000
    
        Allow indexing PointD and PointI from python; #659
    

    bc2593bd

    commit bc2593bd8036f47d5be8561ae247d4b18d2dd759
    Merge: 88ad572 dfd82ef
    Author: rhl 
    Date:   Thu Jul 8 17:26:06 2010 +0000
    
        Merged from trunk and all tests pass
    

    4940d876

    commit 4940d876a0c927f4d36a74848ee3e542b9503fa6
    Author: rhl 
    Date:   Wed Mar 25 22:55:37 2009 +0000
    
        Save and restore Mask and Image (and thus MaskedImage and Exposure) (X0, Y0) when writing to FITS.  The information is written to an extra WCS, WCSA.  Switched WCSA and WCSB in ds9 display to be consistent with this
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    b0e0d3fb

    commit b0e0d3fba6ab46c94f4f600a1f245e407ec0c5d7
    Author: Dustin Lang 
    Date:   Sun Dec 4 11:11:02 2011 -0500
    
        add get0(), set0() accessors + swig + tests
    

    6bd29a86

    commit 6bd29a86ac02eb6e7f352f3f7e756cbb268c49dc
    Author: Robert Lupton the Good 
    Date:   Thu Dec 13 14:47:34 2012 -0500
    
        Handle afwdata not being setuo gracefully
    

    Commits in /Users/nate/repos_lsst/afw/

    4c1ebf6e

    commit 4c1ebf6e319abae5732c024e5f8716dd40b21e8f
    Author: John Swinbank 
    Date:   Wed Mar 25 19:39:41 2015 -0400
    
        Test case for DM-89, -527.
    

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    4bae7ca1

    commit 4bae7ca131d04a3f68e47748b0423617ffd33000
    Author: Paul Price 
    Date:   Wed Aug 6 16:40:49 2014 -0400
    
        tests: seed random number generator to make tests deterministic
    

    8b486590

    commit 8b486590bb1ce380acaf4a34af6372f5a106095e
    Author: John Swinbank 
    Date:   Wed Mar 4 13:21:11 2015 -0500
    
        Test of writting dotted header to FITS.
        
        This tests the use case documented in DM-882; the fix for that issue is
        actually in daf_base.
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    54a43c29

    commit 54a43c297a84a2586aa62781b9b01bbf8884d5bd
    Author: jbosch 
    Date:   Sat Mar 5 04:29:47 2011 +0000
    
        afw #1556 - added ndarray/numpy constructors for Image and friends, removed slower numpy conversions in image/testUtils.py, adjusted unit tests accordingly.
    

    Return to list

    src/math/SeparableKernel.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include 
                    #include 
                    #include 
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/math/Kernel.h"
                    
                    namespace pexExcept = lsst::pex::exceptions;
                    namespace afwImage = lsst::afw::image;
                    namespace afwMath = lsst::afw::math;
                    
                    afwMath::SeparableKernel::SeparableKernel()
                    :
                        Kernel(),
                        _kernelColFunctionPtr(),
                        _kernelRowFunctionPtr(),
                        _localColList(0), _localRowList(0),
                        _kernelX(0), _kernelY(0),
                        _kernelRowCache(0), _kernelColCache(0)
                    {
                        _setKernelXY();
                    }
                    
                    afwMath::SeparableKernel::SeparableKernel(
                        int width,
                        int height,
                        KernelFunction const& kernelColFunction,
                        KernelFunction const& kernelRowFunction,
                        Kernel::SpatialFunction const& spatialFunction
                    ) :
                        Kernel(width, height, kernelColFunction.getNParameters() + kernelRowFunction.getNParameters(),
                            spatialFunction),
                        _kernelColFunctionPtr(kernelColFunction.clone()),
                        _kernelRowFunctionPtr(kernelRowFunction.clone()),
                        _localColList(width), _localRowList(height),
                        _kernelX(width), _kernelY(height),
                        _kernelRowCache(0), _kernelColCache(0)
                    {
                        _setKernelXY();
                    }
                    
                    afwMath::SeparableKernel::SeparableKernel(
                        int width,
                        int height,
                        KernelFunction const& kernelColFunction,
                        KernelFunction const& kernelRowFunction,
                        std::vector const& spatialFunctionList
                    ) :
                        Kernel(width, height, spatialFunctionList),
                        _kernelColFunctionPtr(kernelColFunction.clone()),
                        _kernelRowFunctionPtr(kernelRowFunction.clone()),
                        _localColList(width), _localRowList(height),
                        _kernelX(width), _kernelY(height),
                        _kernelRowCache(0), _kernelColCache(0)    
                    {
                        if (kernelColFunction.getNParameters() + kernelRowFunction.getNParameters()
                            != spatialFunctionList.size()) {
                            std::ostringstream os;
                            os << "kernelColFunction.getNParameters() + kernelRowFunction.getNParameters() = "
                                << kernelColFunction.getNParameters() << " + " << kernelRowFunction.getNParameters()
                                << " != " << spatialFunctionList.size() << " = " << "spatialFunctionList.size()";
    
    85 d7b24982 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    85 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } _setKernelXY(); } PTR(afwMath::Kernel) afwMath::SeparableKernel::clone() const { PTR(afwMath::Kernel) retPtr; if (this->isSpatiallyVarying()) { retPtr.reset(new afwMath::SeparableKernel(this->getWidth(), this->getHeight(), *(this->_kernelColFunctionPtr), *(this->_kernelRowFunctionPtr), this->_spatialFunctionList)); } else { retPtr.reset(new afwMath::SeparableKernel(this->getWidth(), this->getHeight(), *(this->_kernelColFunctionPtr), *(this->_kernelRowFunctionPtr))); } retPtr->setCtr(this->getCtr()); retPtr->computeCache(this->getCacheSize()); return retPtr; } double afwMath::SeparableKernel::computeVectors( std::vector &colList, std::vector &rowList, bool doNormalize, double x, double y ) const { if (static_cast(colList.size()) != this->getWidth() || static_cast(rowList.size()) != this->getHeight()) { std::ostringstream os; os << "colList.size(), rowList.size() = (" << colList.size() << ", " << rowList.size() << ") != ("<< this->getWidth() << ", " << this->getHeight() << ") = " << "kernel dimensions";
    119 d7b24982 - throw LSST_EXCEPT(pexExcept::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    119 21597d88 + throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
    ? ^^ ^ } if (this->isSpatiallyVarying()) { this->setKernelParametersFromSpatialModel(x, y); } return basicComputeVectors(colList, rowList, doNormalize); } afwMath::SeparableKernel::KernelFunctionPtr afwMath::SeparableKernel::getKernelColFunction( ) const { return _kernelColFunctionPtr->clone(); } afwMath::SeparableKernel::KernelFunctionPtr afwMath::SeparableKernel::getKernelRowFunction( ) const { return _kernelRowFunctionPtr->clone(); } std::string afwMath::SeparableKernel::toString(std::string const& prefix) const { std::ostringstream os; os << prefix << "SeparableKernel:" << std::endl; os << prefix << "..x (width) function: " << (_kernelColFunctionPtr ? _kernelColFunctionPtr->toString() : "None") << std::endl; os << prefix << "..y (rows) function: " << (_kernelRowFunctionPtr ? _kernelRowFunctionPtr->toString() : "None") << std::endl; os << Kernel::toString(prefix + "\t"); return os.str(); } std::vector afwMath::SeparableKernel::getKernelParameters() const { std::vector allParams = _kernelColFunctionPtr->getParameters(); std::vector yParams = _kernelRowFunctionPtr->getParameters(); std::copy(yParams.begin(), yParams.end(), std::back_inserter(allParams)); return allParams; } // // Protected Member Functions // double afwMath::SeparableKernel::doComputeImage( afwImage::Image &image, bool doNormalize ) const { double imSum = basicComputeVectors(_localColList, _localRowList, doNormalize); for (int y = 0; y != image.getHeight(); ++y) { afwImage::Image::x_iterator imPtr = image.row_begin(y); for (std::vector::iterator colIter = _localColList.begin(); colIter != _localColList.end(); ++colIter, ++imPtr) { *imPtr = (*colIter)*_localRowList[y]; } } return imSum; } void afwMath::SeparableKernel::setKernelParameter(unsigned int ind, double value) const { unsigned int const nColParams = _kernelColFunctionPtr->getNParameters(); if (ind < nColParams) { _kernelColFunctionPtr->setParameter(ind, value); } else { _kernelRowFunctionPtr->setParameter(ind - nColParams, value); } } // // Private Member Functions // double afwMath::SeparableKernel::basicComputeVectors( std::vector &colList, std::vector &rowList, bool doNormalize ) const { double colSum = 0.0; if (_kernelColCache.empty()) { for (unsigned int i = 0; i != colList.size(); ++i) { double colFuncValue = (*_kernelColFunctionPtr)(_kernelX[i]); colList[i] = colFuncValue; colSum += colFuncValue; } } else { int const cacheSize = _kernelColCache.size(); int const indx = this->getKernelParameter(0)*cacheSize; std::vector &cachedValues = _kernelColCache.at(indx); for (unsigned int i = 0; i != colList.size(); ++i) { double colFuncValue = cachedValues[i]; colList[i] = colFuncValue; colSum += colFuncValue; } } double rowSum = 0.0; if (_kernelRowCache.empty()) { for (unsigned int i = 0; i != rowList.size(); ++i) { double rowFuncValue = (*_kernelRowFunctionPtr)(_kernelY[i]); rowList[i] = rowFuncValue; rowSum += rowFuncValue; } } else { int const cacheSize = _kernelRowCache.size(); int const indx = this->getKernelParameter(1)*cacheSize; std::vector &cachedValues = _kernelRowCache.at(indx); for (unsigned int i = 0; i != rowList.size(); ++i) { double rowFuncValue = cachedValues[i]; rowList[i] = rowFuncValue; rowSum += rowFuncValue; #if 0 if (indx == cacheSize/2) { if (::fabs(rowFuncValue - (*_kernelRowFunctionPtr)(_kernelX[i])) > 1e-2) { std::cout << indx << " " << i << " " << rowFuncValue << " " << (*_kernelRowFunctionPtr)(_kernelX[i]) << std::endl; } } #endif } } double imSum = colSum * rowSum; if (doNormalize) { if ((colSum == 0) || (rowSum == 0)) {
    249 b79a02a2 - throw LSST_EXCEPT(pexExcept::OverflowErrorException, "Cannot normalize; kernel sum is 0");
    ? ---------
    249 21597d88 + throw LSST_EXCEPT(pexExcept::OverflowError, "Cannot normalize; kernel sum is 0");
    } for (std::vector::iterator colIter = colList.begin(); colIter != colList.end(); ++colIter) { *colIter /= colSum; } for (std::vector::iterator rowIter = rowList.begin(); rowIter != rowList.end(); ++rowIter) { *rowIter /= rowSum; } imSum = 1.0; } return imSum; } /************************************************************************************************************/ namespace { /** * Compute a cache of pre-computed Kernels */ void _computeCache(int const cacheSize, std::vector const& x, afwMath::SeparableKernel::KernelFunctionPtr & func, std::vector > *kernelCache) { if (cacheSize <= 0) { kernelCache->erase(kernelCache->begin(), kernelCache->end()); return; } if (kernelCache[0].size() != x.size()) { // invalid kernelCache->erase(kernelCache->begin(), kernelCache->end()); } int const old_cacheSize = kernelCache->size(); if (cacheSize == old_cacheSize) { return; // nothing to do } if (cacheSize < old_cacheSize) { kernelCache->erase(kernelCache->begin() + cacheSize, kernelCache->end()); } else { kernelCache->resize(cacheSize); for (int i = old_cacheSize; i != cacheSize; ++i) { (*kernelCache)[i].resize(x.size()); } } // // Actually fill the cache // for (int i = 0; i != cacheSize; ++i) { func->setParameter(0, (i + 0.5)/static_cast(cacheSize)); for (unsigned int j = 0; j != x.size(); ++j) { (*kernelCache)[i][j] = (*func)(x[j]); } } } } void afwMath::SeparableKernel::computeCache( int const cacheSize ) { afwMath::SeparableKernel::KernelFunctionPtr func; func = getKernelColFunction(); _computeCache(cacheSize, _kernelY, func, &_kernelColCache); func = getKernelRowFunction(); _computeCache(cacheSize, _kernelX, func, &_kernelRowCache); } int afwMath::SeparableKernel::getCacheSize() const { return _kernelColCache.size(); };

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    b79a02a2

    commit b79a02a2c6c1b70fadfb74623e481172a3376579
    Author: rowen 
    Date:   Mon Nov 23 21:16:07 2009 +0000
    
        Implemented ticket #992:
        - Kernel.computeImage now raises lsst::pex::except::InvalidParameterException
          if doNormalize true and kernel sum 0.
        - SeparableKernel.computeVectors and basicComputeVectors do the same.
        - Added unit tests for the above.
        - Fixed typos in tests/Statistics.py so all tests pass again.
    

    d7b24982

    commit d7b24982db8562dc77c4bcc33c84107c65fd686d
    Author: rowen 
    Date:   Thu Oct 29 00:15:47 2009 +0000
    
        Fixed ticket #1000 by adding a missing test to a LinearCombinationKernel constructor.
        Updated tests/Kernel.cc as suggested by Serge so it would not trigger the problem.
        Updated many exceptions in kernel constructors to print more details.
        Added unit tests for the exceptions in kernel methods.
        
        Note: the current code has a swig warning about a shadowed constructor in LinearCombinationKernel.
        This should be resolved before committing the changes to the trunk. See my email to lsst-data.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/test1079.py

    Diff:

    1 0bf99bc8 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # ##test1079 ##\brief Test that the wcs of sub-images are written and read from disk correctly ##$Id$ ##\author Fergal Mullally
    31 ccaf3c48 - import math, os
    32 c605dfcd + import os.path
    import unittest
    34 0bf99bc8 - import eups
    35 7cbb2bb9 + import lsst.utils
    import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.utils.tests as utilsTests
    38 0bf99bc8 - import lsst.pex.exceptions.exceptionsLib as exceptions
    39 6fc1c3d1 + import lsst.pex.exceptions
    import lsst.afw.display.ds9 as ds9 try: type(verbose) except NameError: verbose = 0 class SavingSubImagesTest(unittest.TestCase): """ Tests for changes made for ticket #1079. In the LSST wcs transformations are done in terms of pixel position, which is measured from the lower left hand corner of the parent image from which this sub-image is drawn. However, when saving a sub-image to disk, the fits standards has no concept of parent- and sub- images, and specifies that the wcs is measured relative to the pixel index (i.e the lower left hand corner of the sub-image). This test makes sure we're saving and reading wcs headers from sub-images correctly. """ def setUp(self):
    57 4b0fcca6 - path = eups.productDir("afw")
    58 7cbb2bb9 + path = lsst.utils.getPackageDir("afw")
    self.parentFile = os.path.join(path, "tests", "data", "parent.fits") self.parent = afwImage.ExposureF(self.parentFile) self.llcParent = self.parent.getMaskedImage().getXY0() self.oParent = self.parent.getWcs().getPixelOrigin() #A list of pixel positions to test self.testPositions = [] self.testPositions.append(afwGeom.Point2D(128, 128)) self.testPositions.append(afwGeom.Point2D(0,0)) self.testPositions.append(afwGeom.Point2D(20,30)) self.testPositions.append(afwGeom.Point2D(60,50)) self.testPositions.append(afwGeom.Point2D(80, 80)) self.testPositions.append(afwGeom.Point2D(255,255)) self.parent.getMaskedImage().set(0) for p in self.testPositions: self.parent.getMaskedImage().set(int(p[0]), int(p[1]), (10 + p[0],)) def tearDown(self): del self.parent del self.oParent del self.testPositions def testInvarianceOfCrpix1(self): """Test that crpix is the same for parent and sub-image. Also tests that llc of sub-image saved correctly""" llc = afwGeom.Point2I(20, 30) bbox = afwGeom.Box2I(llc, afwGeom.Extent2I(60, 50)) subImg = afwImage.ExposureF(self.parent, bbox, afwImage.LOCAL) subImgLlc = subImg.getMaskedImage().getXY0() oSubImage = subImg.getWcs().getPixelOrigin() #Useful for debugging if False: print self.parent.getMaskedImage().getXY0() print subImg.getMaskedImage().getXY0() print self.parent.getWcs().getFitsMetadata().toString() print subImg.getWcs().getFitsMetadata().toString() print self.oParent, oSubImage for i in range(2): self.assertEqual(llc[i], subImgLlc[i], "Corner of sub-image not correct") self.assertAlmostEqual(self.oParent[i], oSubImage[i], 6, "Crpix of sub-image not correct") def testInvarianceOfCrpix2(self): """For sub-images loaded from disk, test that crpix is the same for parent and sub-image. Also tests that llc of sub-image saved correctly""" #Load sub-image directly off of disk llc = afwGeom.Point2I(20, 30) bbox = afwGeom.Box2I(llc, afwGeom.Extent2I(60, 50)) subImg = afwImage.ExposureF(self.parentFile, bbox, afwImage.LOCAL) oSubImage = subImg.getWcs().getPixelOrigin() subImgLlc = subImg.getMaskedImage().getXY0() #Useful for debugging if False: print self.parent.getMaskedImage().getXY0() print subImg.getMaskedImage().getXY0() print self.parent.getWcs().getFitsMetadata().toString() print subImg.getWcs().getFitsMetadata().toString() print self.oParent, oSubImage for i in range(2): self.assertEqual(llc[i], subImgLlc[i], "Corner of sub-image not correct") self.assertAlmostEqual(self.oParent[i], oSubImage[i], 6, "Crpix of sub-image not correct") def testInvarianceOfPixelToSky(self): for deep in (True, False): llc = afwGeom.Point2I(20, 30) bbox = afwGeom.Box2I(llc, afwGeom.Extent2I(60, 50)) subImg = afwImage.ExposureF(self.parent, bbox, afwImage.LOCAL, deep) xy0 = subImg.getMaskedImage().getXY0() if False: ds9.mtv(self.parent, frame=0) ds9.mtv(subImg, frame=1) for p in self.testPositions: subP = p - afwGeom.Extent2D(llc[0], llc[1]) # pixel in subImg if \ subP[0] < 0 or subP[0] >= bbox.getWidth() or \ subP[1] < 0 or subP[1] >= bbox.getHeight(): continue adParent = self.parent.getWcs().pixelToSky(p) adSub = subImg.getWcs().pixelToSky(subP + afwGeom.Extent2D(xy0[0], xy0[1])) # # Check that we're talking about the same pixel # self.assertEqual(self.parent.getMaskedImage().get(int(p[0]), int(p[1])), subImg.getMaskedImage().get(int(subP[0]), int(subP[1]))) self.assertEqual(adParent[0], adSub[0], "RAs are equal; deep = %s" % deep) self.assertEqual(adParent[1], adSub[1], "DECs are equal; deep = %s" % deep) def testSubSubImage(self): """Check that a sub-image of a sub-image is equivalent to a sub image, i.e that the parent is an invarient""" llc1 = afwGeom.Point2I(20, 30) bbox = afwGeom.Box2I(llc1, afwGeom.Extent2I(60, 50)) subImg = afwImage.ExposureF(self.parentFile, bbox, afwImage.LOCAL) llc2 = afwGeom.Point2I(22, 23) #This subsub image should fail. Although it's big enough to fit in the parent image #it's too small for the sub-image bbox = afwGeom.Box2I(llc2, afwGeom.Extent2I(100, 110))
    176 20c2c467 - self.assertRaises(exceptions.LsstCppException, afwImage.ExposureF, subImg, bbox, afwImage.LOCAL)
    ? -------
    177 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.Exception, afwImage.ExposureF, subImg, bbox, afwImage.LOCAL)
    ? +++++++++ bbox = afwGeom.Box2I(llc2, afwGeom.Extent2I(10, 11)) subSubImg = afwImage.ExposureF(subImg, bbox, afwImage.LOCAL) sub0 = subImg.getMaskedImage().getXY0() subsub0= subSubImg.getMaskedImage().getXY0() if False: print sub0 print subsub0 for i in range(2): self.assertEqual(llc1[i], sub0[i], "XY0 don't match (1)") self.assertEqual(llc1[i] + llc2[i], subsub0[i], "XY0 don't match (2)") subCrpix = subImg.getWcs().getPixelOrigin() subsubCrpix = subSubImg.getWcs().getPixelOrigin() for i in range(2): self.assertAlmostEqual(subCrpix[i], subsubCrpix[i], 6, "crpix don't match") def testRoundTrip(self): """Test that saving and retrieving an image doesn't alter the metadata""" llc = afwGeom.Point2I(20, 30) bbox = afwGeom.Box2I(llc, afwGeom.Extent2I(60, 50)) for deep in (False, True): subImg = afwImage.ExposureF(self.parent, bbox, afwImage.LOCAL, deep)
    208 ccaf3c48 - outFile = "tmp2.fits"
    209 c605dfcd + with utilsTests.getTempFilePath("_%s.fits" % (deep,)) as outFile:
    209 ccaf3c48 - subImg.writeFits(outFile)
    210 c605dfcd + subImg.writeFits(outFile)
    ? ++++
    210 20c2c467 - newImg = afwImage.ExposureF(outFile)
    211 c605dfcd + newImg = afwImage.ExposureF(outFile)
    ? ++++
    211 ccaf3c48 - os.remove(outFile)
    213 ccaf3c48 - subXY0 = subImg.getMaskedImage().getXY0()
    213 c605dfcd + subXY0 = subImg.getMaskedImage().getXY0()
    ? ++++
    214 ccaf3c48 - newXY0 = newImg.getMaskedImage().getXY0()
    214 c605dfcd + newXY0 = newImg.getMaskedImage().getXY0()
    ? ++++
    216 ccaf3c48 - parentCrpix = self.parent.getWcs().getPixelOrigin()
    216 c605dfcd + parentCrpix = self.parent.getWcs().getPixelOrigin()
    ? ++++
    217 ccaf3c48 - subCrpix = subImg.getWcs().getPixelOrigin()
    217 c605dfcd + subCrpix = subImg.getWcs().getPixelOrigin()
    ? ++++
    218 ccaf3c48 - newCrpix = newImg.getWcs().getPixelOrigin()
    218 c605dfcd + newCrpix = newImg.getWcs().getPixelOrigin()
    ? ++++
    220 ccaf3c48 - if False:
    220 c605dfcd + if False:
    ? ++++
    221 ccaf3c48 - print self.parent.getWcs().getFitsMetadata().toString()
    221 c605dfcd + print self.parent.getWcs().getFitsMetadata().toString()
    ? ++++
    222 ccaf3c48 - print subImg.getWcs().getFitsMetadata().toString()
    222 c605dfcd + print subImg.getWcs().getFitsMetadata().toString()
    ? ++++
    223 ccaf3c48 - print newImg.getWcs().getFitsMetadata().toString()
    223 c605dfcd + print newImg.getWcs().getFitsMetadata().toString()
    ? ++++
    225 ccaf3c48 - for i in range(2):
    225 c605dfcd + for i in range(2):
    ? ++++
    226 ccaf3c48 - self.assertEqual(subXY0[i], newXY0[i], "Origin has changed; deep = %s" % deep)
    226 c605dfcd + self.assertEqual(subXY0[i], newXY0[i], "Origin has changed; deep = %s" % deep)
    ? ++++
    227 ccaf3c48 - self.assertAlmostEqual(subCrpix[i], newCrpix[i], 6,"crpix has changed; deep = %s" % deep)
    227 c605dfcd + self.assertAlmostEqual(subCrpix[i], newCrpix[i], 6,"crpix has changed; deep = %s" % deep)
    ? ++++ def testFitsHeader(self): """Test that XY0 and crpix are written to the header as expected""" #getPixelOrigin() returns origin in lsst coordinates, so need to add 1 to #compare to values stored in fits headers parentCrpix = self.parent.getWcs().getPixelOrigin() #Make a sub-image x0, y0 = 20, 30 llc = afwGeom.Point2I(x0, y0) bbox = afwGeom.Box2I(llc, afwGeom.Extent2I(60, 50)) deep = False subImg = afwImage.ExposureF(self.parent, bbox, afwImage.LOCAL, deep)
    242 0bf99bc8 -
    243 ccaf3c48 - outFile = "tmp.fits"
    242 0bf99bc8 +
    243 c605dfcd + with utilsTests.getTempFilePath(".fits") as outFile:
    244 ccaf3c48 - subImg.writeFits(outFile)
    244 c605dfcd + subImg.writeFits(outFile)
    ? ++++
    245 20c2c467 - hdr = afwImage.readMetadata(outFile)
    245 c605dfcd + hdr = afwImage.readMetadata(outFile)
    ? ++++
    246 ccaf3c48 - os.remove(outFile)
    247 0bf99bc8 -
    246 c605dfcd +
    ? ++++
    248 0bf99bc8 - self.assertTrue( hdr.exists("LTV1"), "LTV1 not saved to fits header")
    247 c605dfcd + self.assertTrue( hdr.exists("LTV1"), "LTV1 not saved to fits header")
    ? ++++
    249 0bf99bc8 - self.assertTrue( hdr.exists("LTV2"), "LTV2 not saved to fits header")
    248 c605dfcd + self.assertTrue( hdr.exists("LTV2"), "LTV2 not saved to fits header")
    ? ++++
    250 0bf99bc8 - self.assertEqual(hdr.get("LTV1"), -1*x0, "LTV1 has wrong value")
    249 c605dfcd + self.assertEqual(hdr.get("LTV1"), -1*x0, "LTV1 has wrong value")
    ? ++++
    251 0bf99bc8 - self.assertEqual(hdr.get("LTV2"), -1*y0, "LTV1 has wrong value")
    250 c605dfcd + self.assertEqual(hdr.get("LTV2"), -1*y0, "LTV1 has wrong value")
    ? ++++
    254 0bf99bc8 - self.assertTrue( hdr.exists("CRPIX1"), "CRPIX1 not saved to fits header")
    253 c605dfcd + self.assertTrue( hdr.exists("CRPIX1"), "CRPIX1 not saved to fits header")
    ? ++++
    255 0bf99bc8 - self.assertTrue( hdr.exists("CRPIX2"), "CRPIX2 not saved to fits header")
    254 c605dfcd + self.assertTrue( hdr.exists("CRPIX2"), "CRPIX2 not saved to fits header")
    ? ++++
    256 0bf99bc8 -
    255 c605dfcd +
    ? ++++
    257 0bf99bc8 - fitsCrpix = [hdr.get("CRPIX1"), hdr.get("CRPIX2")]
    256 c605dfcd + fitsCrpix = [hdr.get("CRPIX1"), hdr.get("CRPIX2")]
    ? ++++
    258 dc5d71ba - self.assertAlmostEqual(fitsCrpix[0] - hdr.get("LTV1"), parentCrpix[0]+1, 6, "CRPIX1 saved wrong")
    257 c605dfcd + self.assertAlmostEqual(fitsCrpix[0] - hdr.get("LTV1"), parentCrpix[0]+1, 6, "CRPIX1 saved wrong")
    ? ++++
    259 dc5d71ba - self.assertAlmostEqual(fitsCrpix[1] - hdr.get("LTV2"), parentCrpix[1]+1, 6, "CRPIX2 saved wrong")
    258 c605dfcd + self.assertAlmostEqual(fitsCrpix[1] - hdr.get("LTV2"), parentCrpix[1]+1, 6, "CRPIX2 saved wrong")
    ? ++++ ##### def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(SavingSubImagesTest) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ccaf3c48

    commit ccaf3c481ca901a3145c8aad2d694c391a1980eb
    Author: rhl 
    Date:   Wed May 26 21:24:40 2010 +0000
    
        Added some tests that show that #1079 isn't fixed until #1292 is resolved
    

    dc5d71ba

    commit dc5d71baa50ea8d79055142a973a56a0bd64b016
    Author: fergal 
    Date:   Wed Jun 16 20:51:06 2010 +0000
    
        Fix bug in Wcs.cc, had fitsToLsst and lsstToFits reversed.
    

    4b0fcca6

    commit 4b0fcca656d7c8f0f80f448cd81df5b3a758afad
    Author: fergal 
    Date:   Fri Mar 12 18:07:34 2010 +0000
    
        Fixed bug where test can't find image file when run from scons
    

    0bf99bc8

    commit 0bf99bc8fabda47c77561a3453e7c1628868c9f9
    Author: fergal 
    Date:   Tue Mar 9 23:30:49 2010 +0000
    
        A test that the wcs of a sub-image is written and read from disk correctly.
    

    20c2c467

    commit 20c2c46776ad69164993f9837f347800a80f245b
    Author: jbosch 
    Date:   Fri Mar 4 01:19:01 2011 +0000
    
        afw #1556 - fixed all python unit tests with trivial syntax-related failures, plus a few others
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    0bf99bc8

    commit 0bf99bc8fabda47c77561a3453e7c1628868c9f9
    Author: fergal 
    Date:   Tue Mar 9 23:30:49 2010 +0000
    
        A test that the wcs of a sub-image is written and read from disk correctly.
    

    c605dfcd

    commit c605dfcd6a7d3f654b0f88cc49b3bc9c62632533
    Author: Russell Owen 
    Date:   Wed Apr 8 15:30:37 2015 -0700
    
        Use getTempFilePath to avoid temp file name collisions
        
        Using the same file name for temp files for different tests
        was causing occasional test failures due to collisions (one test
        would read another test's temporary file). Using the new context manager
        lsst.utils.tests.getTempFilePath avoids the problem, avoids the danger
        of accidentally picking like names in the future (e.g. from careless copy/paste),
        and handles file clean up on success.
        
        Use lsst.utils.tests.getTempFilePath where appropriate
        
        Remove old uses of os.remove, os.unlink and manually creating temporary file names
        and switch to using "with lsst.utils.tests.getTempFilePath(...) as ...:" instead,
        since this automatically creates a name that is unique to a particular test method
        (and can easily create names that are unique within a test) and deletes the file at the end.
        
        Remove the only use of temporaryFile that I could find
    

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    Return to list

    src/geom/ellipses/BaseCore.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include "lsst/afw/geom/ellipses/BaseCore.h"
                    #include "lsst/afw/geom/ellipses/Quadrupole.h"
                    #include "lsst/afw/geom/ellipses/Axes.h"
                    #include "lsst/afw/geom/Angle.h"
                    #include 
                    #include 
                    
                    namespace afwGeom = lsst::afw::geom;
                    
                    namespace lsst { namespace afw { namespace geom { namespace ellipses {
                    
                    namespace {
                    
                    typedef std::map< std::string, boost::shared_ptr > RegistryMap;
                    
                    RegistryMap & getRegistry() {
                        static RegistryMap instance;
                        return instance;
                    }
                    
                    BaseCore::Ptr getRegistryCopy(std::string const & name) {
                        RegistryMap::iterator i = getRegistry().find(name);
                        if (i == getRegistry().end()) {
                            throw LSST_EXCEPT(
    
    48 ce01a540 - lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    48 21597d88 + lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ (boost::format("Ellipse core with name '%s' not found in registry.") % name).str() ); } return i->second->clone(); } } // anonymous BaseCore::Ptr BaseCore::make(std::string const & name) { BaseCore::Ptr result = getRegistryCopy(name); *result = Quadrupole(); return result; } BaseCore::Ptr BaseCore::make(std::string const & name, ParameterVector const & parameters) { BaseCore::Ptr result = getRegistryCopy(name); result->setParameterVector(parameters); return result; } BaseCore::Ptr BaseCore::make(std::string const & name, double v1, double v2, double v3) { BaseCore::Ptr result = getRegistryCopy(name); result->setParameterVector(ParameterVector(v1, v2, v3)); return result; } BaseCore::Ptr BaseCore::make(std::string const & name, BaseCore const & other) { BaseCore::Ptr result = getRegistryCopy(name); *result = other; return result; } BaseCore::Ptr BaseCore::make(std::string const & name, Transformer const & other) { BaseCore::Ptr result = getRegistryCopy(name); other.apply(*result); return result; } BaseCore::Ptr BaseCore::make(std::string const & name, Convolution const & other) { BaseCore::Ptr result = getRegistryCopy(name); other.apply(*result); return result; } void BaseCore::registerSubclass(BaseCore::Ptr const & example) { getRegistry()[example->getName()] = example; } void BaseCore::grow(double buffer) { double a, b, theta; _assignToAxes(a, b, theta); a += buffer; b += buffer; _assignFromAxes(a, b, theta); } void BaseCore::scale(double factor) { double a, b, theta; _assignToAxes(a, b, theta); a *= factor; b *= factor; _assignFromAxes(a, b, theta); } double BaseCore::getArea() const { double a, b, theta; _assignToAxes(a, b, theta); return a * b * afwGeom::PI; } double BaseCore::getDeterminantRadius() const { double a, b, theta; _assignToAxes(a, b, theta); return std::sqrt(a * b); } double BaseCore::getTraceRadius() const { double ixx, iyy, ixy; _assignToQuadrupole(ixx, iyy, ixy); return std::sqrt(0.5 * (ixx + iyy)); } Extent2D BaseCore::computeDimensions() const { double a, b, theta; _assignToAxes(a, b, theta); double c = std::cos(theta); double s = std::sin(theta); c *= c; s *= s; b *= b; a *= a; Extent2D dimensions(std::sqrt(b * s + a * c),std::sqrt(a * s + b * c)); dimensions *= 2; return dimensions; } BaseCore::ParameterVector const BaseCore::getParameterVector() const { ParameterVector r; writeParameters(r.data()); return r; } void BaseCore::setParameterVector(ParameterVector const & p) { readParameters(p.data()); } bool BaseCore::operator==(BaseCore const & other) const { return getParameterVector() == other.getParameterVector() && getName() == other.getName(); } BaseCore & BaseCore::operator=(BaseCore const & other) { if (&other != this) { // We use Axes instead of Quadrupole here because it allows us to copy Axes without // implicitly normalizing them. double a, b, theta; other._assignToAxes(a, b, theta); _assignFromAxes(a, b, theta); } return *this; } BaseCore::Jacobian BaseCore::dAssign(BaseCore const & other) { if (getName() == other.getName()) { this->operator=(other); return Jacobian::Identity(); } // We use Quadrupole instead of Axes here because the ambiguity of the position angle // in the circular case causes some of the Jacobians to/from Axes to be undefined for // exact circles. Quadrupoles don't have that problem, and the Axes-to-Axes case is // handled by the above if block. double ixx, iyy, ixy; Jacobian rhs = other._dAssignToQuadrupole(ixx, iyy, ixy); Jacobian lhs = _dAssignFromQuadrupole(ixx, iyy, ixy); return lhs * rhs; } void BaseCore::_assignQuadrupoleToAxes( double ixx, double iyy, double ixy, double & a, double & b, double & theta ) { double xx_p_yy = ixx + iyy; double xx_m_yy = ixx - iyy; double t = std::sqrt(xx_m_yy*xx_m_yy + 4*ixy*ixy); a = std::sqrt(0.5*(xx_p_yy + t)); b = std::sqrt(0.5*(xx_p_yy - t)); theta = 0.5*std::atan2(2.0*ixy, xx_m_yy); } BaseCore::Jacobian BaseCore::_dAssignQuadrupoleToAxes( double ixx, double iyy, double ixy, double & a, double & b, double & theta ) { double xx_p_yy = ixx + iyy; double xx_m_yy = ixx - iyy; double t2 = xx_m_yy*xx_m_yy + 4.0*ixy*ixy; Eigen::Vector3d dt2(2.0*xx_m_yy, -2.0*xx_m_yy, 8.0*ixy); double t = std::sqrt(t2); a = std::sqrt(0.5*(xx_p_yy + t)); b = std::sqrt(0.5*(xx_p_yy - t)); theta = 0.5*std::atan2(2.0*ixy, xx_m_yy); Jacobian m = Jacobian::Zero(); m(0, 0) = 0.25 * (1.0 + 0.5 * dt2[0] / t) / a; m(0, 1) = 0.25 * (1.0 + 0.5 * dt2[1] / t) / a; m(0, 2) = 0.25 * (0.5 * dt2[2] / t) / a; m(1, 0) = 0.25 * (1.0 - 0.5 * dt2[0] / t) / b; m(1, 1) = 0.25 * (1.0 - 0.5 * dt2[1] / t) / b; m(1, 2) = 0.25 * (-0.5 * dt2[2] / t) / b; m.row(2).setConstant(1.0 / (t * t)); m(2, 0) *= -ixy; m(2, 1) *= ixy; m(2, 2) *= xx_m_yy; return m; } void BaseCore::_assignAxesToQuadrupole( double a, double b, double theta, double & ixx, double & iyy, double & ixy ) { a *= a; b *= b; double c = std::cos(theta); double s = std::sin(theta); ixy = (a - b)*c*s; c *= c; s *= s; ixx = c*a + s*b; iyy = s*a + c*b; } BaseCore::Jacobian BaseCore::_dAssignAxesToQuadrupole( double a, double b, double theta, double & ixx, double & iyy, double & ixy ) { Jacobian m; m.col(0).setConstant(2*a); m.col(1).setConstant(2*b); a *= a; b *= b; m.col(2).setConstant(a-b); double c = std::cos(theta); double s = std::sin(theta); double cs = c*s; ixy = (a - b)*c*s; c *= c; s *= s; ixx = c*a + s*b; iyy = s*a + c*b; m(0,0) *= c; m(0,1) *= s; m(0,2) *= -2.0*cs; m(1,0) *= s; m(1,1) *= c; m(1,2) *= 2.0*cs; m(2,0) *= cs; m(2,1) *= -cs; m(2,2) *= (c - s); return m; } }}}} // namespace lsst::afw::geom::ellipses

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ce01a540

    commit ce01a5406f327071e1701d534e563f0e75b870c4
    Author: jbosch 
    Date:   Wed Feb 2 01:27:08 2011 +0000
    
        afw #1556 - ellipses updated (#1551), but swig wrappers for ellipses now broken
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    src/image/ExposureInfo.cc

    Diff:

                    // -*- LSST-C++ -*- // fixed format comment for emacs
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/pex/logging/Log.h"
                    #include "lsst/afw/image/ExposureInfo.h"
                    #include "lsst/afw/image/Calib.h"
                    #include "lsst/afw/image/Wcs.h"
    
    29 fd15d1dd - #include "lsst/afw/geom/polygon/Polygon.h"
    30 5a944adf - #include "lsst/afw/image/ApCorrMap.h"
    #include "lsst/afw/detection/Psf.h" #include "lsst/afw/cameraGeom/Detector.h" #include "lsst/afw/fits.h" namespace lsst { namespace afw { namespace image { namespace { // Return an int value from a PropertySet if it exists and remove it, or return 0. int popInt(daf::base::PropertySet & metadata, std::string const & name) { int r = 0; if (metadata.exists(name)) { r = metadata.get(name); metadata.remove(name); } return r; } } // anonymous // Clone various components; defined here so that we don't have to expose their insides in Exposure.h PTR(Calib) ExposureInfo::_cloneCalib(CONST_PTR(Calib) calib) {
    55 5a944adf - if (calib) {
    ? --
    53 0a4b53bf + if (calib)
    return PTR(Calib)(new Calib(*calib));
    57 5a944adf - }
    return PTR(Calib)(); } PTR(Wcs) ExposureInfo::_cloneWcs(CONST_PTR(Wcs) wcs) {
    62 5a944adf - if (wcs) {
    ? --
    59 0a4b53bf + if (wcs)
    return wcs->clone();
    64 5a944adf - }
    return PTR(Wcs)();
    66 0a4b53bf - }
    67 0a4b53bf -
    68 5a944adf - PTR(ApCorrMap) ExposureInfo::_cloneApCorrMap(PTR(ApCorrMap const) apCorrMap) {
    69 5a944adf - if (apCorrMap) {
    70 5a944adf - return boost::make_shared(*apCorrMap);
    71 5a944adf - }
    72 5a944adf - return PTR(ApCorrMap)();
    } ExposureInfo::ExposureInfo( CONST_PTR(Wcs) const & wcs, CONST_PTR(detection::Psf) const & psf, CONST_PTR(Calib) const & calib, CONST_PTR(cameraGeom::Detector) const & detector,
    80 fd15d1dd - CONST_PTR(geom::polygon::Polygon) const & polygon,
    Filter const & filter, PTR(daf::base::PropertySet) const & metadata,
    83 5a944adf - PTR(CoaddInputs) const & coaddInputs,
    ? -
    71 910062c9 + PTR(CoaddInputs) const & coaddInputs
    84 5a944adf - PTR(ApCorrMap) const & apCorrMap
    ) : _wcs(_cloneWcs(wcs)), _psf(boost::const_pointer_cast(psf)), _calib(calib ? _cloneCalib(calib) : PTR(Calib)(new Calib())), _detector(detector),
    89 fd15d1dd - _validPolygon(polygon),
    _filter(filter), _metadata(metadata ? metadata : PTR(daf::base::PropertySet)(new daf::base::PropertyList())),
    92 5a944adf - _coaddInputs(coaddInputs),
    ? -
    78 00c19e79 + _coaddInputs(coaddInputs)
    93 5a944adf - _apCorrMap(_cloneApCorrMap(apCorrMap))
    {} ExposureInfo::ExposureInfo(ExposureInfo const & other) : _wcs(_cloneWcs(other._wcs)), _psf(other._psf), _calib(_cloneCalib(other._calib)), _detector(other._detector),
    101 fd15d1dd - _validPolygon(other._validPolygon),
    _filter(other._filter), _metadata(other._metadata),
    104 5a944adf - _coaddInputs(other._coaddInputs),
    ? -
    88 00c19e79 + _coaddInputs(other._coaddInputs)
    105 5a944adf - _apCorrMap(_cloneApCorrMap(other._apCorrMap))
    {} ExposureInfo::ExposureInfo(ExposureInfo const & other, bool copyMetadata) : _wcs(_cloneWcs(other._wcs)), _psf(other._psf), _calib(_cloneCalib(other._calib)), _detector(other._detector),
    113 fd15d1dd - _validPolygon(other._validPolygon),
    _filter(other._filter), _metadata(other._metadata),
    116 5a944adf - _coaddInputs(other._coaddInputs),
    ? -
    98 00c19e79 + _coaddInputs(other._coaddInputs)
    117 5a944adf - _apCorrMap(_cloneApCorrMap(other._apCorrMap))
    { if (copyMetadata) _metadata = _metadata->deepCopy(); } ExposureInfo & ExposureInfo::operator=(ExposureInfo const & other) { if (&other != this) { _wcs = _cloneWcs(other._wcs); _psf = other._psf; _calib = _cloneCalib(other._calib); _detector = other._detector;
    128 fd15d1dd - _validPolygon = other._validPolygon;
    _filter = other._filter; _metadata = other._metadata; _coaddInputs = other._coaddInputs;
    132 5a944adf - _apCorrMap = _cloneApCorrMap(other._apCorrMap);
    } return *this;
    135 0a4b53bf - }
    136 0a4b53bf -
    137 5a944adf - void ExposureInfo::initApCorrMap() {
    138 5a944adf - _apCorrMap = boost::make_shared();
    } ExposureInfo::~ExposureInfo() {} ExposureInfo::FitsWriteData ExposureInfo::_startWriteFits(afw::geom::Point2I const & xy0) const { FitsWriteData data; data.metadata.reset(new daf::base::PropertyList()); data.imageMetadata.reset(new daf::base::PropertyList()); data.maskMetadata = data.imageMetadata; data.varianceMetadata = data.imageMetadata; data.metadata->combine(getMetadata()); // In the future, we might not have exactly three image HDUs, but we always do right now, // so 1=primary, 2=image, 3=mask, 4=variance, 5+=archive data.metadata->set("AR_HDU", 5, "HDU containing the archive used to store ancillary objects"); if (hasCoaddInputs()) { int coaddInputsId = data.archive.put(getCoaddInputs()); data.metadata->set("COADD_INPUTS_ID", coaddInputsId, "archive ID for coadd inputs catalogs"); }
    162 5a944adf - if (hasApCorrMap()) {
    163 5a944adf - int apCorrMapId = data.archive.put(getApCorrMap());
    164 5a944adf - data.metadata->set("AP_CORR_MAP_ID", apCorrMapId, "archive ID for aperture correction map");
    165 5a944adf - }
    if (hasPsf() && getPsf()->isPersistable()) { int psfId = data.archive.put(getPsf()); data.metadata->set("PSF_ID", psfId, "archive ID for the Exposure's main Psf"); } if (hasWcs() && getWcs()->isPersistable()) { int wcsId = data.archive.put(getWcs()); data.metadata->set("WCS_ID", wcsId, "archive ID for the Exposure's main Wcs");
    173 4f859dd5 - }
    174 fd15d1dd - if (hasValidPolygon() && getValidPolygon()->isPersistable()) {
    175 fd15d1dd - int polygonId = data.archive.put(getValidPolygon());
    176 fd15d1dd - data.metadata->set("VALID_POLYGON_ID", polygonId, "archive ID for the Exposure's valid polygon");
    } //LSST convention is that Wcs is in pixel coordinates (i.e relative to bottom left //corner of parent image, if any). The Wcs/Fits convention is that the Wcs is in //image coordinates. When saving an image we convert from pixel to index coordinates. //In the case where this image is a parent image, the reference pixels are unchanged //by this transformation if (hasWcs()) { PTR(Wcs) newWcs = getWcs()->clone(); //Create a copy newWcs->shiftReferencePixel(-xy0.getX(), -xy0.getY() ); // We want the WCS to appear in all HDUs data.imageMetadata->combine(newWcs->getFitsMetadata()); } //Store _x0 and _y0. If this exposure is a portion of a larger image, _x0 and _y0 //indicate the origin (the position of the bottom left corner) of the sub-image with //respect to the origin of the parent image. //This is stored in the fits header using the LTV convention used by STScI //(see \S2.6.2 of HST Data Handbook for STIS, version 5.0 // http://www.stsci.edu/hst/stis/documents/handbooks/currentDHB/ch2_stis_data7.html#429287). //This is not a fits standard keyword, but is recognised by ds9 //LTV keywords use the opposite convention to the LSST, in that they represent //the position of the origin of the parent image relative to the origin of the sub-image. // _x0, _y0 >= 0, while LTV1 and LTV2 <= 0 data.imageMetadata->set("LTV1", -xy0.getX()); data.imageMetadata->set("LTV2", -xy0.getY()); data.metadata->set("FILTER", getFilter().getName()); if (hasDetector()) {
    208 ded0eb52 - data.metadata->set("DETNAME", getDetector()->getId().getName());
    ? --------
    175 e60c1c57 + data.metadata->set("DETNAME", getDetector()->getName());
    209 ded0eb52 - data.metadata->set("DETSER", getDetector()->getId().getSerial());
    ? --------
    176 e60c1c57 + data.metadata->set("DETSER", getDetector()->getSerial());
    } /** * We need to define these keywords properly! XXX */ data.metadata->set("TIME-MID", getCalib()->getMidTime().toString()); data.metadata->set("EXPTIME", getCalib()->getExptime()); data.metadata->set("FLUXMAG0", getCalib()->getFluxMag0().first); data.metadata->set("FLUXMAG0ERR", getCalib()->getFluxMag0().second); return data; } void ExposureInfo::_finishWriteFits(fits::Fits & fitsfile, FitsWriteData const & data) const { data.archive.writeFits(fitsfile); } void ExposureInfo::_readFits( fits::Fits & fitsfile, PTR(daf::base::PropertySet) metadata, PTR(daf::base::PropertySet) imageMetadata ) { // true: strip keywords that are related to the created WCS from the input metadata _wcs = makeWcs(imageMetadata, true); if (!imageMetadata->exists("INHERIT")) { // New-style exposures put everything but the Wcs in the primary HDU, use // INHERIT keyword in the others. For backwards compatibility, if we don't // find the INHERIT keyword, we ignore the primary HDU metadata and expect // everything to be in the image HDU metadata. Note that we can't merge them, // because they're probably duplicates. metadata = imageMetadata; } _filter = Filter(metadata, true); detail::stripFilterKeywords(metadata); PTR(Calib) newCalib(new Calib(metadata)); setCalib(newCalib); detail::stripCalibKeywords(metadata); int archiveHdu = popInt(*metadata, "AR_HDU"); if (archiveHdu) { fitsfile.setHdu(archiveHdu); table::io::InputArchive archive = table::io::InputArchive::readFits(fitsfile); // Load the Psf and Wcs from the archive; id=0 results in a null pointer. // Note that the binary table Wcs, if present, clobbers the FITS header one, // because the former might be an approximation to something we can't represent // using the FITS WCS standard but can represent with binary tables. int psfId = popInt(*metadata, "PSF_ID"); try { _psf = archive.get(psfId);
    262 1caeb568 - } catch (pex::exceptions::NotFoundException & err) {
    ? ^^^^^^ ^
    229 21597d88 + } catch (pex::exceptions::NotFoundError & err) {
    ? ^^ ^ pex::logging::Log::getDefaultLog().warn( boost::format("Could not read PSF; setting to null: %s") % err.what() ); } int wcsId = popInt(*metadata, "WCS_ID"); try { _wcs = archive.get(wcsId);
    270 1caeb568 - } catch (pex::exceptions::NotFoundException & err) {
    ? ^^^^^^ ^
    237 21597d88 + } catch (pex::exceptions::NotFoundError & err) {
    ? ^^ ^ pex::logging::Log::getDefaultLog().warn( boost::format("Could not read WCS; setting to null: %s") % err.what() ); } int coaddInputsId = popInt(*metadata, "COADD_INPUTS_ID"); try { _coaddInputs = archive.get(coaddInputsId);
    278 724b3939 - } catch (pex::exceptions::NotFoundException & err) {
    ? ^^^^^^ ^
    245 21597d88 + } catch (pex::exceptions::NotFoundError & err) {
    ? ^^ ^ pex::logging::Log::getDefaultLog().warn( boost::format("Could not read CoaddInputs; setting to null: %s") % err.what() ); }
    283 5a944adf - int apCorrMapId = popInt(*metadata, "AP_CORR_MAP_ID");
    284 5a944adf - try {
    285 5a944adf - _apCorrMap = archive.get(apCorrMapId);
    286 5a944adf - } catch (pex::exceptions::NotFoundException & err) {
    287 5a944adf - pex::logging::Log::getDefaultLog().warn(
    288 5a944adf - boost::format("Could not read ApCorrMap; setting to null: %s") % err.what()
    289 5a944adf - );
    290 5a944adf - }
    291 fd15d1dd - int validPolygonId = popInt(*metadata, "VALID_POLYGON_ID");
    292 fd15d1dd - try {
    293 fd15d1dd - _validPolygon = archive.get(validPolygonId);
    294 fd15d1dd - } catch (pex::exceptions::NotFoundException & err) {
    295 fd15d1dd - pex::logging::Log::getDefaultLog().warn(
    296 fd15d1dd - boost::format("Could not read ValidPolygon; setting to null: %s") % err.what()
    297 fd15d1dd - );
    298 fd15d1dd - }
    } _metadata = metadata; } }}} // namespace lsst::afw::image

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    4f859dd5

    commit 4f859dd5ad7dd3301410833d48076da3d552a387
    Author: Jim Bosch 
    Date:   Mon Dec 17 17:13:45 2012 -0500
    
        ExposureInfo now saves Psf and Wcs.
    

    fd15d1dd

    commit fd15d1dd03c8a1d1b06864fe90ad7d962bc7e567
    Author: Bob Armstrong 
    Date:   Mon Sep 15 08:34:26 2014 -0400
    
        Exposure: Add a Polygon object to Exposure.
        
        Polygons will be used to define valid regions for each CCD to
        reject vignetted regions when building the Coadd Psf.
    

    1caeb568

    commit 1caeb5685c56569cf07c963df4ba40d05feffc14
    Author: Jim Bosch 
    Date:   Mon Mar 4 15:43:49 2013 -0500
    
        When we can't read an Exposure's Psf or Wcs, warn and load null instead of throwing.
    

    0a4b53bf

    commit 0a4b53bfbc2a788fa566ba4a967ae552e7ff37b8
    Author: Jim Bosch 
    Date:   Mon Nov 12 16:08:08 2012 -0500
    
        Add ExposureInfo class to aggregate all the things that distinguish an Exposure from a MaskedImage
    

    ded0eb52

    commit ded0eb52af9b4e28790afe94d115c1d8699fa271
    Author: Jim Bosch 
    Date:   Tue Nov 20 00:46:52 2012 -0500
    
        Overhaul FITS persistence for MaskedImage and Exposure: no more appending or passing HDU to read, no more multi-file support, but we put metadata in primary HDU and use INHERIT keyword (as per discussion on lsst-data list).
    

    724b3939

    commit 724b393912c16b0d4debaa9d16ea5c57f51ab35b
    Merge: 14b0da8 aacb8e7
    Author: Jim Bosch 
    Date:   Wed Mar 13 13:40:37 2013 -0400
    
        Merge branch 'tickets/2696' into next
        
        Conflicts:
            src/image/ExposureInfo.cc
    

    5a944adf

    commit 5a944adfda0e29fe234bd1b6e7528768f4062652
    Author: Jim Bosch 
    Date:   Tue Jun 3 16:44:07 2014 -0400
    
        Add an ApCorrMap to ExposureInfo (and by extension, Exposure).
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    e60c1c57

    commit e60c1c57f2d0957d5c0b15228ad3d3800bb8b45b
    Author: Russell Owen 
    Date:   Sun Jan 26 17:27:54 2014 -0800
    
        The C++ code compiles, but cameraGeom's SWIG files have not been updated
    

    00c19e79

    commit 00c19e79f743406017a2d9c00b28579b28f52eac
    Author: Jim Bosch 
    Date:   Fri May 3 21:26:46 2013 -0500
    
        ExposureInfo needs to include CoaddInputs in copy, assignment
    

    910062c9

    commit 910062c9757a18d5415355827222db51a51a4ca7
    Author: Jim Bosch 
    Date:   Mon Jan 7 17:57:00 2013 -0500
    
        ExposureInfo now holds an (optional) pair of ExposureCatalogs for coadd provenance.
    

    0a4b53bf

    commit 0a4b53bfbc2a788fa566ba4a967ae552e7ff37b8
    Author: Jim Bosch 
    Date:   Mon Nov 12 16:08:08 2012 -0500
    
        Add ExposureInfo class to aggregate all the things that distinguish an Exposure from a MaskedImage
    

    Return to list

    tests/ellipse.py

    Diff:

    1 755df097 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for geom.ellipses Run with: ./ellipse.py or python >>> import ellipse; ellipse.run() """ import unittest import numpy import lsst.utils.tests as utilsTests import lsst.pex.exceptions import lsst.afw.geom.ellipses import lsst.afw.image numpy.random.seed(500) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class EllipseTestCase(unittest.TestCase): def setUp(self): self.cores = [ lsst.afw.geom.ellipses.Axes(4, 3, 1), lsst.afw.geom.ellipses.Quadrupole(5, 3, -1) ] self.classes = [lsst.afw.geom.ellipses.Axes, lsst.afw.geom.ellipses.Quadrupole] for s in lsst.afw.geom.ellipses.Separable.values(): self.cores.append(s(0.5, 0.3, 2.1)) self.classes.append(s) def assertClose(self, a, b): self.assert_(numpy.allclose(a, b), "%s != %s" % (a, b)) def testRadii(self): for core, det, trace in zip(self.cores, [144, 14], [25, 8]): detRadius = det**0.25 traceRadius = (0.5 * trace)**0.5 area = numpy.pi * det**0.5 self.assertClose(core.getDeterminantRadius(), detRadius) self.assertClose(core.getTraceRadius(), traceRadius) self.assertClose(core.getArea(), area) for cls in self.classes: conv = cls(core) self.assertClose(conv.getDeterminantRadius(), detRadius) self.assertClose(conv.getTraceRadius(), traceRadius) self.assertClose(conv.getArea(), area) conv.scale(3.0) self.assertClose(conv.getDeterminantRadius(), detRadius * 3) self.assertClose(conv.getTraceRadius(), traceRadius * 3) self.assertClose(conv.getArea(), area * 9) def testAccessors(self): for core in self.cores: vec = numpy.random.randn(3) * 1E-3 + core.getParameterVector() core.setParameterVector(vec) self.assert_((core.getParameterVector()==vec).all()) center = lsst.afw.geom.Point2D(*numpy.random.randn(2)) ellipse = lsst.afw.geom.ellipses.Ellipse(core, center) self.assertClose(core.getParameterVector(), ellipse.getParameterVector()[:3]) self.assertEqual(tuple(center), tuple(ellipse.getCenter())) self.assertEqual(lsst.afw.geom.Point2D, type(ellipse.getCenter())) newcore = lsst.afw.geom.ellipses.Axes(1,2,3) newcore.normalize() core.assign(newcore) ellipse.setCore(core) self.assertClose(core.getParameterVector(), ellipse.getCore().getParameterVector()) self.assert_((core.clone().getParameterVector()==core.getParameterVector()).all()) self.assert_(core is not core.clone()) self.assert_((lsst.afw.geom.ellipses.Ellipse(ellipse).getParameterVector() == ellipse.getParameterVector()).all()) self.assert_(ellipse is not lsst.afw.geom.ellipses.Ellipse(ellipse)) def testTransform(self): for core in self.cores: transform = lsst.afw.geom.LinearTransform(numpy.random.randn(2,2)) t1 = core.transform(transform) core.transformInPlace(transform) self.assert_(t1 is not core) self.assertClose(t1.getParameterVector(), core.getParameterVector()) def testPixelRegion(self): for core in self.cores: e = lsst.afw.geom.ellipses.Ellipse(core, lsst.afw.geom.Point2D(*numpy.random.randn(2))) region = lsst.afw.geom.ellipses.PixelRegion(e) bbox = region.getBBox() bbox.grow(2) array = numpy.zeros((bbox.getHeight(), bbox.getWidth()), dtype=bool) for span in region: for point in span: adjusted = point - bbox.getMin() array[adjusted.getY(), adjusted.getX()] = True gt = e.getGridTransform() for i in range(bbox.getBeginY(), bbox.getEndY()): for j in range(bbox.getBeginX(), bbox.getEndX()): point = lsst.afw.geom.Point2I(j, i) adjusted = point - bbox.getMin() transformed = gt(lsst.afw.geom.Point2D(point)) r = (transformed.getX()**2 + transformed.getY()**2)**0.5 if array[adjusted.getY(), adjusted.getX()]: self.assert_(r <= 1.0, "Point %s is in region but r=%f" % (point, r)) else: self.assert_(r > 1.0, "Point %s is outside region but r=%f" % (point, r)) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(EllipseTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit=False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    755df097

    commit 755df097c5529de20757c49ebf2034b75cc42fbd
    Author: jbosch 
    Date:   Fri Dec 18 02:49:46 2009 +0000
    
        afw/#892 - updated swig wrappers for ellipses, added tests for Point, Extent, ellipses
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    Return to list

    include/lsst/afw/table/io/Persistable.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef AFW_TABLE_IO_Persistable_h_INCLUDED
                    #define AFW_TABLE_IO_Persistable_h_INCLUDED
                    
                    #include "boost/noncopyable.hpp"
                    
                    #include "lsst/base.h"
                    #include "lsst/pex/exceptions.h"
                    
                    namespace lsst { namespace afw {
                    
                    namespace fits {
                    
                    class Fits;
                    class MemFileManager;
                    
                    } // namespace fits
                    
                    namespace table { namespace io {
                    
                    class InputArchive;
                    class OutputArchive;
                    class OutputArchiveHandle;
                    class CatalogVector;
                    
                    /**
                     *  @brief An exception thrown when problems occur during persistence.
                     */
    
    29 43c99a68 - LSST_EXCEPTION_TYPE(PersistenceError, lsst::pex::exceptions::IoErrorException,
    ? ---------
    29 21597d88 + LSST_EXCEPTION_TYPE(PersistenceError, lsst::pex::exceptions::IoError,
    lsst::afw::table::io::PersistenceError) /** * @brief An exception thrown when an InputArchive's contents do not make sense. * * This is the exception thrown by the LSST_ARCHIVE_ASSERT macro. */ LSST_EXCEPTION_TYPE(MalformedArchiveError, lsst::afw::table::io::PersistenceError, lsst::afw::table::io::MalformedArchiveError) /** * @brief An assertion macro used to validate the structure of an InputArchive. * * This assertion is not enabled/disabled by NDEBUG, and throws an exception rather than aborting, * and should be reserved for errors that should only occur when an InputArchive is found to be * in a state that could not have been produced by an OutputArchive. */ #define LSST_ARCHIVE_ASSERT(EXPR) \ if (!(EXPR)) throw LSST_EXCEPT( \ lsst::afw::table::io::MalformedArchiveError, \ "Archive assertion failed: " # EXPR) /** * @brief A base class for objects that can be persisted via afw::table::io Archive classes. * * Inheriting from Persistable provides a public API for reading/writing individual objects to * FITS that is fully defined in the base class, with derived classes only needing to implement * persistence to catalogs. It is expected that objects that contain multiple persistables * (such as Exposures) will create their own InputArchives and OutputArchives, and use these * to avoid writing the same object twice (which would otherwise be a big concern for future * objects like ExposureCatalog and CoaddPsf). * * Generally speaking, an abstract base class that inherits from Persistable should * also inherit from PersistableFacade. * A concrete class that inherits (possibly indirectly) from Persistable should inherit from * PersistableFacade (though this just provides a slightly nicer interface to users), * implement isPersistable(), getPersistenceName(), and write(), and define a subclass of * PersistenceFactory. Inheritance from PersistableFacade should always precede inheritance * from Persistable. * * Persistable has no pure virtual member functions, and instead contains a default implementation
    71 6e929743 - * that throws LogicErrorException when the user attempts to save an object for which persistence
    ? ---------
    71 21597d88 + * that throws LogicError when the user attempts to save an object for which persistence
    * has not actually been implemented. */ class Persistable { public: /** * @brief Write the object to a regular FITS file. * * @param[in] fileName Name of the file to write to. * @param[in] mode If "w", any existing file with the given name will be overwritten. If * "a", new HDUs will be appended to an existing file. */ void writeFits(std::string const & fileName, std::string const & mode="w") const; /** * @brief Write the object to a FITS image in memory. * * @param[in] manager Name of the file to write to. * @param[in] mode If "w", any existing file with the given name will be overwritten. If * "a", new HDUs will be appended to an existing file. */ void writeFits(fits::MemFileManager & manager, std::string const & mode="w") const; #ifndef SWIG // only expose the higher-level interfaces to Python /** * @brief Write the object to an already-open FITS object. * * @param[in] fitsfile Open FITS object to write to. */ void writeFits(fits::Fits & fitsfile) const; #endif // !SWIG /// @brief Return true if this particular object can be persisted using afw::table::io. virtual bool isPersistable() const { return false; } virtual ~Persistable() {} protected: // convenient for derived classes not in afw::table::io typedef io::OutputArchiveHandle OutputArchiveHandle; /** * @brief Return the unique name used to persist this object and look up its factory. * * Must be less than ArchiveIndexSchema::MAX_NAME_LENGTH characters. */ virtual std::string getPersistenceName() const; /** * @brief Return the fully-qualified Python module that should be imported to guarantee that its * factory is registered. * * Must be less than ArchiveIndexSchema::MAX_MODULE_LENGTH characters. * * Will be ignored if empty. */ virtual std::string getPythonModule() const; /** * @brief Write the object to one or more catalogs. * * The handle object passed to this function provides an interface for adding new catalogs * and adding nested objects to the same archive (while checking for duplicates). See * OutputArchiveHandle for more information. */ virtual void write(OutputArchiveHandle & handle) const; Persistable() {} Persistable(Persistable const & other) {} void operator=(Persistable const & other) {} private: friend class io::OutputArchive; friend class io::InputArchive; template friend class PersistableFacade; static PTR(Persistable) _readFits(std::string const & fileName, int hdu=0); static PTR(Persistable) _readFits(fits::MemFileManager & manager, int hdu=0); static PTR(Persistable) _readFits(fits::Fits & fitsfile); }; /** * @brief A CRTP facade class for subclasses of Persistable. * * Derived classes should generally inherit from PersistableFacade at all levels, * but only inherit from Persistable via the base class of each hierarchy. For example, * with Psfs: * @code * class Psf: public PersistableFacade, public Persistable { ... }; * class DoubleGaussianPsf: public PersistableFacade, public Psf { ... }; * @endcode * * Inheriting from PersistableFacade is not required for any classes but the base of * each hierarchy, but doing so can save users from having to do some dynamic_casts. * * @note PersistableFacade should usually be the first class in a list of base classes; * if it appears after a base class that inherits from different specialization of * PersistableFacade, those base class member functions will hide the desired ones. */ template class PersistableFacade { public: #ifndef SWIG /** * @brief Read an object from an already open FITS object. * * @param[in] fitsfile FITS object to read from, already positioned at the desired HDU. */ static PTR(T) readFits(fits::Fits & fitsfile) { return boost::dynamic_pointer_cast(Persistable::_readFits(fitsfile)); } #endif // !SWIG /** * @brief Read an object from a regular FITS file. * * @param[in] fileName Name of the file to read. * @param[in] hdu HDU to read, where 1 is the primary. The special value of 0 * skips the primary HDU if it is empty. */ static PTR(T) readFits(std::string const & fileName, int hdu=0) { return boost::dynamic_pointer_cast(Persistable::_readFits(fileName, hdu)); } /** * @brief Read an object from a FITS file in memory. * * @param[in] manager Manager for the memory to read from. * @param[in] hdu HDU to read, where 1 is the primary. The special value of 0 * skips the primary HDU if it is empty. */ static PTR(T) readFits(fits::MemFileManager & manager, int hdu=0) { return boost::dynamic_pointer_cast(Persistable::_readFits(manager, hdu)); } }; #ifndef SWIG /** * @brief A base class for factory classes used to reconstruct objects from records. * * Classes that inherit from Persistable should also subclass PersistableFactory, * and instantiate exactly one instance of the derived factory with static duration (usually * the class and instance are both defined in an anonymous namespace in a source file). */ class PersistableFactory : private boost::noncopyable { protected: typedef io::InputArchive InputArchive; // convenient for derived classes not in afw::table::io typedef io::CatalogVector CatalogVector; public: /** * @brief Constructor for the factory. * * This should be called only once, and only on an object with static duration, * as a pointer to the object will be put in a singleton registry. * * The name must be globally unique with respect to *all* Persistables and be the * same as Persistable::getPersistenceName(); the Python module that a Persistable * may also declare is not used to resolve names, but rather just to import the * module that may install the necessary factory in the registry. */ explicit PersistableFactory(std::string const & name); /// @brief Construct a new object from the given InputArchive and vector of catalogs. virtual PTR(Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const = 0; /** * @brief Return the factory that has been registered with the given name. * * If the lookup fails and module is not an empty string, we will attempt to import a Python * module with that name (this will only work when the C++ is being called from Python) and * try again. */ static PersistableFactory const & lookup(std::string const & name, std::string const & module=""); virtual ~PersistableFactory() {} }; #endif // !SWIG }}}} // namespace lsst::afw::table::io #endif // !AFW_TABLE_IO_Persistable_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6e929743

    commit 6e929743960d4731f0979c1f78479a05382d347f
    Author: Jim Bosch 
    Date:   Mon Dec 17 15:24:29 2012 -0500
    
        Fix up persistence docs, use correct inheritance order in test code.
    

    43c99a68

    commit 43c99a6851d54a44e9bd44fffc5ab7b8a44d6eaa
    Author: Jim Bosch 
    Date:   Wed Dec 12 14:23:59 2012 -0500
    
        Custom exceptions and better error handling for table-based persistence
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/image/ImageAlgorithm.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    /**
                     * \file
                     * \brief Support for functors over Image's pixels
                     */
                    #ifndef LSST_AFW_IMAGE_IMAGE_ALGORITHM_H
                    #define LSST_AFW_IMAGE_IMAGE_ALGORITHM_H
                    
                    #include 
                    #include 
                    #include 
                    #include 
                    #include 
                    
                    #include "boost/tr1/functional.hpp"
                    #include "boost/mpl/bool.hpp"
                    #include "boost/shared_ptr.hpp"
                    
                    #include "lsst/afw/image/lsstGil.h"
                    #include "lsst/afw/image/Utils.h"
                    #include "lsst/afw/image/ImageUtils.h"
                    #include "lsst/daf/base.h"
                    #include "lsst/daf/base/Citizen.h"
                    #include "lsst/pex/exceptions.h"
                    
                    namespace lsst { namespace afw { namespace image {
                    #if !defined(SWIG)
                        /**
                         * A functor class equivalent to tr1::function, but with a virtual operator()
                         */
                        template
                        struct pixelOp0 : public std::tr1::function {
                            virtual ~pixelOp0() {}
                            virtual ValT operator()() const = 0;
                        };
                        
                        /**
                         * A functor class equivalent to tr1::function, but with a virtual operator()
                         */
                        template
                        struct pixelOp1 : public std::tr1::function {
                            virtual ~pixelOp1() {}
                            virtual ValT operator()(ValT lhs) const = 0;
                        };
                        
                        /**
                         * A functor class equivalent to tr1::function, but with a virtual operator()
                         */
                        template
                        struct pixelOp1XY : public std::tr1::function {
                            virtual ~pixelOp1XY() {}
                            virtual ValT operator()(int x, int y, ValT lhs) const = 0;
                        };
                        
                        /**
                         * A functor class equivalent to tr1::function, but with a virtual operator()
                         */
                        template
                        struct pixelOp2 : public std::tr1::function
                        {
                            virtual ~pixelOp2() {}
                            virtual LhsT operator()(LhsT lhs, RhsT rhs) const = 0;
                        };
                    
                        /**
                         * A functor class equivalent to tr1::function, but with a virtual operator()
                         */
                        template
                        struct pixelOp2XY : public std::tr1::function
                        {
                            virtual ~pixelOp2XY() {}
                            virtual LhsT operator()(int x, int y, LhsT lhs, RhsT rhs) const = 0;
                        };
                    
                        /*******************************************************************************************************/
                        /**
                         * Set each pixel in an Image to func()
                         */
                        template
                        void for_each_pixel(Image &lhs,     ///< Image to set
                                            pixelOp0 const& func ///< functor to call
                                           )
                        {
                            for (int y = 0; y != lhs.getHeight(); ++y) {
                                for (typename Image::x_iterator lhsPtr = lhs.row_begin(y), lhsEnd = lhs.row_end(y);
                                     lhsPtr != lhsEnd; ++lhsPtr) {
                                    *lhsPtr = func();
                                }
                            }
                        }
                    
                        /**
                         * Set each pixel in an Image to func(lhs)
                         */
                        template
                        void for_each_pixel(Image &lhs,                ///< Image to set
                                            pixelOp1 const& func       ///< functor to call
                                           )
                        {
                            for (int y = 0; y != lhs.getHeight(); ++y) {
                                for (typename Image::x_iterator lhsPtr = lhs.row_begin(y), lhsEnd = lhs.row_end(y);
                                     lhsPtr != lhsEnd; ++lhsPtr) {
                                    *lhsPtr = func(*lhsPtr);
                                }
                            }
                        }
                    
                        /**
                         * Set each pixel in an Image to func(x, y, lhs)
                         *
                         * (x, y) allow for lhs.getXY0()
                         */
                        template
                        void for_each_pixel(Image &lhs,                ///< Image to set
                                            pixelOp1XY const& func     ///< functor to call
                                           )
                        {
                            for (int y = 0; y != lhs.getHeight(); ++y) {
                                int x = lhs.getX0();
                                for (typename Image::x_iterator lhsPtr = lhs.row_begin(y), lhsEnd = lhs.row_end(y);
                                     lhsPtr != lhsEnd; ++lhsPtr, ++x) {
                                    *lhsPtr = func(x, y + lhs.getY0(), *lhsPtr);
                                }
                            }
                        }
                    
                        /**
                         * Set each pixel in an Image to func(rhs), getting the rhs from an Image
                         */
                        template
                        void for_each_pixel(Image &lhs,                ///< Image to set
                                            Image const& rhs,          ///< other Image to pass to @c func
                                            pixelOp1 const& func       ///< functor to call
                                           )
                        {
                            if (lhs.getDimensions() != rhs.getDimensions()) {
    
    160 45645345 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    160 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % lhs.getWidth() % lhs.getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } for (int y = 0; y != lhs.getHeight(); ++y) { typename Image::const_x_iterator rhsPtr = rhs.row_begin(y); for (typename Image::x_iterator lhsPtr = lhs.row_begin(y), lhsEnd = lhs.row_end(y); lhsPtr != lhsEnd; ++rhsPtr, ++lhsPtr) { *lhsPtr = func(*rhsPtr); } } } /** * Set each pixel in an Image to func(lhs, rhs), getting the rhs from an Image */ template void for_each_pixel(Image &lhs, ///< Image to set Image const& rhs, ///< other Image to pass to @c func pixelOp2 const& func ///< functor to call ) { if (lhs.getDimensions() != rhs.getDimensions()) {
    185 45645345 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    185 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % lhs.getWidth() % lhs.getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } for (int y = 0; y != lhs.getHeight(); ++y) { typename Image::const_x_iterator rhsPtr = rhs.row_begin(y); for (typename Image::x_iterator lhsPtr = lhs.row_begin(y), lhsEnd = lhs.row_end(y); lhsPtr != lhsEnd; ++rhsPtr, ++lhsPtr) { *lhsPtr = func(*lhsPtr, *rhsPtr); } } } /** * Set each pixel in an Image to func(x, y, lhs, rhs), getting the rhs from an Image * * (x, y) allow for lhs.getXY0() */ template void for_each_pixel(Image &lhs, ///< Image to set Image const& rhs, ///< other Image to pass to @c func pixelOp2XY const& func ///< functor to call ) { if (lhs.getDimensions() != rhs.getDimensions()) {
    211 d2fef1e5 - throw LSST_EXCEPT(lsst::pex::exceptions::LengthErrorException,
    ? ---------
    211 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
    (boost::format("Images are of different size, %dx%d v %dx%d") % lhs.getWidth() % lhs.getHeight() % rhs.getWidth() % rhs.getHeight()).str()); } for (int y = 0; y != lhs.getHeight(); ++y) { typename Image::const_x_iterator rhsPtr = rhs.row_begin(y); int x = lhs.getX0(); for (typename Image::x_iterator lhsPtr = lhs.row_begin(y), lhsEnd = lhs.row_end(y); lhsPtr != lhsEnd; ++rhsPtr, ++lhsPtr, ++x) { *lhsPtr = func(x, y + lhs.getY0(), *lhsPtr, *rhsPtr); } } } #endif }}} // lsst::afw::image #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    d2fef1e5

    commit d2fef1e5dd11242836f57c6da043aa0123ac141e
    Author: rhl 
    Date:   Wed Dec 2 17:18:03 2009 +0000
    
        Added ability for for_each_pixel to know its coordinates
    

    45645345

    commit 4564534503f405bb9a8c0c2e9270b49878a3b1c0
    Author: rhl 
    Date:   Tue Dec 1 23:59:53 2009 +0000
    
        Supported MaskedImage /= Image where Image is of same type as MaskedImage.getImage();  in C++ support Image /= Image for non-matched types.  Added for_each_pixel to write the code; #1038
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/math/mathLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    %define mathLib_DOCSTRING
                    "
                    Python interface to lsst::afw::math classes
                    "
                    %enddef
                    
                    %feature("autodoc", "1");
                    %module(package="lsst.afw.math",docstring=mathLib_DOCSTRING) mathLib
                    
                    %{
                    #   include "lsst/daf/base.h"
                    #   include "lsst/pex/logging.h"
                    #   include "lsst/pex/policy.h"
                    #   include "lsst/afw/image.h"
                    #   include "lsst/afw/geom.h"
    
    40 4563d0f0 + # include "lsst/afw/cameraGeom.h"
    # include "lsst/afw/math.h"
    41 4563d0f0 - # include "lsst/afw/cameraGeom.h"
    # pragma clang diagnostic ignored "-Warray-bounds" // PyTupleObject has an array declared as [1] %}
    46 853c5734 + %include "lsst/p_lsstSwig.i"
    47 853c5734 +
    // Enable ndarray's NumPy typemaps; types are declared in %included files.
    49 853c5734 + %initializeNumPy(afw_math)
    %{
    48 5d65499c - #define PY_ARRAY_UNIQUE_SYMBOL LSST_AFW_MATH_NUMPY_ARRAY_API
    49 5d65499c - #include "numpy/arrayobject.h"
    #include "ndarray/swig.h" #include "ndarray/swig/eigen.h" %}
    53 5d65499c - %init %{
    54 5d65499c - import_array();
    55 5d65499c - %}
    %include "ndarray.i"
    57 5d65499c -
    58 ae06b2a8 - %include "lsst/p_lsstSwig.i"
    // vectors of plain old types; template vectors of more complex types in objectVectors.i %template(vectorF) std::vector; %template(vectorD) std::vector; %template(vectorI) std::vector; %template(vectorVectorF) std::vector >; %template(vectorVectorD) std::vector >; %template(vectorVectorI) std::vector >; %import "lsst/afw/image/imageLib.i" %lsst_exceptions();
    73 264e671e - %include "approximate.i"
    %include "function.i" %include "kernel.i" %include "minimize.i" %include "statistics.i" %include "interpolate.i" %include "background.i" %include "warpExposure.i" %include "spatialCell.i" %include "random.i" %include "stack.i" %include "GaussianProcess.i" %include "objectVectors.i" // must come last %include "LeastSquares.i"
    88 561d9af1 - %include "BoundedField.i"
    89 3f99dca1 - %include "ChebyshevBoundedField.i"
    %inline %{ struct InitGsl { InitGsl() { static int first = true; if (first) { (void)gsl_set_error_handler_off(); } } }; InitGsl _initGsl; // created at import time, to initialise the GSL library %}

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    561d9af1

    commit 561d9af1a98006c5026631538c2a0b3ff9b00844
    Author: Jim Bosch 
    Date:   Fri May 23 14:26:48 2014 -0400
    
        New base class for image-associated 2-d functions.
    

    5d65499c

    commit 5d65499cb1d04df9a3159a61d2f0820d1c96b6c5
    Author: Jim Bosch 
    Date:   Sat Mar 31 16:35:59 2012 -0400
    
        Add Python wrappers for LeastSquares
    

    4563d0f0

    commit 4563d0f054173793ca51c25afdac392dc16bdb19
    Author: smm 
    Date:   Wed Nov 9 02:57:43 2011 +0000
    
        afw Winter2012b: upgrade to swig 2.x
    

    ae06b2a8

    commit ae06b2a82f540d4475ab1df257cd211bc5b670c9
    Author: dubcovsky 
    Date:   Sat Oct 24 00:38:07 2009 +0000
    
        #892 swig wrappers for ellipse classes
    

    3f99dca1

    commit 3f99dca17c50d3a38e5c5b0a487a347521286dd4
    Author: Jim Bosch 
    Date:   Fri May 23 18:50:20 2014 -0400
    
        Added 2-d Chebyshev class with new API
    

    264e671e

    commit 264e671eb6ee7db871f0611ee8606cbe2e61a061
    Author: Steven Bickerton 
    Date:   Fri Oct 24 14:37:15 2014 +0900
    
        Use shared_ptr.  Add test.  Disable double,int backgrounds.
    

    Commits in /Users/nate/repos_lsst/afw/

    4563d0f0

    commit 4563d0f054173793ca51c25afdac392dc16bdb19
    Author: smm 
    Date:   Wed Nov 9 02:57:43 2011 +0000
    
        afw Winter2012b: upgrade to swig 2.x
    

    853c5734

    commit 853c5734ee13f55fd35e9e18ed5ac69a0073b97f
    Author: Jim Bosch 
    Date:   Wed Apr 8 16:18:28 2015 -0400
    
        Utilize new numeric scalar typemaps and NumPy import macro.
    

    Return to list

    include/lsst/afw/image/fits/fitsiompl.h

    Diff:

                    // -*- lsst-c++ -*-
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #ifndef LSST_AFW_IMAGE_fits_io_mpl_h_INCLUDED
                    #define LSST_AFW_IMAGE_fits_io_mpl_h_INCLUDED
                    
                    #include "boost/mpl/for_each.hpp"
                    #include "boost/mpl/vector.hpp"
                    
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/fits.h"
                    #include "lsst/afw/image/fits/fits_io.h"
                    #include "lsst/afw/image/Image.h"
                    
                    namespace lsst { namespace afw { namespace image {
                    
                    namespace {
                    struct found_type : public std::exception { }; // type to throw when we've read our data
                    
                    template
                    class try_fits_read_array {
                    public:
                        try_fits_read_array(fits::Fits & fitsfile,
                                            ndarray::Array & array,
                                            geom::Point2I & xy0,
                                            daf::base::PropertySet & metadata,
                                            geom::Box2I const& bbox,
                                            ImageOrigin const origin
                        ) : _fitsfile(&fitsfile), _array(array), _xy0(xy0), 
                            _metadata(metadata), _bbox(bbox), _origin(origin) { }
                        
                        // read directly into the desired type if the file's the same type
                        void operator()(typename ImageT::Pixel) {
                            try {
                                fits_read_array(*_fitsfile, _array, _xy0, _metadata, _bbox, _origin);
                                throw ExceptionT();         // signal that we've succeeded
                            } catch(fits::FitsTypeError const&) {
                                // ah well.  We'll try another image type
                            }
                        }
                    
                        template  
                            void operator()(OtherPixel) { // read and convert into the desired type
                            try {
                                ndarray::Array array;
                                fits_read_array(*_fitsfile, array, _xy0, _metadata, _bbox, _origin);
                                //copy and convert
                                _array = ndarray::allocate(array.getShape());
                                _array.deep() = array;
                                throw ExceptionT();         // signal that we've succeeded
                            } catch(fits::FitsTypeError const&) {
                                // pass
                            }
                        }
                    private:
                        fits::Fits * _fitsfile;
                        ndarray::Array & _array;
                        geom::Point2I & _xy0;
                        daf::base::PropertySet & _metadata;
                        geom::Box2I const& _bbox;
                        ImageOrigin _origin;
                    };
                    
                    } // anonymous
                                
                    template
                    void fits_read_image(
                        fits::Fits & fitsfile, ImageT& img,
                        lsst::daf::base::PropertySet &metadata,
    
    90 c9c89e06 - geom::Box2I const& bbox = geom::Box2I(),
    ? - -
    90 1a4ca329 + geom::Box2I const& bbox=geom::Box2I(),
    91 3263f939 - ImageOrigin const origin = LOCAL
    ? - ^^^^ ^
    91 93994d54 + ImageOrigin const origin=PARENT
    ? ^ ^^^^ ) { ndarray::Array array; geom::Point2I xy0; try { boost::mpl::for_each( try_fits_read_array( fitsfile, array, xy0, metadata, bbox, origin ) ); } catch (found_type &) { img = ImageT(array, false, xy0); return; } throw LSST_FITS_EXCEPT( fits::FitsError, fitsfile, "FITS file does not have one of the expected types" ); } template void fits_read_image( fits::Fits & fitsfile, ImageT& img, PTR(lsst::daf::base::PropertySet) metadata = PTR(lsst::daf::base::PropertySet)(),
    116 70efee05 - geom::Box2I const& bbox = geom::Box2I(),
    ? - -
    116 1a4ca329 + geom::Box2I const& bbox=geom::Box2I(),
    117 70efee05 - ImageOrigin const origin = LOCAL
    ? - ^^^^ ^
    117 93994d54 + ImageOrigin const origin=PARENT
    ? ^ ^^^^ ) { lsst::daf::base::PropertySet metadata_s; fits_read_image(fitsfile, img, (metadata ? *metadata : metadata_s), bbox, origin); } }}} // lsst::afw::image #endif // !LSST_AFW_IMAGE_fits_io_mpl_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    70efee05

    commit 70efee0580d789ad3e42234191a8e5b876bb9e5a
    Author: Robert Lupton the Good 
    Date:   Thu Apr 26 09:44:37 2012 -0400
    
        Change calling sequence of internal routines to use PropertySet & rather than PropertySet::Ptr
        
        The motivation is working around a clang++ bug (apparently failing to destroy shared_ptr when exceptions are thrown), but probably a good idea anyway
        
        N.b. This may not be a minimal set of changes; stay tuned for further commits to clean up this set of patches
    

    c9c89e06

    commit c9c89e060322883ace8599bf9b3584a73ac25d7b
    Author: jbosch 
    Date:   Tue Mar 8 23:14:46 2011 +0000
    
        afw #1556 - added std::ostream operator<< for Box, replaced (Point|Extent|Box)[ID] with 2[ID] forms
    

    3263f939

    commit 3263f93963907fdc317e43c074bf400f7ab1aa4e
    Author: dubcovsky 
    Date:   Thu Feb 24 00:56:41 2011 +0000
    
        #1556 Removed image::PointI and image::BoxI, Images and other classes modified accordingly. This is a work in progress. Tests and examples are not all converted to use geom classes yet
    

    Commits in /Users/nate/repos_lsst/afw/

    1a4ca329

    commit 1a4ca329fc8ac9c646272236d4182d5917845984
    Author: Russell Owen 
    Date:   Wed Sep 10 13:22:32 2014 -0700
    
        Two more instances where the default image origin was LOCAL
    

    93994d54

    commit 93994d544662b9a3589ba2fdda5f3a647fde3c70
    Author: Russell Owen 
    Date:   Wed Sep 10 13:46:23 2014 -0700
    
        Change default image origin to PARENT and use the default where possible.
    

    Return to list

    src/geom/ellipses/Axes.cc

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #include "lsst/afw/geom/ellipses/Quadrupole.h"
                    #include "lsst/afw/geom/ellipses/Axes.h"
                    
                    namespace lsst { namespace afw { namespace geom { namespace ellipses {
                    
                    BaseCore::Registrar Axes::registrar;
                    
                    std::string Axes::getName() const { return "Axes"; }
                    
                    void Axes::normalize() {
                        if (_vector[A] < 0 || _vector[B] < 0)
    
    35 ce01a540 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    35 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Major and minor axes cannot be negative."); if (_vector[A] < _vector[B]) { std::swap(_vector[A], _vector[B]); _vector[THETA] += M_PI_2; } if (_vector[THETA] > M_PI_2 || _vector[THETA] <= -M_PI_2) { _vector[THETA] -= M_PI * std::ceil(_vector[THETA] / M_PI - 0.5); } } void Axes::readParameters(double const * iter) { setA(*iter++); setB(*iter++); setTheta(*iter++); } void Axes::writeParameters(double * iter) const { *iter++ = getA(); *iter++ = getB(); *iter++ = getTheta(); } void Axes::_assignToQuadrupole(double & ixx, double & iyy, double & ixy) const { BaseCore::_assignAxesToQuadrupole(_vector[A], _vector[B], _vector[THETA], ixx, iyy, ixy); } BaseCore::Jacobian Axes::_dAssignToQuadrupole(double & ixx, double & iyy, double & ixy) const { return BaseCore::_dAssignAxesToQuadrupole(_vector[A], _vector[B], _vector[THETA], ixx, iyy, ixy); } void Axes::_assignToAxes(double & a, double & b, double & theta) const { a = _vector[A]; b = _vector[B]; theta = _vector[THETA]; } BaseCore::Jacobian Axes::_dAssignToAxes(double & a, double & b, double & theta) const { a = _vector[A]; b = _vector[B]; theta = _vector[THETA]; return Jacobian::Identity(); } void Axes::_assignFromQuadrupole(double ixx, double iyy, double ixy) { BaseCore::_assignQuadrupoleToAxes(ixx, iyy, ixy, _vector[A], _vector[B], _vector[THETA]); normalize(); } BaseCore::Jacobian Axes::_dAssignFromQuadrupole(double ixx, double iyy, double ixy) { return BaseCore::_dAssignQuadrupoleToAxes(ixx, iyy, ixy, _vector[A], _vector[B], _vector[THETA]); normalize(); } void Axes::_assignFromAxes(double a, double b, double theta) { _vector[A] = a; _vector[B] = b; _vector[THETA] = theta; } BaseCore::Jacobian Axes::_dAssignFromAxes(double a, double b, double theta) { _vector[A] = a; _vector[B] = b; _vector[THETA] = theta; return Jacobian::Identity(); } }}}} // namespace lsst::afw::geom::ellipses

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    ce01a540

    commit ce01a5406f327071e1701d534e563f0e75b870c4
    Author: jbosch 
    Date:   Wed Feb 2 01:27:08 2011 +0000
    
        afw #1556 - ellipses updated (#1551), but swig wrappers for ellipses now broken
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    lib/SConscript

    Diff:

                    # -*- python -*-
                    from lsst.sconsUtils import scripts, targets, env
                    
                    objs = env.SourcesForSharedLibrary(Glob("#src/*.cc") + Glob("#src/*/*.cc") + Glob("#src/*/*/*.cc") + Glob("#src/*/*/*/*.cc"))
                    
    
    6 9a54bc54 - import eups
    7 5fb2c35e - if eups.productDir("cuda_toolkit"):
    6 ed95653a + import lsst.utils
    7 ed95653a + try:
    8 ed95653a + lsst.utils.getPackageDir('cuda_toolkit')
    9 ed95653a + except Exception:
    10 ed95653a + pass
    11 ed95653a + else:
    objs.append("#src/math/detail/convGPU.os") objs.append("#src/math/detail/cudaLanczos.os") targets["lib"].extend(env.SharedLibrary(env["packageName"], objs, LIBS=env.getLibs("self")))

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    5fb2c35e

    commit 5fb2c35e8d820bd7a5b04a3923b5606358e7735a
    Author: Kresimir Cosic 
    Date:   Thu Dec 8 15:51:09 2011 +0100
    
        Gpu convolution does not need to depend on cuda_sdk package wile compiling
    

    9a54bc54

    commit 9a54bc543c765f54a9c226462f50bde9d2bfc183
    Author: Kresimir Cosic 
    Date:   Thu Nov 24 06:39:59 2011 +0100
    
        Fixed lib/SConscript to link with GPU convolution only when CUda packages are found
        - deleted testGPU.cc example. timeConvolveGPU.cc replaces this example
    

    Commits in /Users/nate/repos_lsst/afw/

    ed95653a

    commit ed95653aae0db5c64fec82321af822db861c9e9c
    Author: Joshua Hoblitt 
    Date:   Thu May 21 14:38:34 2015 -0700
    
        replace eups.productDir() calls with lsst.utils.getPackageDir()
    

    Return to list

    tests/testTableArchivesLib.i

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    
                    %module testTableArchivesLib
                    
                    %pythonnondynamic;
                    %naturalvar;  // use const reference typemaps
                    
                    %include "lsst/p_lsstSwig.i"
                    
                    %lsst_exceptions()
                    
                    %{
                    // It's really horrible that I have to include all this just to get this simple
                    // test module to build, but that's the way it is right now.
                    #include "lsst/afw/detection.h"
    
    38 aacb8e71 - #include "lsst/afw/cameraGeom.h"
    #include "lsst/afw/image.h" #include "lsst/pex/logging.h" #include "lsst/afw/math.h"
    41 7b9f89c5 + #include "lsst/afw/cameraGeom.h"
    42 12f0506e + #include "lsst/afw/table.h"
    %} %import "lsst/afw/detection/detectionLib.i" %shared_ptr(DummyPsf); %inline { // not really a Psf, just a Persistable we can stuff in an Exposure class DummyPsf : public lsst::afw::detection::Psf { public: virtual PTR(lsst::afw::detection::Psf) clone() const { return PTR(lsst::afw::detection::Psf)(new DummyPsf(_x)); } virtual bool isPersistable() const { return true; } double getValue() const { return _x; } explicit DummyPsf(double x) : _x(x) {} protected: virtual PTR(Image) doComputeKernelImage( lsst::afw::geom::Point2D const & ccdXY, lsst::afw::image::Color const & color ) const { return PTR(Image)(); } virtual double doComputeApertureFlux( double radius, lsst::afw::geom::Point2D const & ccdXY, lsst::afw::image::Color const & color ) const { return 0.0; } virtual lsst::afw::geom::ellipses::Quadrupole doComputeShape( lsst::afw::geom::Point2D const & ccdXY, lsst::afw::image::Color const & color ) const { return lsst::afw::geom::ellipses::Quadrupole(); } virtual std::string getPersistenceName() const { return "DummyPsf"; } virtual std::string getPythonModule() const { return "testTableArchivesLib"; } virtual void write(OutputArchiveHandle & handle) const; double _x; }; } %{ #include "boost/make_shared.hpp" #include "lsst/afw/table/io/OutputArchive.h" #include "lsst/afw/table/io/InputArchive.h" #include "lsst/afw/table/io/CatalogVector.h" namespace { struct DummyPsfPersistenceHelper : private boost::noncopyable { lsst::afw::table::Schema schema; lsst::afw::table::Key x; static DummyPsfPersistenceHelper const & get() { static DummyPsfPersistenceHelper instance; return instance; } private: DummyPsfPersistenceHelper() : schema(), x(schema.addField("x", "dummy parameter")) { schema.getCitizen().markPersistent(); } }; class DummyPsfFactory : public lsst::afw::table::io::PersistableFactory { public: virtual PTR(lsst::afw::table::io::Persistable) read(InputArchive const & archive, CatalogVector const & catalogs) const { static DummyPsfPersistenceHelper const & keys = DummyPsfPersistenceHelper::get(); LSST_ARCHIVE_ASSERT(catalogs.size() == 1u); LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u); lsst::afw::table::BaseRecord const & record = catalogs.front().front(); LSST_ARCHIVE_ASSERT(record.getSchema() == keys.schema); return boost::make_shared( record.get(keys.x) ); } DummyPsfFactory(std::string const & name) : lsst::afw::table::io::PersistableFactory(name) {} }; DummyPsfFactory registration("DummyPsf"); } // anonymous void DummyPsf::write(OutputArchiveHandle & handle) const { static DummyPsfPersistenceHelper const & keys = DummyPsfPersistenceHelper::get(); lsst::afw::table::BaseCatalog catalog = handle.makeCatalog(keys.schema); PTR(lsst::afw::table::BaseRecord) record = catalog.addNew(); (*record).set(keys.x, _x); handle.saveCatalog(catalog); } %} %lsst_persistable(DummyPsf);

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    aacb8e71

    commit aacb8e7145342e4bdbd611a458c652328778042a
    Author: Jim Bosch 
    Date:   Mon Mar 4 15:56:09 2013 -0500
    
        Unit tests for import mechanism in table persistence.
    

    Commits in /Users/nate/repos_lsst/afw/

    7b9f89c5

    commit 7b9f89c5d3a8bdedaf50793abaf4d5322716b892
    Author: Russell Owen 
    Date:   Mon Jan 27 16:31:54 2014 -0800
    
        Switch TransformRegistry to unordered_map.
        It all builds but the swig wrapper for cameraGeom isn't working due to a missing symbol.
    

    12f0506e

    commit 12f0506e3b45c001fc10b3888a604fd8d1ac1ca8
    Author: Lauren MacArthur 
    Date:   Wed Apr 8 16:20:57 2015 -0400
    
        Include lsst/afw/table.h in tests/testTableArchivesLib.i
    

    Return to list

    include/lsst/afw/math/FunctionLibrary.h

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    #ifndef LSST_AFW_MATH_FUNCTIONLIBRARY_H
                    #define LSST_AFW_MATH_FUNCTIONLIBRARY_H
                    /**
                     * @file
                     *
                     * @brief Define a collection of useful Functions.
                     *
                     * @author Russell Owen
                     *
                     * @ingroup afw
                     */
                    #include 
                    #include 
                    
                    #include "lsst/afw/geom.h"
                    #include "lsst/afw/math/Function.h"
                    #include "lsst/afw/geom/Angle.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    
                    #ifndef SWIG
                    using boost::serialization::make_nvp;
                    #endif
                    
                        /**
                         * @brief 1-dimensional integer delta function.
                         *
                         * f(x) = 1 if x == xo, 0 otherwise.
                         *
                         * For use as a kernel function be sure to handle the offset for row and column center;
                         * see examples/deltaFunctionKernel for an example.
                         *
                         * @ingroup afw
                         */
                        template
                        class IntegerDeltaFunction1: public Function1 {
                        public:
                            typedef typename Function1::Ptr Function1Ptr;
                    
                            /**
                             * @brief Construct an integer delta function with specified xo, yo
                             */
                            explicit IntegerDeltaFunction1(
                                double xo)
                            :
                                Function1(0),
                                _xo(xo)
                            {}
                    
                            virtual ~IntegerDeltaFunction1() {};
                    
                            virtual Function1Ptr clone() const {
                                return Function1Ptr(new IntegerDeltaFunction1(_xo));
                            }
                    
                            virtual ReturnT operator() (double x, double y) const {
                                return static_cast(x == _xo);
                            }
                    
                            virtual std::string toString(std::string const& prefix="") const {
                                std::ostringstream os;
                                os << "IntegerDeltaFunction1 [" << _xo << "]: ";
                                os << Function1::toString(prefix);
                                return os.str();
                            };
                    
                        private:
                            double _xo;
                    
                        protected:
                            /* Default constructor: intended only for serialization */
                            explicit IntegerDeltaFunction1() : Function1(0), _xo(0.0) {}
                    
                        private:
                            friend class boost::serialization::access;
                            template 
                            void serialize(Archive& ar, unsigned int const version) {
                                ar & make_nvp("fn1", boost::serialization::base_object >(*this));
                                ar & make_nvp("xo", this->_xo);
                            }
                        };
                    
                        /**
                         * @brief 2-dimensional integer delta function.
                         *
                         * f(x) = 1 if x == xo and y == yo, 0 otherwise.
                         *
                         * For use as a kernel function be sure to handle the offset for row and column center;
                         * see examples/deltaFunctionKernel for an example.
                         *
                         * @ingroup afw
                         */
                        template
                        class IntegerDeltaFunction2: public Function2 {
                        public:
                            typedef typename Function2::Ptr Function2Ptr;
                    
                            /**
                             * @brief Construct an integer delta function with specified xo, yo
                             */
                            explicit IntegerDeltaFunction2(
                                double xo,
                                double yo)
                            :
                                Function2(0),
                                _xo(xo),
                                _yo(yo)
                            {}
                    
                            virtual ~IntegerDeltaFunction2() {}
                    
                            virtual Function2Ptr clone() const {
                                return Function2Ptr(new IntegerDeltaFunction2(_xo, _yo));
                            }
                    
                            virtual ReturnT operator() (double x, double y) const {
                                return static_cast((x == _xo) && (y == _yo));
                            }
                    
                            virtual std::string toString(std::string const& prefix) const {
                                std::ostringstream os;
                                os << "IntegerDeltaFunction2 [" << _xo << ", " << _yo << "]: ";
                                os << Function2::toString(prefix);
                                return os.str();
                            }
                    
                        private:
                            double _xo;
                            double _yo;
                    
                        protected:
                            /* Default constructor: intended only for serialization */
                            explicit IntegerDeltaFunction2() : Function2(0), _xo(0.0), _yo(0.0) {}
                    
                        private:
                            friend class boost::serialization::access;
                            template 
                            void serialize(Archive& ar, unsigned int const version) {
                                ar & make_nvp("fn2", boost::serialization::base_object >(*this));
                                ar & make_nvp("xo", this->_xo);
                                ar & make_nvp("yo", this->_yo);
                            }
                        };
                    
                        /**
                         * @brief 1-dimensional Gaussian
                         *
                         * f(x) = A e^(-x^2 / 2 sigma^2)
                         * where:
                         * * A = 1 / (sqrt(2 pi) xSigma)
                         * coefficient c0 = sigma
                         *
                         * @ingroup afw
                         */
                        template
                        class GaussianFunction1: public Function1 {
                        public:
                            typedef typename Function1::Ptr Function1Ptr;
                    
                            /**
                             * @brief Construct a Gaussian function with specified sigma
                             */
                            explicit GaussianFunction1(
                                double sigma)    ///< sigma
                            :
                                Function1(1),
                                _multFac(1.0 / std::sqrt(lsst::afw::geom::TWOPI))
                            {
                                this->_params[0] = sigma;
                            }
                            virtual ~GaussianFunction1() {}
                    
                            virtual Function1Ptr clone() const {
                                return Function1Ptr(new GaussianFunction1(this->_params[0]));
                            }
                    
                            virtual ReturnT operator() (double x) const {
                                return static_cast (
                                    (_multFac / this->_params[0]) *
                                    std::exp(- (x * x) / (2.0 * this->_params[0] * this->_params[0])));
                            }
                    
                            virtual std::string toString(std::string const& prefix) const {
                                std::ostringstream os;
                                os << "GaussianFunction1 [" << _multFac << "]: ";
                                os << Function1::toString(prefix);
                                return os.str();
                            }
                    
                        private:
                            const double _multFac; ///< precomputed scale factor
                    
                        protected:
                            /* Default constructor: intended only for serialization */
                            explicit GaussianFunction1() : Function1(1), _multFac(1.0 / std::sqrt(lsst::afw::geom::TWOPI)) {}
                    
                        private:
                            friend class boost::serialization::access;
                            template 
                            void serialize(Archive& ar, unsigned int const version) {
                                ar & make_nvp("fn1", boost::serialization::base_object >(*this));
                            }
                        };
                    
                        /**
                         * @brief 2-dimensional Gaussian
                         *
                         * f(x,y) = A e^((-pos1^2 / 2 sigma1^2) - (pos2^2 / 2 sigma2^2))
                         * where:
                         * * A = 1 / (2 pi sigma1 sigma2)
                         * * pos1 =  cos(angle) x + sin(angle) y
                         * * pos2 = -sin(angle) x + cos(angle) y
                         * coefficients c0 = sigma1, c1 = sigma2, c2 = angle
                         *
                         * @note if sigma1 > sigma2 then angle is the angle of the major axis
                         *
                         * @ingroup afw
                         */
                        template
                        class GaussianFunction2: public Function2 {
                        public:
                            typedef typename Function2::Ptr Function2Ptr;
                    
                            /**
                             * @brief Construct a 2-dimensional Gaussian function
                             */
                            explicit GaussianFunction2(
                                double sigma1,      ///< sigma along the pos1 axis
                                double sigma2,      ///< sigma along the pos2 axis
                                double angle = 0.0) ///< angle of pos1 axis, in rad (along x=0, y=pi/2)
                            :
                                Function2(3),
                                _multFac(1.0 / (lsst::afw::geom::TWOPI))
                            {
                                this->_params[0] = sigma1;
                                this->_params[1] = sigma2;
                                this->_params[2] = angle;
                                _updateCache();
                            }
                    
                            virtual ~GaussianFunction2() {}
                    
                            virtual Function2Ptr clone() const {
                                return Function2Ptr(new GaussianFunction2(this->_params[0], this->_params[1], this->_params[2]));
                            }
                    
                            virtual ReturnT operator() (double x, double y) const {
                                if (_angle != this->_params[2]) {
                                    _updateCache();
                                }
                                double pos1 = ( _cosAngle * x) + (_sinAngle * y);
                                double pos2 = (-_sinAngle * x) + (_cosAngle * y);
                                return static_cast (
                                    (_multFac / (this->_params[0] * this->_params[1])) *
                                    std::exp(- ((pos1 * pos1) / (2.0 * this->_params[0] * this->_params[0]))
                                             - ((pos2 * pos2) / (2.0 * this->_params[1] * this->_params[1]))));
                            }
                    
                            virtual std::string toString(std::string const& prefix) const {
                                std::ostringstream os;
                                os << "GaussianFunction2: ";
                                os << Function2::toString(prefix);
                                return os.str();
                            }
                    
                            virtual bool isPersistable() const { return true; }
                    
                        protected:
                    
                            virtual std::string getPersistenceName() const;
                    
                            virtual void write(afw::table::io::OutputArchiveHandle & handle) const;
                    
                        private:
                            /**
                            * @brief Update cached values
                            *
                            * sin(angle) and cos(angle) are cached to speed computation
                            * and angle is cached so one can check if an update is required
                            *
                            * The current design is to have operator() update the cache if needed.
                            * An alternate design is to update the cache when the parameters are set,
                            * not test in operator().
                            * The main advantage to updating in operator() is safety and simplicity.
                            * The test is performed in one place, and it is the place where it matters the most.
                            * In contrast, there are multiple member functions to set parameters, and all must be overloaded
                            * to update the cache; miss one and the function silently misbehaves.
                            * There are trade-offs, of course. Testing the cache in operator() slows down operator() slightly.
                            * The overhead is small, but the function is typically evaulated more often
                            * than its parameters are changed.
                            */
                            void _updateCache() const {
                                _angle = this->_params[2];
                                _sinAngle = std::sin(_angle);
                                _cosAngle = std::cos(_angle);
                            }
                            const double _multFac;  ///< precomputed scale factor
                            mutable double _angle;    ///< cached angle
                            mutable double _sinAngle; ///< cached sin(angle)
                            mutable double _cosAngle; ///< cached cos(angle)
                    
                        protected:
                            /* Default constructor: intended only for serialization */
                            explicit GaussianFunction2() : Function2(3), _multFac(1.0 / (lsst::afw::geom::TWOPI)), _angle(0.0),
                                _sinAngle(0.0), _cosAngle(1.0) {}
                    
                        private:
                            friend class boost::serialization::access;
                            template 
                            void serialize(Archive& ar, unsigned int const version) {
                                ar & make_nvp("fn2", boost::serialization::base_object >(*this));
                                ar & make_nvp("angle", this->_angle);
                                ar & make_nvp("sinAngle", this->_sinAngle);
                                ar & make_nvp("cosAngle", this->_cosAngle);
                            }
                        };
                    
                        /**
                         * @brief double Guassian (sum of two Gaussians)
                         *
                         * Intended for use as a PSF model: the main Gaussian represents the core
                         * and the second Gaussian represents the wings.
                         *
                         * f(x,y) = A (e^(-r^2 / 2 sigma1^2) + ampl2 e^(-r^2 / 2 sigma2^2))
                         * where:
                         * * A = 1 / (2 pi (sigma1^2 + ampl2 sigma2^2))
                         * * r^2 = x^2 + y^2
                         * coefficients c[0] = sigma1, c[1] = sigma2, c[2] = ampl2
                         *
                         * @ingroup afw
                         */
                        template
                        class DoubleGaussianFunction2: public Function2 {
                        public:
                            typedef typename Function2::Ptr Function2Ptr;
                    
                            /**
                             * @brief Construct a Gaussian function with specified x and y sigma
                             */
                            explicit DoubleGaussianFunction2(
                                double sigma1,      ///< sigma of main Gaussian
                                double sigma2 = 0,  ///< sigma of second Gaussian
                                double ampl2 = 0)   ///< amplitude of second Gaussian as a fraction of main Gaussian at peak
                            :
                                Function2(3),
                                _multFac(1.0 / (lsst::afw::geom::TWOPI))
                            {
                                this->_params[0] = sigma1;
                                this->_params[1] = sigma2;
                                this->_params[2] = ampl2;
                            }
                    
                            virtual ~DoubleGaussianFunction2() {}
                    
                            virtual Function2Ptr clone() const {
                                return Function2Ptr(
                                    new DoubleGaussianFunction2(this->_params[0], this->_params[1], this->_params[2]));
                            }
                    
                            virtual ReturnT operator() (double x, double y) const {
                                double radSq = (x * x) + (y * y);
                                double sigma1Sq = this->_params[0] * this->_params[0];
                                double sigma2Sq = this->_params[1] * this->_params[1];
                                double b = this->_params[2];
                                return static_cast (
                                    (_multFac / (sigma1Sq + (b * sigma2Sq))) *
                                    (std::exp(-radSq / (2.0 * sigma1Sq))
                                    + (b * std::exp(-radSq / (2.0 * sigma2Sq)))));
                            }
                    
                            virtual std::string toString(std::string const& prefix) const {
                                std::ostringstream os;
                                os << "DoubleGaussianFunction2 [" << _multFac << "]: ";
                                os << Function2::toString(prefix);
                                return os.str();
                            }
                    
                            virtual bool isPersistable() const { return true; }
                    
                        protected:
                    
                            virtual std::string getPersistenceName() const;
                    
                            virtual void write(afw::table::io::OutputArchiveHandle & handle) const;
                    
                        private:
                            const double _multFac; ///< precomputed scale factor
                    
                        protected:
                            /* Default constructor: intended only for serialization */
                            explicit DoubleGaussianFunction2() : Function2(3), _multFac(1.0 / (lsst::afw::geom::TWOPI)) {}
                    
                        private:
                            friend class boost::serialization::access;
                            template 
                            void serialize(Archive& ar, unsigned int const version) {
                                ar & make_nvp("fn2", boost::serialization::base_object >(*this));
                            }
                        };
                    
                        /**
                         * @brief 1-dimensional polynomial function.
                         *
                         * f(x) = c0 + c1 x + c2 x^2 + ... cn-1 x^(n-1)
                         *
                         * @ingroup afw
                         */
                        template
                        class PolynomialFunction1: public Function1 {
                        public:
                            typedef typename Function1::Ptr Function1Ptr;
                    
                            /**
                             * @brief Construct a polynomial function of the specified order.
                             *
                             * The parameters are initialized to zero.
                             */
                            explicit PolynomialFunction1(
                                unsigned int order)     ///< order of polynomial (0 for constant)
                            :
                                Function1(order+1) {
                            }
                    
                            /**
                             * @brief Construct a polynomial function with the specified parameters.
                             *
                             * The order of the polynomial is set to the length of the params vector.
                             *
                             * @throw lsst::pex::exceptions::InvalidParameter if params is empty
                             */
                            explicit PolynomialFunction1(
                                std::vector params)  ///< polynomial coefficients (const, x, x^2...)
                            :
                                Function1(params)
                            {
                                if (params.size() < 1) {
    
    463 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    463 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "PolynomialFunction1 called with empty vector"); } } virtual ~PolynomialFunction1() {} virtual Function1Ptr clone() const { return Function1Ptr(new PolynomialFunction1(this->_params)); } virtual bool isLinearCombination() const { return true; }; virtual ReturnT operator() (double x) const { int const order = static_cast(this->_params.size()) - 1; double retVal = this->_params[order]; for (int ii = order-1; ii >= 0; --ii) { retVal = (retVal * x) + this->_params[ii]; } return static_cast(retVal); } /** * @brief Get the polynomial order */ unsigned int getOrder() const { return this->getNParameters() - 1; }; virtual std::string toString(std::string const& prefix) const { std::ostringstream os; os << "PolynomialFunction1 []: "; os << Function1::toString(prefix); return os.str(); } protected: /* Default constructor: intended only for serialization */ explicit PolynomialFunction1() : Function1(1) {} private: friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("fn1", boost::serialization::base_object >(*this)); } }; /** * @brief 2-dimensional polynomial function with cross terms * * f(x,y) = c0 (0th order) * + c1 x + c2 y (1st order) * + c3 x^2 + c4 x y + c5 y^2 (2nd order) * + c6 x^3 + c7 x^2 y + c8 x y^2 + c9 y^3 (3rd order) * + ... * * Intermediate products for the most recent y are cached, * so when computing for a set of x, y it is more efficient to change x before you change y. * * @ingroup afw */ template class PolynomialFunction2: public BasePolynomialFunction2 { public: typedef typename Function2::Ptr Function2Ptr; /** * @brief Construct a polynomial function of specified order. * * The polynomial will have (order + 1) * (order + 2) / 2 coefficients * * The parameters are initialized to zero. */ explicit PolynomialFunction2( unsigned int order) ///< order of polynomial (0 for constant) : BasePolynomialFunction2(order), _oldY(0), _xCoeffs(this->_order + 1) {} /** * @brief Construct a polynomial function with specified parameters. * * The order of the polynomial is determined from the length of the params vector: * order = (sqrt(1 + 8 * length) - 3) / 2 * and if this is not an integer then the length is unsuitable *
    550 3771b5eb - * @throw lsst::pex::exceptions::InvalidParameterException if params length is unsuitable
    ? ^^^^^^ ^
    550 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if params length is unsuitable
    ? ^^ ^ * @throw lsst::pex::exceptions::Exception if an internal sanity check fails */ explicit PolynomialFunction2( std::vector params) ///< polynomial coefficients (const, x, y, x^2, xy, y^2...); ///< length must be one of 1, 3, 6, 10, 15... : BasePolynomialFunction2(params), _oldY(0), _xCoeffs(this->_order + 1) {} virtual ~PolynomialFunction2() {} virtual Function2Ptr clone() const { return Function2Ptr(new PolynomialFunction2(this->_params)); } virtual ReturnT operator() (double x, double y) const { /* Solve as follows: - f(x,y) = Cx0 + Cx1 x + Cx2 x^2 + Cx3 x^3 + ... where: Cx0 = P0 + P2 y + P5 y^2 + P9 y^3 + ... Cx1 = P1 + P4 y + P8 y2 + ... Cx2 = P3 + P7 y + ... Cx3 = P6 + ... ... Compute Cx0, Cx1...Cxn by solving 1-d polynomials in y in the usual way. These values are cached and only recomputed for new values of Y or if the parameters change. Then compute f(x,y) by solving the 1-d polynomial in x in the usual way. */ const int maxXCoeffInd = this->_order; if ((y != _oldY) || !this->_isCacheValid) { // update _xCoeffs cache // note: paramInd is decremented in both of the following loops int paramInd = static_cast(this->_params.size()) - 1; // initialize _xCoeffs to coeffs for pure y^n; e.g. for 3rd order: // _xCoeffs[0] = _params[9], _xCoeffs[1] = _params[8], ... _xCoeffs[3] = _params[6] for (int xCoeffInd = 0; xCoeffInd <= maxXCoeffInd; ++xCoeffInd, --paramInd) { _xCoeffs[xCoeffInd] = this->_params[paramInd]; } // finish computing _xCoeffs for (int xCoeffInd = 0, endXCoeffInd = maxXCoeffInd; paramInd >= 0; --paramInd) { _xCoeffs[xCoeffInd] = (_xCoeffs[xCoeffInd] * y) + this->_params[paramInd]; ++xCoeffInd; if (xCoeffInd >= endXCoeffInd) { xCoeffInd = 0; --endXCoeffInd; } } _oldY = y; this->_isCacheValid = true; } // use _xCoeffs to compute result double retVal = _xCoeffs[maxXCoeffInd]; for (int xCoeffInd = maxXCoeffInd - 1; xCoeffInd >= 0; --xCoeffInd) { retVal = (retVal * x) + _xCoeffs[xCoeffInd]; } return static_cast(retVal); } virtual std::vector getDFuncDParameters(double x, double y) const; virtual std::string toString(std::string const& prefix) const { std::ostringstream os; os << "PolynomialFunction2 [" << this->_order << "]: "; os << Function2::toString(prefix); return os.str(); } virtual bool isPersistable() const { return true; } protected: virtual std::string getPersistenceName() const; virtual void write(afw::table::io::OutputArchiveHandle & handle) const; private: mutable double _oldY; ///< value of y for which _xCoeffs is valid mutable std::vector _xCoeffs; ///< working vector protected: /* Default constructor: intended only for serialization */ explicit PolynomialFunction2() : BasePolynomialFunction2(), _oldY(0), _xCoeffs(0) {} private: friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("fn2", boost::serialization::base_object >(*this)); ar & make_nvp("yCoeffs", this->_xCoeffs); // sets size of _xCoeffs; name is historical } }; /** * @brief 1-dimensional weighted sum of Chebyshev polynomials of the first kind. * * f(x) = c0 T0(x') + c1 T1(x') + c2 T2(x') + ... * = c0 + c1 T1(x') + c2 T2(x') + ... * where: * * Tn(x) is the nth Chebyshev function of the first kind: * T0(x) = 1 * T1(x) = 2 * Tn+1(x) = 2xTn(x) + Tn-1(x) * * x' is x offset and scaled to range [-1, 1] as x ranges over [minX, maxX] * * The function argument must be in the range [minX, maxX]. * * @ingroup afw */ template class Chebyshev1Function1: public Function1 { public: typedef typename Function1::Ptr Function1Ptr; /** * @brief Construct a Chebyshev polynomial of specified order and range. * * The parameters are initialized to zero. */ explicit Chebyshev1Function1( unsigned int order, ///< order of polynomial (0 for constant) double minX = -1, ///< minimum allowed x double maxX = 1) ///< maximum allowed x : Function1(order + 1) { _initialize(minX, maxX); } /** * @brief Construct a Chebyshev polynomial with specified parameters and range. * * The order of the polynomial is set to the length of the params vector. *
    693 3771b5eb - * @throw lsst::pex::exceptions::InvalidParameterException if params is empty
    ? ^^^^^^ ^
    693 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if params is empty
    ? ^^ ^ */ explicit Chebyshev1Function1( std::vector params, ///< polynomial coefficients double minX = -1, ///< minimum allowed x double maxX = 1) ///< maximum allowed x : Function1(params) { if (params.size() < 1) {
    703 3771b5eb - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException,
    ? ^^^^^^ ^
    703 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
    ? ^^ ^ "Chebyshev1Function1 called with empty vector"); } _initialize(minX, maxX); } virtual ~Chebyshev1Function1() {} virtual Function1Ptr clone() const { return Function1Ptr(new Chebyshev1Function1(this->_params, _minX, _maxX)); } /** * @brief Get minimum allowed x */ double getMinX() const { return _minX; }; /** * @brief Get maximum allowed x */ double getMaxX() const { return _maxX; }; /** * @brief Get the polynomial order */ unsigned int getOrder() const { return this->getNParameters() - 1; }; virtual bool isLinearCombination() const { return true; }; virtual ReturnT operator() (double x) const { double xPrime = (x + _offset) * _scale; // Clenshaw function for solving the Chebyshev polynomial // Non-recursive version from Kresimir Cosic int const order = _order; if (order == 0) { return this->_params[0]; } else if (order == 1) { return this->_params[0] + (this->_params[1] * xPrime); } double cshPrev = this->_params[order]; double csh = (2 * xPrime * this->_params[order]) + this->_params[order-1]; for (int i = order - 2; i > 0; --i) { double cshNext = (2 * xPrime * csh) + this->_params[i] - cshPrev; cshPrev = csh; csh = cshNext; } return (xPrime * csh) + this->_params[0] - cshPrev; } virtual std::string toString(std::string const& prefix) const { std::ostringstream os; os << "Chebyshev1Function1 [" << _minX << ", " << _maxX << "]: "; os << Function1::toString(prefix); return os.str(); } private: double _minX; ///< minimum allowed x double _maxX; ///< maximum allowed x double _scale; ///< x' = (x + _offset) * _scale double _offset; ///< x' = (x + _offset) * _scale unsigned int _order; ///< polynomial order /** * @brief initialize private constants */ void _initialize(double minX, double maxX) { _minX = minX; _maxX = maxX; _scale = 2.0 / (_maxX - _minX); _offset = -(_minX + _maxX) * 0.5; _order = this->getNParameters() - 1; } protected: /* Default constructor: intended only for serialization */ explicit Chebyshev1Function1() : Function1(1), _minX(0.0), _maxX(0.0), _scale(1.0), _offset(0.0), _order(0) {} private: friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const) { ar & make_nvp("fn1", boost::serialization::base_object >(*this)); ar & make_nvp("minX", this->_minX); ar & make_nvp("minX", this->_minX); ar & make_nvp("maxX", this->_maxX); ar & make_nvp("scale", this->_scale); ar & make_nvp("offset", this->_offset); ar & make_nvp("maxInd", this->_order); } }; /** * @brief 2-dimensional weighted sum of Chebyshev polynomials of the first kind. * * f(x,y) = c0 T0(x') T0(y') # order 0 * + c1 T1(x') T0(y') + c2 T0(x') T1(y') # order 1 * + c3 T2(x') T0(y') + c4 T1(x') T1(y') + c5 T0(x') T2(y') # order 2 * + ... * * = c0 # order 0 * + c1 T1(x') + c2 T1(y') # order 1 * + c3 T2(x') + c4 T1(x') T1(y') + c5 T2(y') # order 2 * + ... * * where: * * Tn(x) is the nth Chebyshev function of the first kind: * T0(x) = 1 * T1(x) = x * Tn+1(x) = 2xTn(x) + Tn-1(x) * * x' is x offset and scaled to range [-1, 1] as x ranges over [minX, maxX] * * y' is y offset and scaled to range [-1, 1] as y ranges over [minY, maxY] * * Return value is incorrect if function arguments are not in the range [minX, maxX], [minY, maxY]. * * @ingroup afw */ template class Chebyshev1Function2: public BasePolynomialFunction2 { public: typedef typename Function2::Ptr Function2Ptr; /** * @brief Construct a Chebyshev polynomial of specified order and range. * * The parameters are initialized to zero. */ explicit Chebyshev1Function2( unsigned int order, ///< order of polynomial (0 for constant) lsst::afw::geom::Box2D const &xyRange = lsst::afw::geom::Box2D(lsst::afw::geom::Point2D(-1.0, -1.0), lsst::afw::geom::Point2D( 1.0, 1.0))) ///< allowed x,y range : BasePolynomialFunction2(order), _oldYPrime(0), _yCheby(this->_order + 1), _xCoeffs(this->_order + 1) { _initialize(xyRange); } /** * @brief Construct a Chebyshev polynomial with specified parameters and range. * * The order of the polynomial is set to the length of the params vector. *
    851 13ce3777 - * @throw lsst::pex::exceptions::InvalidParameterException if params is empty
    ? ^^^^^^ ^
    851 21597d88 + * @throw lsst::pex::exceptions::InvalidParameterError if params is empty
    ? ^^ ^ */ explicit Chebyshev1Function2( std::vector params, ///< polynomial coefficients ///< length must be one of 1, 3, 6, 10, 15... lsst::afw::geom::Box2D const &xyRange = lsst::afw::geom::Box2D(lsst::afw::geom::Point2D(-1.0, -1.0), lsst::afw::geom::Point2D( 1.0, 1.0))) ///< allowed x,y range : BasePolynomialFunction2(params), _oldYPrime(0), _yCheby(this->_order + 1), _xCoeffs(this->_order + 1) { _initialize(xyRange); } virtual ~Chebyshev1Function2() {} virtual Function2Ptr clone() const { return Function2Ptr(new Chebyshev1Function2(this->_params, this->getXYRange())); } /** * @brief Get x,y range */ lsst::afw::geom::Box2D getXYRange() const { return lsst::afw::geom::Box2D(lsst::afw::geom::Point2D(_minX, _minY), lsst::afw::geom::Point2D(_maxX, _maxY)); }; /** * @brief Return a truncated copy of lower (or equal) order * * @throw lsst::pex::exceptions::InvalidParameter if truncated order > original order */ virtual Chebyshev1Function2 truncate( int truncOrder ///< order of truncated polynomial ) const { if (truncOrder > this->_order) { std::ostringstream os; os << "truncated order=" << truncOrder << " must be <= original order=" << this->_order;
    893 13ce3777 - throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterException, os.str());
    ? ^^^^^^ ^
    893 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError, os.str());
    ? ^^ ^ } int truncNParams = this->nParametersFromOrder(truncOrder); std::vector truncParams(this->_params.begin(), this->_params.begin() + truncNParams); return Chebyshev1Function2(truncParams, this->getXYRange()); } virtual ReturnT operator() (double x, double y) const { /* Solve as follows: - f(x,y) = Cy0 T0(y') + Cy1 T1(y') + Cy2 T2(y') + Cy3 T3(y') + ... where: Cy0 = P0 T0(x') + P1 T1(x') + P3 T2(x') + P6 T3(x') + ... Cy1 = P2 T0(x') + P4 T1(x') + P7 T2(x') + ... Cy2 = P5 T0(x') + P8 T1(x') + ... Cy3 = P9 T0(x') + ... ... First compute Tn(x') for each n Then use that to compute Cy0, Cy1, ...Cyn Then solve the y Chebyshev polynomial using the Clenshaw algorithm */ double const xPrime = (x + _offsetX) * _scaleX; double const yPrime = (y + _offsetY) * _scaleY; const int nParams = static_cast(this->_params.size()); const int order = this->_order; if (order == 0) { return this->_params[0]; // No caching required } if ((yPrime != _oldYPrime) || !this->_isCacheValid) { // update cached _yCheby and _xCoeffs _yCheby[0] = 1.0; _yCheby[1] = yPrime; for (int chebyInd = 2; chebyInd <= order; chebyInd++) { _yCheby[chebyInd] = (2 * yPrime * _yCheby[chebyInd-1]) - _yCheby[chebyInd-2]; } for (int coeffInd=0; coeffInd <= order; coeffInd++) { _xCoeffs[coeffInd] = 0; } for (int coeffInd = 0, endCoeffInd = 0, paramInd = 0; paramInd < nParams; paramInd++) { _xCoeffs[coeffInd] += this->_params[paramInd] * _yCheby[endCoeffInd]; --coeffInd; ++endCoeffInd; if (coeffInd < 0) { coeffInd = endCoeffInd; endCoeffInd = 0; } } _oldYPrime = yPrime; this->_isCacheValid = true; } // Clenshaw function for solving the Chebyshev polynomial // Non-recursive version from Kresimir Cosic if (order == 1) { return _xCoeffs[0] + (_xCoeffs[1] * xPrime); } double cshPrev = _xCoeffs[order]; double csh = (2 * xPrime * _xCoeffs[order]) + _xCoeffs[order-1]; for (int i = order - 2; i > 0; --i) { double cshNext = (2 * xPrime * csh) + _xCoeffs[i] - cshPrev; cshPrev = csh; csh = cshNext; } return (xPrime * csh) + _xCoeffs[0] - cshPrev; } virtual std::string toString(std::string const& prefix) const { std::ostringstream os; os << "Chebyshev1Function2 ["; os << this->_order << ", " << this->getXYRange() << "]"; os << Function2::toString(prefix); return os.str(); } virtual bool isPersistable() const { return true; } protected: virtual std::string getPersistenceName() const; virtual void write(afw::table::io::OutputArchiveHandle & handle) const; private: mutable double _oldYPrime; mutable std::vector _yCheby; ///< working vector: value of Tn(y') mutable std::vector _xCoeffs; ///< working vector: transformed coeffs of x polynomial double _minX; ///< minimum allowed x double _minY; ///< minimum allowed y double _maxX; ///< maximum allowed x double _maxY; ///< maximum allowed y double _scaleX; ///< x' = (x + _offsetX) * _scaleX double _scaleY; ///< y' = (y + _offsetY) * _scaleY double _offsetX; ///< x' = (x + _offsetX) * _scaleX double _offsetY; ///< y' = (y + _offsetY) * _scaleY /** * @brief initialize private constants */ void _initialize(lsst::afw::geom::Box2D const &xyRange) { _minX = xyRange.getMinX(); _minY = xyRange.getMinY(); _maxX = xyRange.getMaxX(); _maxY = xyRange.getMaxY(); _scaleX = 2.0 / (_maxX - _minX); _scaleY = 2.0 / (_maxY - _minY); _offsetX = -(_minX + _maxX) * 0.5; _offsetY = -(_minY + _maxY) * 0.5; } protected: /* Default constructor: intended only for serialization */ explicit Chebyshev1Function2() : BasePolynomialFunction2(), _oldYPrime(0), _yCheby(0), _xCoeffs(0), _minX(0.0), _minY(0.0), _maxX(0.0), _maxY(0.0), _scaleX(1.0), _scaleY(1.0), _offsetX(0.0), _offsetY(0.0) {} private: friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("fn2", boost::serialization::base_object >(*this)); ar & make_nvp("minX", this->_minX); ar & make_nvp("minY", this->_minY); ar & make_nvp("maxX", this->_maxX); ar & make_nvp("maxY", this->_maxY); ar & make_nvp("scaleX", this->_scaleX); ar & make_nvp("scaleY", this->_scaleY); ar & make_nvp("offsetX", this->_offsetX); ar & make_nvp("offsetY", this->_offsetY); ar & make_nvp("xCheby", this->_yCheby); // sets size of _yCheby; name is historical _xCoeffs.resize(_yCheby.size()); } }; /** * @brief 1-dimensional Lanczos function * * f(x) = sinc(pi x') sinc(pi x' / n) * where x' = x - xOffset * and coefficient c0 = xOffset * * Warning: the Lanczos function is sometimes forced to 0 if |x'| > n * but this implementation does not perform that truncation so as to improve Lanczos kernels. * * @ingroup afw */ template class LanczosFunction1: public Function1 { public: typedef typename Function1::Ptr Function1Ptr; /** * @brief Construct a Lanczos function of specified order and x,y offset. */ explicit LanczosFunction1( unsigned int n, ///< order of Lanczos function double xOffset = 0.0) ///< x offset : Function1(1), _invN(1.0/static_cast(n)) { this->_params[0] = xOffset; } virtual ~LanczosFunction1() {} virtual Function1Ptr clone() const { return Function1Ptr(new LanczosFunction1(this->getOrder(), this->_params[0])); } virtual ReturnT operator() (double x) const { double xArg1 = (x - this->_params[0]) * lsst::afw::geom::PI; double xArg2 = xArg1 * _invN; if (std::fabs(xArg1) > 1.0e-5) { return static_cast(std::sin(xArg1) * std::sin(xArg2) / (xArg1 * xArg2)); } else { return static_cast(1); } } /** * @brief Get the order of the Lanczos function */ unsigned int getOrder() const { return static_cast(0.5 + (1.0 / _invN)); }; virtual std::string toString(std::string const& prefix) const { std::ostringstream os; os << "LanczosFunction1 [" << this->getOrder() << "]: ";; os << Function1::toString(prefix); return os.str(); } private: double _invN; // == 1/n protected: /* Default constructor: intended only for serialization */ explicit LanczosFunction1() : Function1(1), _invN(1.0) {} private: friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("fn1", boost::serialization::base_object >(*this)); ar & make_nvp("invN", this->_invN); } }; /** * @brief 2-dimensional separable Lanczos function * * f(x, y) = sinc(pi x') sinc(pi x' / n) sinc(pi y') sinc(pi y' / n) * where x' = x - xOffset and y' = y - yOffset * and coefficients c0 = xOffset, c1 = yOffset * * Warning: the Lanczos function is sometimes forced to 0 if |x'| > n or |y'| > n * but this implementation does not perform that truncation so as to improve Lanczos kernels. * * @ingroup afw */ template class LanczosFunction2: public Function2 { public: typedef typename Function2::Ptr Function2Ptr; /** * @brief Construct a Lanczos function of specified order and x,y offset. */ explicit LanczosFunction2( unsigned int n, ///< order of Lanczos function double xOffset = 0.0, ///< x offset double yOffset = 0.0) ///< y offset : Function2(2), _invN(1.0 / static_cast(n)) { this->_params[0] = xOffset; this->_params[1] = yOffset; } virtual ~LanczosFunction2() {} virtual Function2Ptr clone() const { return Function2Ptr(new LanczosFunction2(this->getOrder(), this->_params[0], this->_params[1])); } virtual ReturnT operator() (double x, double y) const { double xArg1 = (x - this->_params[0]) * lsst::afw::geom::PI; double xArg2 = xArg1 * _invN; double xFunc = 1; if (std::fabs(xArg1) > 1.0e-5) { xFunc = std::sin(xArg1) * std::sin(xArg2) / (xArg1 * xArg2); } double yArg1 = (y - this->_params[1]) * lsst::afw::geom::PI; double yArg2 = yArg1 * _invN; double yFunc = 1; if (std::fabs(yArg1) > 1.0e-5) { yFunc = std::sin(yArg1) * std::sin(yArg2) / (yArg1 * yArg2); } return static_cast(xFunc * yFunc); } /** * @brief Get the order of Lanczos function */ unsigned int getOrder() const { return static_cast(0.5 + (1.0 / _invN)); }; virtual std::string toString(std::string const& prefix) const { std::ostringstream os; os << "LanczosFunction2 [" << this->getOrder() << "]: ";; os << Function2::toString(prefix); return os.str(); } private: double _invN; ///< 1/n protected: /* Default constructor: intended only for serialization */ explicit LanczosFunction2() : Function2(2), _invN(1.0) {} private: friend class boost::serialization::access; template void serialize(Archive& ar, unsigned int const version) { ar & make_nvp("fn2", boost::serialization::base_object >(*this)); ar & make_nvp("invN", this->_invN); } }; }}} // lsst::afw::math #endif // #ifndef LSST_AFW_MATH_FUNCTIONLIBRARY_H

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    13ce3777

    commit 13ce37775941ae0652c04391f59807edbe2db60f
    Author: rowen 
    Date:   Thu Apr 28 22:31:38 2011 +0000
    
        First draft.
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    examples/maskedImageFitsIo.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    #include 
                    
    
    26 a9aec7fc + #include "lsst/utils/Utils.h"
    27 a9aec7fc + #include "lsst/pex/exceptions.h"
    #include "lsst/afw/image/MaskedImage.h"
    28 5ec55fee - const std::string outFile("rwfitsOut");
    ? ^^^
    30 c3d8b5cf + const std::string outImagePath("rwfitsOut.fits");
    ? ^^^^ ++++ +++++ int main(int argc, char **argv) {
    32 8c6c0d93 - std::string file;
    ? - ^
    34 c3d8b5cf + std::string inImagePath;
    ? ^^^^^ ++++ if (argc == 2) {
    34 8c6c0d93 - file = std::string(argv[1]);
    ? - ^
    36 c3d8b5cf + inImagePath = std::string(argv[1]);
    ? ^^^^^ ++++ } else {
    36 8c6c0d93 - std::string afwdata = getenv("AFWDATA_DIR");
    37 8c6c0d93 - if (afwdata.empty()) {
    38 a9aec7fc + try {
    39 7cbb2bb9 + std::string dataDir = lsst::utils::getPackageDir("afwdata");
    40 c3d8b5cf + inImagePath = dataDir + "/data/small.fits";
    41 a9aec7fc + } catch (lsst::pex::exceptions::NotFoundError) {
    38 8c6c0d93 - std::cerr << "Usage: maskedImageFitsIO fitsFile" << std::endl;
    42 a9aec7fc + std::cerr << "Usage: maskedImageFitsIO [fitsFile]" << std::endl;
    ? + +
    43 a9aec7fc + std::cerr << "fitsFile is the path to a masked image" << std::endl;
    44 a9aec7fc + std::cerr << "\nError: setup afwdata or specify fitsFile.\n" << std::endl;
    39 8c6c0d93 - std::cerr << "fitsFile excludes the \"_img.fits\" suffix" << std::endl;
    40 8c6c0d93 - std::cerr << "AFWDATA_DIR not set. Provide fits file as argument or setup afwdata.\n"
    41 8c6c0d93 - << std::endl;
    exit(EXIT_FAILURE);
    43 8c6c0d93 - } else {
    44 8c6c0d93 - file = afwdata + "/small_MI";
    } }
    47 8c6c0d93 - std::cout << "Running with: " << file << std::endl;
    ? - ^
    48 c3d8b5cf + std::cout << "Running with: " << inImagePath << std::endl;
    ? ^^^^^ ++++
    49 8c6c0d93 - lsst::afw::image::MaskedImage mImage(file);
    ? - ^
    50 c3d8b5cf + lsst::afw::image::MaskedImage mImage(inImagePath);
    ? ^^^^^ ++++
    50 5ec55fee - mImage.writeFits(outFile);
    ? ^^^
    51 c3d8b5cf + mImage.writeFits(outImagePath);
    ? ^^^^ ++++
    52 c3d8b5cf + std::cout << "Wrote masked image: " << outImagePath << std::endl;
    }

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    5ec55fee

    commit 5ec55fee86d14901ff78b1b02efd8497ecdc7a49
    Author: rowen 
    Date:   Thu Jul 19 22:08:05 2007 +0000
    
        Added example maskedImageFitsIO.cc which shows the problem in ticket 93
    

    8c6c0d93

    commit 8c6c0d93eaf03478cc6379a16055c3ae6119aa35
    Author: bick 
    Date:   Fri Jan 8 21:49:43 2010 +0000
    
        #1113 Changed examples to default to afwdata fits files with no arguments.
    

    Commits in /Users/nate/repos_lsst/afw/

    7cbb2bb9

    commit 7cbb2bb9eb9c90ff2171954c7b9c0266caba4250
    Author: Russell Owen 
    Date:   Tue Apr 28 17:08:34 2015 -0700
    
        Use lsst.utils.getPackageDir instead of eups.productDir
    

    c3d8b5cf

    commit c3d8b5cfa7d0dd7a5c1204dc69b6d400a8c4e25c
    Author: Russell Owen 
    Date:   Tue Jul 8 14:45:38 2014 -0700
    
        Minor updates
        
        Change maskedImageFitsIO to print the name of the written image file.
        Unify variable names.
    

    a9aec7fc

    commit a9aec7fccf43933d582b64486479b2a10a861329
    Author: Russell Owen 
    Date:   Tue Jul 8 11:41:49 2014 -0700
    
        Replace misuse of getenv("AFWDATA_DIR") and fix outdated afwdata paths
        
        afw was full of examples of std::string = getenv("AFWDATA_DIR")
        followed by testing for a non-empty string. This doesn't work as expected
        because getenv returns NULL if the environment variable does not exist.
        Fixed by calling eups::productDir("afwdata") and explicitly checking
        for the exception raised if the product is not setup.
        
        Also, most of that code used outdated paths to files in AFWDATA.
        In a few cases files were being read that no longer exist,
        so minor additional changes were needed.
    

    Return to list

    include/lsst/afw/table/Flag.h

    Diff:

                    // -*- lsst-c++ -*-
                    #ifndef LSST_AFW_TABLE_Flag_h_INCLUDED
                    #define LSST_AFW_TABLE_Flag_h_INCLUDED
                    
                    #include "lsst/afw/table/misc.h"
                    #include "lsst/afw/table/FieldBase.h"
                    #include "lsst/afw/table/KeyBase.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    namespace detail {
                    
                    class Access;
                    
                    } // namespace detail
                    
                    /**
                     *  @brief Specialization for Flag fields.
                     *
                     *  Flag fields are handled specially in many places, because their keys have both an offset into an
                     *  integer element and the bit in that element; while other fields have one or more elements per field,
                     *  Flags have multiple fields per element.  This means we can't put all the custom code for Flag in
                     *  FieldBase, and because Flags have an explicit Key specialization, we put the record access
                     *  implementation in Key.
                     */
                    template <>
                    struct FieldBase {
                    
                        typedef bool Value;        ///< @brief the type returned by BaseRecord::get
                        typedef boost::int64_t Element;   ///< @brief the actual storage type (shared by multiple flag fields)
                    
                        /// @brief Return the number of subfield elements (always one for scalars).
                        int getElementCount() const { return 1; }
                    
                        /// @brief Return a string description of the field type.
                        static std::string getTypeString() { return "Flag"; }
                    
                    #ifndef SWIG_BUG_3465431_FIXED
                        // SWIG uses this template to define the interface for the other specializations.
                        // We can add other methods to full specializations using %extend, but we can't add
                        // constructors that way.
                        FieldBase() {}
                        FieldBase(int) {
                            throw LSST_EXCEPT(
    
    45 8c13afe2 - lsst::pex::exceptions::LogicErrorException,
    ? ---------
    45 21597d88 + lsst::pex::exceptions::LogicError,
    "Constructor disabled (it only appears to exist as a workaround for a SWIG bug)." ); } #endif protected: /// Defines how fields are printed. void stream(std::ostream & os) const {} }; /** * @brief A base class for Key that allows the underlying storage field to be extracted. */ template <> class KeyBase< Flag > { public: static bool const HAS_NAMED_SUBFIELDS = false; /// Return a key corresponding to the integer element where this field's bit is packed. Key::Element> getStorage() const; }; /** * @brief Key specialization for Flag. * * Flag fields are special; their keys need to contain not only the offset to the * integer element they share with other Flag fields, but also their position * in that shared field. * * Flag fields operate mostly like a bool field, but they do not support reference * access, and internally they are packed into an integer shared by multiple fields * so the marginal cost of each Flag field is only one bit. */ template <> class Key : public KeyBase, public FieldBase { public: //@{ /** * @brief Equality comparison. * * Two keys with different types are never equal. Keys with the same type * are equal if they point to the same location in a table, regardless of * what Schema they were constructed from (for instance, if a field has a * different name in one Schema than another, but is otherwise the same, * the two keys will be equal). */ template bool operator==(Key const & other) const { return false; } template bool operator!=(Key const & other) const { return true; } bool operator==(Key const & other) const { return _offset == other._offset && _bit == other._bit; } bool operator!=(Key const & other) const { return !this->operator==(other); } //@} /// @brief Return the offset in bytes of the integer element that holds this field's bit. int getOffset() const { return _offset; } /// @brief The index of this field's bit within the integer it shares with other Flag fields. int getBit() const { return _bit; } /** * @brief Return true if the key was initialized to valid offset. * * This does not guarantee that a key is valid with any particular schema, or even * that any schemas still exist in which this key is valid. * * A key that is default constructed will always be invalid. */ bool isValid() const { return _offset >= 0; } /** * @brief Default construct a field. * * The new field will be invalid until a valid Key is assigned to it. */ Key() : FieldBase(), _offset(-1), _bit(0) {} /// Stringification. inline friend std::ostream & operator<<(std::ostream & os, Key const & key) { return os << "Key['" << Key::getTypeString() << "'](offset=" << key.getOffset() << ", bit=" << key.getBit() << ")"; } private: friend class detail::Access; friend class BaseRecord; /// Used to implement RecordBase::get. Value getValue(Element const * p, ndarray::Manager::Ptr const &) const { return (*p) & (Element(1) << _bit); } /// Used to implement RecordBase::set. void setValue(Element * p, ndarray::Manager::Ptr const &, Value v) const { if (v) { *p |= (Element(1) << _bit); } else { *p &= ~(Element(1) << _bit); } } explicit Key(int offset, int bit) : _offset(offset), _bit(bit) {} int _offset; int _bit; }; }}} // namespace lsst::afw::table #endif // !LSST_AFW_TABLE_Flag_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    8c13afe2

    commit 8c13afe20104ffb237b8dc26aea8dcbec6a346e0
    Author: Jim Bosch 
    Date:   Thu Jan 5 16:02:54 2012 -0500
    
        cleaned up Schema stringification, added tests for Schema introspection
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    tests/statisticsOverloads.py

    Diff:

    1 823db3e8 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Statistics Run with: ./statisticsOverloads.py or python >>> import statisticsOverloads; statisticsOverloads.run() """ import unittest import lsst.utils.tests as utilsTests import lsst.pex.exceptions import lsst.afw.image as afwImage import lsst.afw.geom as afwGeom import lsst.afw.math as afwMath try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class StatisticsTestCase(unittest.TestCase): """A test case to check all overloaded makeStatistics() factories for Statistics""" def setUp(self): self.val = 10 self.nRow, self.nCol = 100, 200 self.sctrl = afwMath.StatisticsControl() # Integers self.mimgI = afwImage.MaskedImageI(afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgI.set(self.val, 0x0, self.val) self.imgI = afwImage.ImageI(afwGeom.Extent2I(self.nRow, self.nCol), self.val) self.vecI = afwMath.vectorI(self.nRow*self.nCol, self.val) # floats self.mimgF = afwImage.MaskedImageF(afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgF.set(self.val, 0x0, self.val) self.imgF = afwImage.ImageF(afwGeom.Extent2I(self.nRow, self.nCol), self.val) self.vecF = afwMath.vectorF(self.nRow*self.nCol, self.val) # doubles self.mimgD = afwImage.MaskedImageD(afwGeom.Extent2I(self.nRow, self.nCol)) self.mimgD.set(self.val, 0x0, self.val) self.imgD = afwImage.ImageD(afwGeom.Extent2I(self.nRow, self.nCol), self.val) self.vecD = afwMath.vectorD(self.nRow*self.nCol, self.val) self.imgList = [self.imgI, self.imgF, self.imgD] self.mimgList = [self.mimgI, self.mimgF, self.mimgD] self.vecList = [self.vecI, self.vecF, self.vecD] def tearDown(self): del self.mimgI; del self.mimgF; del self.mimgD del self.imgI; del self.imgF; del self.imgD del self.vecI; del self.vecF; del self.vecD del self.mimgList del self.imgList del self.vecList # The guts of the testing: grab a mean, stddev, and sum for whatever you're called with def compareMakeStatistics(self, image, n): stats = afwMath.makeStatistics(image, afwMath.NPOINT | afwMath.STDEV | afwMath.MEAN | afwMath.SUM, self.sctrl) self.assertEqual(stats.getValue(afwMath.NPOINT), n) self.assertEqual(stats.getValue(afwMath.NPOINT)*stats.getValue(afwMath.MEAN), stats.getValue(afwMath.SUM)) self.assertEqual(stats.getValue(afwMath.MEAN), self.val) self.assertEqual(stats.getValue(afwMath.STDEV), 0) # same as compareMakeStatistics but calls constructor directly (only for masked image) def compareStatistics(self, stats, n): self.assertEqual(stats.getValue(afwMath.NPOINT), n) self.assertEqual(stats.getValue(afwMath.NPOINT)*stats.getValue(afwMath.MEAN), stats.getValue(afwMath.SUM)) self.assertEqual(stats.getValue(afwMath.MEAN), self.val) self.assertEqual(stats.getValue(afwMath.STDEV), 0) # Test regular image::Image def testImage(self): for img in self.imgList: self.compareMakeStatistics(img, img.getWidth()*img.getHeight()) # Test the image::MaskedImages def testMaskedImage(self): for mimg in self.mimgList: self.compareMakeStatistics(mimg, mimg.getWidth()*mimg.getHeight()) # Test the std::vectors def testVector(self): for vec in self.vecList: self.compareMakeStatistics(vec, vec.size()) def testWeightedVector(self): """Test std::vector, but with weights""" sctrl = afwMath.StatisticsControl() nval = len(self.vecList[0]) weight = 10 weights = [i*weight/float(nval - 1) for i in range(nval)] for vec in self.vecList: stats = afwMath.makeStatistics(vec, weights, afwMath.NPOINT | afwMath.STDEV | afwMath.MEAN | afwMath.SUM, sctrl) self.assertAlmostEqual(0.5*weight*sum(vec)/stats.getValue(afwMath.SUM), 1.0) self.assertAlmostEqual(sum(vec)/vec.size(), stats.getValue(afwMath.MEAN)) # Try calling the Statistics constructor directly def testStatisticsConstructor(self): if False: statsI = afwMath.StatisticsI(self.mimgI.getImage(), self.mimgI.getMask(), afwMath.NPOINT | afwMath.STDEV | afwMath.MEAN | afwMath.SUM, self.sctrl) statsF = afwMath.StatisticsF(self.mimgF.getImage(), self.mimgF.getMask(), afwMath.NPOINT | afwMath.STDEV | afwMath.MEAN | afwMath.SUM, self.sctrl) statsD = afwMath.StatisticsD(self.mimgD.getImage(), self.mimgD.getMask(), afwMath.NPOINT | afwMath.STDEV | afwMath.MEAN | afwMath.SUM, self.sctrl) self.compareStatistics(statsI, self.mimgI.getWidth()*self.mimgI.getHeight()) self.compareStatistics(statsF, self.mimgF.getWidth()*self.mimgF.getHeight()) self.compareStatistics(statsD, self.mimgD.getWidth()*self.mimgD.getHeight()) # Test the Mask specialization def testMask(self): mask = afwImage.MaskU(afwGeom.Extent2I(10, 10)) mask.set(0x0) mask.set(1, 1, 0x10) mask.set(3, 1, 0x08) mask.set(5, 4, 0x08) mask.set(4, 5, 0x02) stats = afwMath.makeStatistics(mask, afwMath.SUM | afwMath.NPOINT) self.assertEqual(mask.getWidth()*mask.getHeight(), stats.getValue(afwMath.NPOINT)) self.assertEqual(0x1a, stats.getValue(afwMath.SUM)) def tst(): stats = afwMath.makeStatistics(mask, afwMath.MEAN)
    174 823db3e8 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException, tst)
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    175 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError, tst)
    ? ^^ ^ ^^ ^ #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(StatisticsTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    823db3e8

    commit 823db3e850744057f4912c72b9e4c453a9b6e633
    Author: bick 
    Date:   Tue Sep 29 20:09:10 2009 +0000
    
        Added tests to verify overleaded factories, NaN being ignored, and Masked pixels being ignored.
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    Return to list

    tests/statistics.py

    Diff:

    1 f8edfe90 - #!/usr/bin/env python
    1 b80fe1d3 + #!/usr/bin/env python2
    ? +
    2 b80fe1d3 + from __future__ import absolute_import, division
    # # LSST Data Management System # Copyright 2008, 2009, 2010 LSST Corporation. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # """ Tests for Statistics Run with: ./statistics.py or python >>> import statistics; statistics.run() """ import sys import math import os import numpy as np import unittest import lsst.utils.tests as utilsTests import lsst.pex.exceptions import lsst.afw.image.imageLib as afwImage import lsst.afw.math as afwMath import lsst.afw.geom as afwGeom import lsst.afw.display.ds9 as ds9 try: type(display) except NameError: display = False #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- class StatisticsTestCase(unittest.TestCase): """A test case for Statistics""" def setUp(self): self.val = 10 self.image = afwImage.ImageF(afwGeom.Extent2I(100, 200)) self.image.set(self.val) def tearDown(self): del self.image def testDefaultGet(self): """Test that we can get a single statistic without specifying it""" stats = afwMath.makeStatistics(self.image, afwMath.MEDIAN) self.assertEqual(stats.getValue(), stats.getValue(afwMath.MEDIAN)) self.assertEqual(stats.getResult()[0], stats.getResult(afwMath.MEDIAN)[0]) # stats = afwMath.makeStatistics(self.image, afwMath.MEDIAN | afwMath.ERRORS) self.assertEqual(stats.getValue(), stats.getValue(afwMath.MEDIAN)) self.assertEqual(stats.getResult(), stats.getResult(afwMath.MEDIAN)) self.assertEqual(stats.getError(), stats.getError(afwMath.MEDIAN)) def tst(): stats.getValue() stats = afwMath.makeStatistics(self.image, afwMath.MEDIAN | afwMath.MEAN)
    81 a716b827 - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException, tst)
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    82 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError, tst)
    ? ^^ ^ ^^ ^ def testStats1(self): stats = afwMath.makeStatistics(self.image, afwMath.NPOINT | afwMath.STDEV | afwMath.MEAN | afwMath.SUM) self.assertEqual(stats.getValue(afwMath.NPOINT), self.image.getWidth()*self.image.getHeight()) self.assertEqual(stats.getValue(afwMath.NPOINT)*stats.getValue(afwMath.MEAN), stats.getValue(afwMath.SUM)) self.assertEqual(stats.getValue(afwMath.MEAN), self.val) self.assertTrue(np.isnan(stats.getError(afwMath.MEAN))) # didn't ask for error, so it's a NaN self.assertEqual(stats.getValue(afwMath.STDEV), 0) def testStats2(self): stats = afwMath.makeStatistics(self.image, afwMath.STDEV | afwMath.MEAN | afwMath.ERRORS) mean = stats.getResult(afwMath.MEAN) sd = stats.getValue(afwMath.STDEV) self.assertEqual(mean[0], self.image.get(0, 0)) self.assertEqual(mean[1], sd/math.sqrt(self.image.getWidth()*self.image.getHeight())) def testStats3(self): stats = afwMath.makeStatistics(self.image, afwMath.NPOINT) def getMean(): stats.getValue(afwMath.MEAN)
    108 3771b5eb - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException, getMean)
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    109 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError, getMean)
    ? ^^ ^ ^^ ^ def testStatsZebra(self): """Add 1 to every other row""" image2 = self.image.Factory(self.image, True) # # Add 1 to every other row, so the variance is 1/4 # self.assertEqual(image2.getHeight()%2, 0) width = image2.getWidth() for y in range(1, image2.getHeight(), 2): sim = image2.Factory(image2, afwGeom.Box2I(afwGeom.Point2I(0, y), afwGeom.Extent2I(width, 1)), afwImage.LOCAL) sim += 1 if display: ds9.mtv(self.image, frame = 0) ds9.mtv(image2, frame = 1) stats = afwMath.makeStatistics(image2, afwMath.NPOINT | afwMath.STDEV | afwMath.MEAN | afwMath.ERRORS) mean = stats.getResult(afwMath.MEAN) n = stats.getValue(afwMath.NPOINT) sd = stats.getValue(afwMath.STDEV) self.assertEqual(mean[0], image2.get(0, 0) + 0.5) self.assertEqual(sd, 1/math.sqrt(4.0)*math.sqrt(n/(n - 1))) self.assertAlmostEqual(mean[1], sd/math.sqrt(image2.getWidth()*image2.getHeight()), 10) meanSquare = afwMath.makeStatistics(image2, afwMath.MEANSQUARE).getValue() self.assertEqual(meanSquare, 0.5*(image2.get(0, 0)**2 + image2.get(0, 1)**2)) def testStatsStdevclip(self): """Test STDEVCLIP; cf. #611""" image2 = self.image.Factory(self.image, True) stats = afwMath.makeStatistics(image2, afwMath.STDEVCLIP | afwMath.NPOINT | afwMath.SUM) self.assertEqual(stats.getValue(afwMath.STDEVCLIP), 0) # # Check we get the correct sum even when clipping # self.assertEqual(stats.getValue(afwMath.NPOINT)* afwMath.makeStatistics(image2, afwMath.MEAN).getValue(), stats.getValue(afwMath.SUM)) def testMedian(self): """Test the median code""" stats = afwMath.makeStatistics(self.image, afwMath.MEDIAN) self.assertEqual(stats.getValue(afwMath.MEDIAN), self.val) values = [1.0, 2.0, 3.0, 2.0 ] self.assertEqual(afwMath.makeStatistics(values, afwMath.MEDIAN).getValue(), 2.0) def testIqrange(self): """Test the inter-quartile range""" stats = afwMath.makeStatistics(self.image, afwMath.IQRANGE) self.assertEqual(stats.getValue(afwMath.IQRANGE), 0) def testMeanClip(self): """Test the 3-sigma clipped mean""" stats = afwMath.makeStatistics(self.image, afwMath.MEANCLIP) self.assertEqual(stats.getValue(afwMath.MEANCLIP), self.val) def testStdevClip(self): """Test the 3-sigma clipped standard deviation""" stats = afwMath.makeStatistics(self.image, afwMath.STDEVCLIP) self.assertEqual(stats.getValue(afwMath.STDEVCLIP), 0) def testVarianceClip(self): """Test the 3-sigma clipped variance""" stats = afwMath.makeStatistics(self.image, afwMath.VARIANCECLIP) self.assertEqual(stats.getValue(afwMath.VARIANCECLIP), 0)
    183 6e8b043b + def _testBadValue(self, badVal):
    184 6e8b043b + """Test that we can handle an instance of `badVal` in the data correctly"""
    182 55d3d121 - def testMaxWithNan(self):
    183 4b1b5190 - """Test that we can handle NaNs correctly"""
    184 4b1b5190 -
    x, y = 10, 10 for useImage in [True, False]: if useImage: self.image = afwImage.ImageF(100, 100) self.image.set(self.val)
    190 4b1b5190 - self.image.set(x, y, np.nan)
    ? ^^^^ ^
    190 6e8b043b + self.image.set(x, y, badVal)
    ? ^ ^^^^ else: self.image = afwImage.MaskedImageF(100, 100) self.image.set(self.val, 0x0, 1.0)
    194 4b1b5190 - self.image.set(x, y, (np.nan, 0x0, 1.0))
    ? ^^^^ ^
    194 6e8b043b + self.image.set(x, y, (badVal, 0x0, 1.0))
    ? ^ ^^^^ self.assertEqual(afwMath.makeStatistics(self.image, afwMath.MAX).getValue(), self.val) self.assertEqual(afwMath.makeStatistics(self.image, afwMath.MEAN).getValue(), self.val) sctrl = afwMath.StatisticsControl() sctrl.setNanSafe(False) self.assertFalse(np.isfinite(afwMath.makeStatistics(self.image, afwMath.MAX, sctrl).getValue())) self.assertFalse(np.isfinite(afwMath.makeStatistics(self.image, afwMath.MEAN, sctrl).getValue()))
    204 55d3d121 +
    205 6e8b043b + def testMaxWithNan(self):
    206 6e8b043b + """Test that we can handle NaNs correctly"""
    207 6e8b043b + self._testBadValue(np.nan)
    208 6e8b043b +
    209 6e8b043b + def testMaxWithInf(self):
    210 6e8b043b + """Test that we can handle infinities correctly"""
    211 6e8b043b + self._testBadValue(np.inf)
    def testSampleImageStats(self): """ Compare our results to known values in test data """ imgfiles = [] imgfiles.append("v1_i1_g_m400_s20_f.fits") imgfiles.append("v1_i1_g_m400_s20_u16.fits") imgfiles.append("v1_i2_g_m400_s20_f.fits") imgfiles.append("v1_i2_g_m400_s20_u16.fits") imgfiles.append("v2_i1_p_m9_f.fits") imgfiles.append("v2_i1_p_m9_u16.fits") imgfiles.append("v2_i2_p_m9_f.fits") imgfiles.append("v2_i2_p_m9_u16.fits") afwdataDir = os.getenv("AFWDATA_DIR") if not afwdataDir: print >> sys.stderr, "Skipping tests as afwdata is not setup" return for imgfile in imgfiles: imgPath = os.path.join(afwdataDir, "Statistics", imgfile) # get the image and header dimg = afwImage.DecoratedImageF(imgPath) fitsHdr = dimg.getMetadata() # get the true values of the mean and stdev trueMean = fitsHdr.getAsDouble("MEANCOMP") trueStdev = fitsHdr.getAsDouble("SIGCOMP") # measure the mean and stdev with the Statistics class img = dimg.getImage() statobj = afwMath.makeStatistics(img, afwMath.MEAN | afwMath.STDEV) mean = statobj.getValue(afwMath.MEAN) stdev = statobj.getValue(afwMath.STDEV) # print trueMean, mean, trueStdev, stdev self.assertAlmostEqual(mean, trueMean, 8) self.assertAlmostEqual(stdev, trueStdev, 8) def testStatisticsRamp(self): """ Tests Statistics on a 'ramp' (image with constant gradient) """ nx = 101 ny = 64 img = afwImage.ImageF(afwGeom.Extent2I(nx, ny)) z0 = 10.0 dzdx = 1.0
    256 effee8a5 - mean = z0 + (nx/2)*dzdx
    264 b80fe1d3 + mean = z0 + (nx//2)*dzdx
    ? + stdev = 0.0 for y in range(ny): for x in range(nx): z = z0 + dzdx*x img.set(x, y, z) stdev += (z - mean)*(z - mean) stdev = math.sqrt(stdev/(nx*ny - 1)) stats = afwMath.makeStatistics(img, afwMath.NPOINT | afwMath.STDEV | afwMath.MEAN) testmean = stats.getValue(afwMath.MEAN) teststdev = stats.getValue(afwMath.STDEV) self.assertEqual(stats.getValue(afwMath.NPOINT), nx*ny) self.assertEqual(testmean, mean) self.assertAlmostEqual(teststdev, stdev) stats = afwMath.makeStatistics(img, afwMath.STDEV | afwMath.MEAN | afwMath.ERRORS) mean, meanErr = stats.getResult(afwMath.MEAN) sd = stats.getValue(afwMath.STDEV)
    278 effee8a5 - self.assertEqual(mean, img.get(nx/2, ny/2))
    286 b80fe1d3 + self.assertEqual(mean, img.get(nx//2, ny//2))
    ? + + self.assertEqual(meanErr, sd/math.sqrt(img.getWidth()*img.getHeight())) # =============================================================================== # sjb code for percentiles and clipped stats stats = afwMath.makeStatistics(img, afwMath.MEDIAN) self.assertEqual(z0 + dzdx*(nx - 1)/2.0, stats.getValue(afwMath.MEDIAN)) stats = afwMath.makeStatistics(img, afwMath.IQRANGE) self.assertEqual(dzdx*(nx - 1)/2.0, stats.getValue(afwMath.IQRANGE)) stats = afwMath.makeStatistics(img, afwMath.MEANCLIP) self.assertEqual(z0 + dzdx*(nx - 1)/2.0, stats.getValue(afwMath.MEANCLIP)) def testMask(self): mask = afwImage.MaskU(afwGeom.Extent2I(10, 10)) mask.set(0x0) mask.set(1, 1, 0x10) mask.set(3, 1, 0x08) mask.set(5, 4, 0x08) mask.set(4, 5, 0x02) stats = afwMath.makeStatistics(mask, afwMath.SUM | afwMath.NPOINT) self.assertEqual(mask.getWidth()*mask.getHeight(), stats.getValue(afwMath.NPOINT)) self.assertEqual(0x1a, stats.getValue(afwMath.SUM)) def tst(): stats = afwMath.makeStatistics(mask, afwMath.MEAN)
    309 2d8a5cfe - utilsTests.assertRaisesLsstCpp(self, lsst.pex.exceptions.InvalidParameterException, tst)
    ? ^^^ ^^^^^^ ------- ------ ^^^^^^ ^
    317 6fc1c3d1 + self.assertRaises(lsst.pex.exceptions.InvalidParameterError, tst)
    ? ^^ ^ ^^ ^ def testTicket1025(self): """ Ticket #1025 reported that the Statistics median was getting '3' as the median of [1,2,3,2] it was caused by an off-by-one error in the implementation """ # check the exact example in the ticket values = [1.0, 2.0, 3.0, 2.0] self.assertEqual(afwMath.makeStatistics(values, afwMath.MEDIAN).getValue(), 2) self.assertEqual(afwMath.makeStatistics(sorted(values), afwMath.MEDIAN).getValue(), 2) # check some other possible ways it could show up values = range(10) self.assertEqual(afwMath.makeStatistics(values, afwMath.MEDIAN).getValue(), 4.5) values = range(11) self.assertEqual(afwMath.makeStatistics(values, afwMath.MEDIAN).getValue(), 5.0) def testTicket1123(self): """ Ticket #1123 reported that the Statistics stack routine throws an exception when all pixels in a stack are masked. Returning a NaN pixel in the stack is preferred """ ctrl = afwMath.StatisticsControl() ctrl.setAndMask(~0x0) mimg = afwImage.MaskedImageF(afwGeom.Extent2I(10, 10)) mimg.set([self.val, 0x1, self.val]) # test the case with no valid pixels ... both mean and stdev should be nan stat = afwMath.makeStatistics(mimg, afwMath.MEAN | afwMath.STDEV, ctrl) mean = stat.getValue(afwMath.MEAN) stdev = stat.getValue(afwMath.STDEV) self.assertNotEqual(mean, mean) # NaN does not equal itself self.assertNotEqual(stdev, stdev) # NaN does not equal itself # test the case with one valid pixel ... mean is ok, but stdev should still be nan mimg.getMask().set(1, 1, 0x0) stat = afwMath.makeStatistics(mimg, afwMath.MEAN | afwMath.STDEV, ctrl) mean = stat.getValue(afwMath.MEAN) stdev = stat.getValue(afwMath.STDEV) self.assertEqual(mean, self.val) self.assertNotEqual(stdev, stdev) # NaN does not equal itself # test the case with two valid pixels ... both mean and stdev are ok mimg.getMask().set(1, 2, 0x0) stat = afwMath.makeStatistics(mimg, afwMath.MEAN | afwMath.STDEV, ctrl) mean = stat.getValue(afwMath.MEAN) stdev = stat.getValue(afwMath.STDEV) self.assertEqual(mean, self.val) self.assertEqual(stdev, 0.0) def testTicket1125(self): """Ticket 1125 reported that the clipped routines were aborting when called with no valid pixels. """ mimg = afwImage.MaskedImageF(afwGeom.Extent2I(10, 10)) mimg.set([self.val, 0x1, self.val]) ctrl = afwMath.StatisticsControl() ctrl.setAndMask(~0x0) # test the case with no valid pixels ... try MEANCLIP and STDEVCLIP stat = afwMath.makeStatistics(mimg, afwMath.MEANCLIP | afwMath.STDEVCLIP, ctrl) mean = stat.getValue(afwMath.MEANCLIP) stdev = stat.getValue(afwMath.STDEVCLIP) self.assertNotEqual(mean, mean) # NaN does not equal itself self.assertNotEqual(stdev, stdev) # NaN does not equal itself def testWeightedSum(self): ctrl = afwMath.StatisticsControl() mi = afwImage.MaskedImageF(afwGeom.Extent2I(10,10)) mi.getImage().set(1.0) mi.getVariance().set(0.1) stats = afwMath.makeStatistics(mi, afwMath.SUM, ctrl) self.assertEqual(stats.getValue(afwMath.SUM), 100.0) ctrl.setWeighted(True) weighted = afwMath.makeStatistics(mi, afwMath.SUM, ctrl) # precision at "4 places" as images are floats # ... variance = 0.1 is stored as 0.100000001 self.assertAlmostEqual(weighted.getValue(afwMath.SUM), 1000.0, 4) def testWeightedSum2(self): """Test using a weight image separate from the variance plane""" weight, mean = 0.1, 1.0 ctrl = afwMath.StatisticsControl() mi = afwImage.MaskedImageF(afwGeom.Extent2I(10,10)); npix = 10*10 mi.getImage().set(mean) mi.getVariance().set(np.nan) weights = afwImage.ImageF(mi.getDimensions()) weights.set(weight) stats = afwMath.makeStatistics(mi, afwMath.SUM, ctrl) self.assertEqual(stats.getValue(afwMath.SUM), mean*npix) weighted = afwMath.makeStatistics(mi, weights, afwMath.SUM, ctrl) # precision at "4 places" as images are floats # ... variance = 0.1 is stored as 0.100000001 self.assertAlmostEqual(weighted.getValue(afwMath.SUM), mean*npix*weight, 4) def testErrorsFromVariance(self): """Test that we can estimate the errors from the incoming variances""" weight, mean, variance = 0.1, 1.0, 10.0 ctrl = afwMath.StatisticsControl() mi = afwImage.MaskedImageF(afwGeom.Extent2I(10,10)); npix = 10*10 mi.getImage().set(mean) mi.getVariance().set(variance) weights = afwImage.ImageF(mi.getDimensions()) weights.set(weight) ctrl.setCalcErrorFromInputVariance(True) weighted = afwMath.makeStatistics(mi, weights, afwMath.MEAN | afwMath.MEANCLIP | afwMath.SUM | afwMath.ERRORS, ctrl) self.assertAlmostEqual(weighted.getValue(afwMath.SUM)/(npix*mean*weight), 1) self.assertAlmostEqual(weighted.getValue(afwMath.MEAN), mean) self.assertAlmostEqual(weighted.getError(afwMath.MEAN)**2, variance/npix) self.assertAlmostEqual(weighted.getError(afwMath.MEANCLIP)**2, variance/npix) def testMeanClip(self): """Verify that the 3-sigma clipped mean doesn't not return NaN for a single value.""" stats = afwMath.makeStatistics(self.image, afwMath.MEANCLIP) self.assertEqual(stats.getValue(afwMath.MEANCLIP), self.val) # this bug was caused by the iterative nature of the MEANCLIP. # With only one point, the sample variance returns NaN to avoid a divide by zero error # Thus, on the second iteration, the clip width (based on _variance) is NaN and corrupts # all further calculations. img = afwImage.ImageF(afwGeom.Extent2I(1, 1)) img.set(0) stats = afwMath.makeStatistics(img, afwMath.MEANCLIP) self.assertEqual(stats.getValue(), 0) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- def suite(): """Returns a suite containing all the test cases in this module.""" utilsTests.init() suites = [] suites += unittest.makeSuite(StatisticsTestCase) suites += unittest.makeSuite(utilsTests.MemoryTestCase) return unittest.TestSuite(suites) def run(shouldExit = False): """Run the tests""" utilsTests.run(suite(), shouldExit) if __name__ == "__main__": run(True)

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    a716b827

    commit a716b8278e46b783bd31b9781f12a51761041a1e
    Author: rhl 
    Date:   Wed Mar 4 17:58:23 2009 +0000
    
        Add footprintToBBoxList (#681).  As part of writing its test, make Statistics understand unsigned short images, and allow getValue() to return single requested statistic
    

    55d3d121

    commit 55d3d121c04b83ee3e079cbf31c34856cb1d1a5d
    Author: rhl 
    Date:   Thu Oct 27 23:03:50 2011 +0000
    
        Confirmed that NaNs get into MAX if NaN checking is disabled
    

    3771b5eb

    commit 3771b5eb018339a58ef8360f56bf5dafd4de771b
    Author: smm 
    Date:   Tue Jan 6 22:45:35 2009 +0000
    
        Merged revisions 6846,6871 via svnmerge from
        svn+ssh://svn.lsstcorp.org/DMS/afw/tickets/547
        
        ........
          r6846 | smm | 2008-12-22 19:41:18 -0800 (Mon, 22 Dec 2008) | 2 lines
        
          update afw to use new exception classes and PropertySet (#547)
        ........
          r6871 | rhl | 2009-01-03 06:50:10 -0800 (Sat, 03 Jan 2009) | 1 line
        
          findUnique isn't in PropertySet
        ........
    

    4b1b5190

    commit 4b1b5190150253550c148f5bd98bc2e00a2a9a67
    Author: rhl 
    Date:   Mon Oct 31 22:24:16 2011 +0000
    
        Added tests for handling NaN in images
    

    effee8a5

    commit effee8a5fd485349690f371bf8167dac9d6b3812
    Merge: a5867d5 762dfc9
    Author: bick 
    Date:   Sat Oct 31 21:59:27 2009 +0000
    
        #987 code and tests working.  Cleaned-up some of sjb's other afw code.
    

    2d8a5cfe

    commit 2d8a5cfe15ad5ab754d0b7dd5fa5746bf2f87587
    Author: rhl 
    Date:   Sun Mar 29 14:11:32 2009 +0000
    
        Specialize Statistics for U16 masks to calculate the | of all pixels as SUM (n.b. double, but 32-bit ints can be exactly represented as doubles)
    

    Commits in /Users/nate/repos_lsst/afw/

    b80fe1d3

    commit b80fe1d34f34256cffd4a92349a2a0fc5d44d9a3
    Author: Russell Owen 
    Date:   Mon Oct 27 18:01:15 2014 -0700
    
        Support from __future__ import division
        for classes such as Extension that support operator/ and/or operator/=
        and change unit tests to use it
    

    6e8b043b

    commit 6e8b043b597d4cf3616ba44da677a86e82961f5e
    Author: John Swinbank 
    Date:   Mon Apr 6 11:37:03 2015 -0400
    
        CheckFinite should check for Inf (as well as NaN).
        
        Addresses DM-2488.
    

    6fc1c3d1

    commit 6fc1c3d1a61a370d7ec035cb2a56948beb4fbf7f
    Author: Jim Bosch 
    Date:   Thu Jul 17 16:05:56 2014 -0400
    
        Adapt to changes in exception Python wrappers (DM-827)
    

    55d3d121

    commit 55d3d121c04b83ee3e079cbf31c34856cb1d1a5d
    Author: rhl 
    Date:   Thu Oct 27 23:03:50 2011 +0000
    
        Confirmed that NaNs get into MAX if NaN checking is disabled
    

    Return to list

    include/lsst/afw/math/MaskedVector.h

    Diff:

                    // -*- lsst-c++ -*-
                    
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #if !defined(LSST_AFW_MATH_MASKEDVECTOR_H)
                    #define LSST_AFW_MATH_MASKEDVECTOR_H
                    
                    #include "boost/shared_ptr.hpp"
                    #include "lsst/afw/image/Image.h"
                    #include "lsst/afw/image/Mask.h"
                    
                    namespace lsst {
                    namespace afw {
                    namespace math {
                    
                    template    
                    class MaskedVector : private lsst::afw::image::MaskedImage {    
                    public:
                        //typedef typename lsst::afw::image::Mask::MaskPlaneDict MaskPlaneDict;
                        typedef typename lsst::afw::image::MaskedImage::Pixel Pixel;
                        
                        explicit MaskedVector(int width=0) : //, MaskPlaneDict const& planeDict=MaskPlaneDict()) :
                            lsst::afw::image::MaskedImage(geom::Extent2I(width, 1)) {} //, planeDict) {}
                    
                        // Getters
                        /// Return a (Ptr to) the MaskedImage's %image
                        boost::shared_ptr > getVector(bool const noThrow=false) const {
                            if (!this->getImage() && !noThrow) {
    
    49 37817775 - throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeErrorException, "MaskedVector's Image is NULL");
    ? ---------
    49 21597d88 + throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "MaskedVector's Image is NULL");
    } boost::shared_ptr > imgcp(new std::vector(0)); for (int i_y = 0; i_y < this->getImage()->getHeight(); ++i_y) { for (typename lsst::afw::image::Image::x_iterator ptr = this->getImage()->row_begin(i_y); ptr != this->getImage()->row_end(i_y); ++ptr) { imgcp->push_back(*ptr); } } return imgcp; } // if we're asked for a single value return the image pixel //EntryT &operator[](int const i) { return (*lsst::afw::image::MaskedImage::getImage())(i, 0); } Pixel &operator[](int const i) { return Pixel(lsst::afw::image::MaskedImage::getImage()(i, 0), lsst::afw::image::MaskedImage::getMask()(i, 0), lsst::afw::image::MaskedImage::getVariance()(i, 0) ); } typename lsst::afw::image::MaskedImage::Image::Pixel &value(int const i) { return (*lsst::afw::image::MaskedImage::getImage())(i, 0); } typename lsst::afw::image::MaskedImage::Mask::Pixel &mask(int const i) { return (*lsst::afw::image::MaskedImage::getMask())(i, 0); } typename lsst::afw::image::MaskedImage::Variance::Pixel &variance(int const i) { return (*lsst::afw::image::MaskedImage::getVariance())(i, 0); } typename lsst::afw::image::MaskedImage::ImagePtr getImage() const { return lsst::afw::image::MaskedImage::getImage(); } typename lsst::afw::image::MaskedImage::MaskPtr getMask() const { return lsst::afw::image::MaskedImage::getMask(); } typename lsst::afw::image::MaskedImage::VariancePtr getVariance() const { return lsst::afw::image::MaskedImage::getVariance(); } //MaskedVector& operator=(Pixel const& rhs) { return lsst::afw::image::MaskedImage::operator=(rhs); } //MaskedVector& operator=(SinglePixel const& rhs) { return this->operator=(rhs); } // Make some std::vector methods int size() { return this->getWidth(0); } bool empty() { return this->getWidth(0) == 0; } class iterator : public lsst::afw::image::MaskedImage::x_iterator { public: #if 0 using typename lsst::afw::image::MaskedImage::x_iterator::mask; using typename lsst::afw::image::MaskedImage::x_iterator::variance; #endif iterator(typename lsst::afw::image::MaskedImage::Image::x_iterator im, typename lsst::afw::image::MaskedImage::Mask::x_iterator msk, typename lsst::afw::image::MaskedImage::Variance::x_iterator var) : lsst::afw::image::MaskedImage::x_iterator(im, msk, var) {} iterator(typename lsst::afw::image::MaskedImage::x_iterator ptr) : lsst::afw::image::MaskedImage::x_iterator(ptr) {} typename lsst::afw::image::MaskedImage::Image::Pixel &value() { return this->image(); } }; iterator begin() { return this->row_begin(0); } iterator end() { return this->row_end(0); } private: }; }}} #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    37817775

    commit 3781777568b9eba0fdfbcfbb0ec37b3c2c1dfe3c
    Author: bick 
    Date:   Tue Dec 15 04:08:30 2009 +0000
    
        framework in place for image stacking. ... buggy, doesn't compile.
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    include/lsst/afw/table/Simple.h

    Diff:

                    // -*- lsst-c++ -*-
                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010, 2011 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                    #ifndef AFW_TABLE_Simple_h_INCLUDED
                    #define AFW_TABLE_Simple_h_INCLUDED
                    
                    #include "lsst/afw/table/BaseRecord.h"
                    #include "lsst/afw/table/BaseTable.h"
                    #include "lsst/afw/table/IdFactory.h"
                    #include "lsst/afw/table/Catalog.h"
                    #include "lsst/afw/table/BaseColumnView.h"
                    #include "lsst/afw/table/SortedCatalog.h"
                    
                    namespace lsst { namespace afw { namespace table {
                    
                    class SimpleRecord;
                    class SimpleTable;
                    
                    /**
                     *  @brief Record class that must contain a unique ID field and a celestial coordinate field.
                     *
                     *  SimpleTable / SimpleRecord are intended to be the base class for records representing astronomical
                     *  objects.  In additional to the minimal schema and the convenience accessors it allows, a SimpleTable
                     *  may hold an IdFactory object that is used to assign unique IDs to new records.
                     */
                    class SimpleRecord : public BaseRecord {
                    public:
                    
                        typedef SimpleTable Table;
                        typedef ColumnViewT ColumnView;
                        typedef SortedCatalogT Catalog;
                        typedef SortedCatalogT ConstCatalog;
                    
                        CONST_PTR(SimpleTable) getTable() const {
                            return boost::static_pointer_cast(BaseRecord::getTable());
                        }
                    
                        //@{
                        /// @brief Convenience accessors for the keys in the minimal reference schema.
                        RecordId getId() const;
                        void setId(RecordId id);
                    
                        IcrsCoord getCoord() const;
                        void setCoord(IcrsCoord const & coord);
                        void setCoord(Coord const & coord);
                    
                        Angle getRa() const;
                        void setRa(Angle ra);
                    
                        Angle getDec() const;
                        void setDec(Angle dec);
                        //@}
                    
                    protected:
                    
                        SimpleRecord(PTR(SimpleTable) const & table);
                    
                    };
                    
                    /**
                     *  @brief Table class that must contain a unique ID field and a celestial coordinate field.
                     *
                     *  @copydetails SimpleRecord
                     */
                    class SimpleTable : public BaseTable {
                    public:
                    
                        typedef SimpleRecord Record;
                        typedef ColumnViewT ColumnView;
                        typedef SortedCatalogT Catalog;
                        typedef SortedCatalogT ConstCatalog;
                    
                        /**
                         *  @brief Construct a new table.
                         *
                         *  @param[in] schema            Schema that defines the fields, offsets, and record size for the table.
                         *  @param[in] idFactory         Factory class to generate record IDs when they are not explicitly given.
                         *                               If null, record IDs will default to zero.
                         *
                         *  Note that not passing an IdFactory at all will call the other override of make(), which will
                         *  set the ID factory to IdFactory::makeSimple().
                         */
                        static PTR(SimpleTable) make(Schema const & schema, PTR(IdFactory) const & idFactory);
                    
                        /**
                         *  @brief Construct a new table.
                         *
                         *  @param[in] schema            Schema that defines the fields, offsets, and record size for the table.
                         *
                         *  This overload sets the ID factory to IdFactory::makeSimple().
                         */
                        static PTR(SimpleTable) make(Schema const & schema) { return make(schema, IdFactory::makeSimple()); }
                    
                        /**
                         *  @brief Return a minimal schema for Simple tables and records.
                         *
                         *  The returned schema can and generally should be modified further,
                         *  but many operations on SimpleRecords will assume that at least the fields
                         *  provided by this routine are present.
                         */
    
    120 1e296bda - static Schema makeMinimalSchema() { return getMinimalSchema().schema; }
    120 af38dfb3 + static Schema makeMinimalSchema() {
    121 af38dfb3 + Schema r = getMinimalSchema().schema;
    122 af38dfb3 + r.disconnectAliases();
    123 af38dfb3 + return r;
    124 af38dfb3 + }
    /** * @brief Return true if the given schema is a valid SimpleTable schema. * * This will always be true if the given schema was originally constructed * using makeMinimalSchema(), and will rarely be true otherwise. */ static bool checkSchema(Schema const & other) { return other.contains(getMinimalSchema().schema); } /// @brief Return the object that generates IDs for the table (may be null). PTR(IdFactory) getIdFactory() { return _idFactory; } /// @brief Return the object that generates IDs for the table (may be null). CONST_PTR(IdFactory) getIdFactory() const { return _idFactory; } /// @brief Switch to a new IdFactory -- object that generates IDs for the table (may be null). void setIdFactory(PTR(IdFactory) f) { _idFactory = f; } //@{ /** * Get keys for standard fields shared by all references. * * These keys are used to implement getters and setters on SimpleRecord. */ /// @brief Key for the unique ID. static Key getIdKey() { return getMinimalSchema().id; } /// @brief Key for the celestial coordinates. static Key getCoordKey() { return getMinimalSchema().coord; } //@} /// @copydoc BaseTable::clone PTR(SimpleTable) clone() const { return boost::static_pointer_cast(_clone()); } /// @copydoc BaseTable::makeRecord PTR(SimpleRecord) makeRecord() { return boost::static_pointer_cast(_makeRecord()); } /// @copydoc BaseTable::copyRecord PTR(SimpleRecord) copyRecord(BaseRecord const & other) { return boost::static_pointer_cast(BaseTable::copyRecord(other)); } /// @copydoc BaseTable::copyRecord PTR(SimpleRecord) copyRecord(BaseRecord const & other, SchemaMapper const & mapper) { return boost::static_pointer_cast(BaseTable::copyRecord(other, mapper)); } protected: SimpleTable(Schema const & schema, PTR(IdFactory) const & idFactory); SimpleTable(SimpleTable const & other); private: // Struct that holds the minimal schema and the special keys we've added to it. struct MinimalSchema { Schema schema; Key id; Key coord; MinimalSchema(); }; // Return the singleton minimal schema. static MinimalSchema & getMinimalSchema(); friend class io::FitsWriter; // Return a writer object that knows how to save in FITS format. See also FitsWriter. virtual PTR(io::FitsWriter) makeFitsWriter(fits::Fits * fitsfile, int flags) const; PTR(IdFactory) _idFactory; // generates IDs for new records }; #ifndef SWIG inline RecordId SimpleRecord::getId() const { return get(SimpleTable::getIdKey()); } inline void SimpleRecord::setId(RecordId id) { set(SimpleTable::getIdKey(), id); } inline IcrsCoord SimpleRecord::getCoord() const { return get(SimpleTable::getCoordKey()); } inline void SimpleRecord::setCoord(IcrsCoord const & coord) { set(SimpleTable::getCoordKey(), coord); } inline void SimpleRecord::setCoord(Coord const & coord) { set(SimpleTable::getCoordKey(), coord); } inline Angle SimpleRecord::getRa() const { return get(SimpleTable::getCoordKey().getRa()); } inline void SimpleRecord::setRa(Angle ra) { set(SimpleTable::getCoordKey().getRa(), ra); } inline Angle SimpleRecord::getDec() const { return get(SimpleTable::getCoordKey().getDec()); } inline void SimpleRecord::setDec(Angle dec) { set(SimpleTable::getCoordKey().getDec(), dec); } #endif // !SWIG }}} // namespace lsst::afw::table #endif // !AFW_TABLE_Simple_h_INCLUDED

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    1e296bda

    commit 1e296bda917d1eeac92c30040cc4fd5a929344ad
    Author: Jim Bosch 
    Date:   Fri Feb 24 00:04:33 2012 -0500
    
        added SimpleTable/Record as (future) base class for all tables/records with IDs and celestial coordinates
    

    Commits in /Users/nate/repos_lsst/afw/

    af38dfb3

    commit af38dfb301ac07e9a48bfdcaf28140d730eb650c
    Author: Jim Bosch 
    Date:   Fri Nov 21 16:00:24 2014 -0600
    
        Disconnect aliases from minimal schemas
        
        Aliases are shared when Schemas are copied, which is usually desirable,
        but the makeMinimalSchema need to return new Schemas with a fresh set
        of aliases, or we end up with a lot of confusing behavior as one piece
        of code tries to set an alias and affects a completely different one,
        via a shared AliasMap they both got from the minimal schema.
    

    Return to list

    src/geom/Point.cc

    Diff:

                    /* 
                     * LSST Data Management System
                     * Copyright 2008, 2009, 2010 LSST Corporation.
                     * 
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     * 
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     * 
                     * You should have received a copy of the LSST License Statement and 
                     * the GNU General Public License along with this program.  If not, 
                     * see .
                     */
                     
                    #include 
                    
                    #include "lsst/afw/geom/Point.h"
                    
                    namespace geom = lsst::afw::geom;
                    
                    namespace lsst { namespace afw { namespace geom { namespace detail {
                    
                    template 
                    struct PointSpecialized {};
                    
                    template <>
                    struct PointSpecialized {
                        template 
                        static int convert(U scalar) {
                            return static_cast(std::floor(scalar + 0.5));
                        }
                    };
                    
                    template <>
                    struct PointSpecialized {
                        template 
                        static double convert(U scalar) {
                            return static_cast(scalar);
                        }
                    };
                    
                    }}}}
                    
                    template 
                    template 
                    geom::Point::Point(Point const & other) : Super() {
    
    55 6e365968 - for (register int n=0; n ? ---------
    55 51a67dff + for (int n=0; n this->_vector[n] = detail::PointSpecialized::template convert(other[n]); } } template template geom::Point::Point(Point const & other) : Super() {
    63 25e61ab4 - for (register int n=0; n<2; ++n) {
    ? ---------
    63 51a67dff + for (int n=0; n<2; ++n) {
    this->_vector[n] = detail::PointSpecialized::template convert(other[n]); } } template template geom::Point::Point(Point const & other) : Super() {
    71 25e61ab4 - for (register int n=0; n<3; ++n) {
    ? ---------
    71 51a67dff + for (int n=0; n<3; ++n) {
    this->_vector[n] = detail::PointSpecialized::template convert(other[n]); } } template geom::CoordinateExpr geom::PointBase::eq(Point const & other) const { CoordinateExpr r;
    79 6e365968 - for (register int n=0; n_vector[n] == other[n];
    ? ---------
    79 51a67dff + for (int n=0; n_vector[n] == other[n];
    return r; } template geom::CoordinateExpr geom::PointBase::ne(Point const & other) const { CoordinateExpr r;
    86 6e365968 - for (register int n=0; n_vector[n] != other[n];
    ? ---------
    86 51a67dff + for (int n=0; n_vector[n] != other[n];
    return r; } template geom::CoordinateExpr geom::PointBase::lt(Point const & other) const { CoordinateExpr r;
    93 7ccf406e - for (register int n=0; n_vector[n] < other[n];
    ? ---------
    93 51a67dff + for (int n=0; n_vector[n] < other[n];
    return r; } template geom::CoordinateExpr geom::PointBase::le(Point const & other) const { CoordinateExpr r;
    100 7ccf406e - for (register int n=0; n_vector[n] <= other[n];
    ? ---------
    100 51a67dff + for (int n=0; n_vector[n] <= other[n];
    return r; } template geom::CoordinateExpr geom::PointBase::gt(Point const & other) const { CoordinateExpr r;
    107 7ccf406e - for (register int n=0; n_vector[n] > other[n];
    ? ---------
    107 51a67dff + for (int n=0; n_vector[n] > other[n];
    return r; } template geom::CoordinateExpr geom::PointBase::ge(Point const & other) const { CoordinateExpr r;
    114 7ccf406e - for (register int n=0; n_vector[n] >= other[n];
    ? ---------
    114 51a67dff + for (int n=0; n_vector[n] >= other[n];
    return r; } #ifndef DOXYGEN template class geom::PointBase; template class geom::PointBase; template class geom::PointBase; template class geom::PointBase; template class geom::Point; template class geom::Point; template class geom::Point; template class geom::Point; template geom::Point::Point(geom::Point const &); template geom::Point::Point(geom::Point const &); template geom::Point::Point(geom::Point const &); template geom::Point::Point(geom::Point const &); #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    6e365968

    commit 6e3659683208d3284beba48d035e588c0aa10cf1
    Author: jbosch 
    Date:   Tue Dec 15 03:11:05 2009 +0000
    
        afw/892:
         - removed new Box objects (will implement in a new ticket)
         - fixed up documentation a bit
         - finished implementing Point and Extent
    

    7ccf406e

    commit 7ccf406eabf8ad8f018a7d66cf517ddeaa94d9e1
    Author: jbosch 
    Date:   Mon Dec 14 19:43:59 2009 +0000
    
        afw/892:
         - implementations for geom (all but Box now done)
         - fixed compilation errors in ellipses and tests for ellipses
         - merged updates from trunk in (fixed an obvious typo introduced in math::offsetImage by the merge)
    

    25e61ab4

    commit 25e61ab45c0496ecd27f1f616b886c77a0bdee97
    Author: jbosch 
    Date:   Sun Jan 30 22:19:38 2011 +0000
    
        afw #1556 - implemented ticket #1240: direct construction of Point and Extent
    

    Commits in /Users/nate/repos_lsst/afw/

    51a67dff

    commit 51a67dff1f2d5067d66ad025fe1efee37aeca339
    Author: Russell Owen 
    Date:   Tue Oct 14 12:50:44 2014 -0700
    
        Remove use of deprecated C++ keyword "register"
    

    Return to list

    src/gpu/detail/CudaQueryDevice.cc

    Diff:

                    // -*- LSST-C++ -*-
                    
                    /*
                     * LSST Data Management System
                     * Copyright 2008 - 2012 LSST Corporation.
                     *
                     * This product includes software developed by the
                     * LSST Project (http://www.lsst.org/).
                     *
                     * This program is free software: you can redistribute it and/or modify
                     * it under the terms of the GNU General Public License as published by
                     * the Free Software Foundation, either version 3 of the License, or
                     * (at your option) any later version.
                     *
                     * This program is distributed in the hope that it will be useful,
                     * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     * GNU General Public License for more details.
                     *
                     * You should have received a copy of the LSST License Statement and
                     * the GNU General Public License along with this program.  If not,
                     * see .
                     */
                    
                    /**
                     * @file
                     *
                     * @brief Functions to query the properties of currently selected GPU device
                     *
                     * Functions in this file are used to query GPU device.
                     *
                     * @author Kresimir Cosic
                     *
                     * @ingroup afw
                     */
                    
                    #include "lsst/pex/exceptions.h"
                    #include "lsst/afw/gpu/GpuExceptions.h"
                    #include "lsst/afw/gpu/detail/CudaQueryDevice.h"
                    
                    using namespace lsst::afw::gpu;
                    
                    #ifndef GPU_BUILD //if no GPU support, throw exceptions
                    
                    #include 
                    
                    namespace lsst {
                    namespace afw {
                    namespace gpu {
                    namespace detail {
                    
                    void PrintCudaDeviceInfo() {
                        printf("Afw not compiled with GPU support\n");
                    }
                    
                    int GetCudaCurDeviceId() {
    
    57 eb0bc04b - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    57 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } int GetCudaCurSMSharedMemorySize() {
    61 eb0bc04b - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    61 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } int GetCudaCurGlobalMemorySize() {
    65 eb0bc04b - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    65 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } int GetCudaCurSMRegisterCount() {
    69 eb0bc04b - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    69 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } int GetCudaCurSMCount() {
    73 eb0bc04b - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    73 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } bool GetCudaCurIsDoublePrecisionSupported() {
    77 eb0bc04b - throw LSST_EXCEPT(GpuRuntimeErrorException, "AFW not built with GPU support");
    ? ---------
    77 21597d88 + throw LSST_EXCEPT(GpuRuntimeError, "AFW not built with GPU support");
    } } } } } #else #include #include #include using namespace std; namespace lsst { namespace afw { namespace gpu { namespace detail { void PrintDeviceProperties(int id, cudaDeviceProp deviceProp) { printf("Name : %s |", deviceProp.name ); printf(" CUDA Capable SM %d.%d hardware, %d multiproc.\n", deviceProp.major, deviceProp.minor, deviceProp.multiProcessorCount); printf(" Clock rate: %6.2f GHz \t", deviceProp.clockRate / (1000.0 * 1000)); printf(" Memory on device: %6zu MiB\n", deviceProp.totalGlobalMem / (1 << 20) ); printf(" Multiprocessors: %6d\n", deviceProp.multiProcessorCount); printf(" Warp size: %6d \t", deviceProp.warpSize ); printf(" Shared memory:%6zu KiB\n", deviceProp.sharedMemPerBlock / (1 << 10) ); printf(" Registers: %6d \t", deviceProp.regsPerBlock ); printf(" Max threads: %6d \n", deviceProp.maxThreadsPerBlock ); printf(" Compute mode (device sharing) : "); if (deviceProp.computeMode == cudaComputeModeDefault) { printf("Default - shared between threads\n" ); } if (deviceProp.computeMode == cudaComputeModeExclusive) { printf("Exclusive - only one thread at a time\n" ); } if (deviceProp.computeMode == cudaComputeModeProhibited) { printf("Prohibited - cannot use this device\n" ); } printf(" Timeout enabled: %3s ", deviceProp.kernelExecTimeoutEnabled == 1 ? "Yes" : "No" ); printf(" Overlapped copying: %3s ", deviceProp.deviceOverlap == 1 ? "Yes" : "No" ); printf(" Intergrated on MB: %3s\n", deviceProp.integrated == 1 ? "Yes" : "No" ); printf(" Memory pitch: %12zu \t", deviceProp.memPitch ); printf(" Constant memory: %6zu kiB \n", deviceProp.totalConstMem / (1 << 10) ); } void PrintCudaErrorInfo(cudaError_t cudaError, const char* errorStr) { printf("\nSupplied error string: %s\n", errorStr); printf( "CUDA error : %d\n", cudaError); printf( "CUDA error string : %s\n", cudaGetErrorString(cudaError)); exit(0); } void PrintCudaDeviceInfo() { fflush(stdout); cudaError_t cudaError; int driverVersion; cudaError = cudaDriverGetVersion(&driverVersion); if (cudaError != cudaSuccess) PrintCudaErrorInfo(cudaError, "Could not get CUDA driver version"); printf("Driver ver.: %d.%d ", driverVersion / 1000, driverVersion % 1000); fflush(stdout); int runtimeVersion; cudaError = cudaRuntimeGetVersion(&runtimeVersion); if (cudaError != cudaSuccess) PrintCudaErrorInfo(cudaError, "Could not get CUDA runtime version"); printf("Runtime ver.: %d.%d ", runtimeVersion / 1000, runtimeVersion % 1000); fflush(stdout); //int preferredDeviceId = 0; int cudaDevicesN = 0; cudaError = cudaGetDeviceCount(&cudaDevicesN); if (cudaError != cudaSuccess) PrintCudaErrorInfo(cudaError, "Could not get CUDA device count"); printf("Device count: %d ", cudaDevicesN); fflush(stdout); if(cudaDevicesN < 1) { printf("Your system does not have a CUDA capable device\n"); exit(0); } int curDevId; cudaError = cudaGetDevice(&curDevId); if (cudaError != cudaSuccess) PrintCudaErrorInfo(cudaError, "Could not get CUDA device id"); printf("Info for device %d\n", curDevId); fflush(stdout); cudaDeviceProp deviceProp; cudaError = cudaGetDeviceProperties(&deviceProp, curDevId); if (cudaError != cudaSuccess) PrintCudaErrorInfo(cudaError, "Could not get CUDA device properties"); PrintDeviceProperties(curDevId, deviceProp); fflush(stdout); for (int i = 0; i < 79; i++) { printf("-"); } printf("\n"); fflush(stdout); } int GetCudaCurDeviceId() { int curDevId; cudaError_t cudaError = cudaGetDevice(&curDevId); if (cudaError != cudaSuccess) PrintCudaErrorInfo(cudaError, "GetCudaDeviceId> Could not get CUDA device id"); return curDevId; } int GetCudaCurSMSharedMemorySize() { int curDevId = GetCudaCurDeviceId(); cudaDeviceProp deviceProp; cudaError_t cudaError = cudaGetDeviceProperties(&deviceProp, curDevId); if (cudaError != cudaSuccess) PrintCudaErrorInfo(cudaError, "GetCudaSMSharedMemorySize> Could not get CUDA device properties"); return deviceProp.sharedMemPerBlock; } int GetCudaCurGlobalMemorySize() { int curDevId = GetCudaCurDeviceId(); cudaDeviceProp deviceProp; cudaError_t cudaError = cudaGetDeviceProperties(&deviceProp, curDevId); if (cudaError != cudaSuccess) { PrintCudaErrorInfo(cudaError, "GetCudaCurGlobalMemorySize> Could not get CUDA device properties"); } return deviceProp.totalGlobalMem; } int GetCudaCurSMRegisterCount() { int curDevId = GetCudaCurDeviceId(); cudaDeviceProp deviceProp; cudaError_t cudaError = cudaGetDeviceProperties(&deviceProp, curDevId); if (cudaError != cudaSuccess) { PrintCudaErrorInfo(cudaError, "GetCudaSMRegisterCount> Could not get CUDA device properties"); } return deviceProp.regsPerBlock; } int GetCudaCurSMCount() { int curDevId = GetCudaCurDeviceId(); cudaDeviceProp deviceProp; cudaError_t cudaError = cudaGetDeviceProperties(&deviceProp, curDevId); if (cudaError != cudaSuccess) { PrintCudaErrorInfo(cudaError, "GetCudaSMCount> Could not get CUDA device properties"); } return deviceProp.multiProcessorCount; } bool GetCudaCurIsDoublePrecisionSupported() { int curDevId = GetCudaCurDeviceId(); cudaDeviceProp deviceProp; cudaError_t cudaError = cudaGetDeviceProperties(&deviceProp, curDevId); if (cudaError != cudaSuccess) { PrintCudaErrorInfo(cudaError, "GetCudaIsDoublePrecisionSupported> Could not get CUDA device properties"); } return deviceProp.major >= 2 || (deviceProp.major == 1 && deviceProp.minor >= 3); } } } } } #endif

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    eb0bc04b

    commit eb0bc04b619ec6529a2ebb557212d9271d34b06a
    Author: Kresimir Cosic 
    Date:   Wed Jan 25 20:50:30 2012 +0100
    
        Added missing files related to previous commit
    

    Commits in /Users/nate/repos_lsst/afw/

    21597d88

    commit 21597d884d868e35a5d1a1b396621e5fe8a53d10
    Author: Russell Owen 
    Date:   Tue Jun 17 11:38:19 2014 -0700
    
        Rename exceptions
    

    Return to list

    python/lsst/afw/display/ds9.py

    Diff:

                    #
                    # LSST Data Management System
    
    3 a6d55f08 - # Copyright 2008, 2009, 2010 LSST Corporation.
    3 bde0ab27 + # Copyright 2008, 2009, 2010, 2015 LSST Corporation.
    ? ++++++ # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see . # ## ## \file
    25 f8edfe90 - ## \brief Definitions to talk to ds9 from python
    ? ^^ ----- ^^^^^
    25 bde0ab27 + ## \brief Support for talking to ds9 from python
    ? ^^^^^^^^ ^ +++
    26 bde0ab27 + ## \deprecated New code should use lsst.afw.display and set the backend to ds9
    27 4402095d - from __future__ import with_statement
    28 bde0ab27 + from __future__ import absolute_import, division, print_function
    29 03b53c5c - import os, re, math, sys, time
    30 bde0ab27 + import lsst.afw.display
    31 23ef9f32 + import lsst.afw.image as afwImage
    32 bde0ab27 + from .interface import getDisplay, getDefaultBackend, setDefaultBackend
    try:
    32 fd913cf6 - import xpa
    35 bde0ab27 + loaded
    36 097d37d8 + except NameError:
    37 bde0ab27 + if getDefaultBackend() == "virtualDevice":
    38 bde0ab27 + try:
    39 bde0ab27 + setDefaultBackend("lsst.display.ds9")
    33 fd913cf6 - except ImportError, e:
    ? ^
    40 bde0ab27 + except ImportError as e:
    ? ++++++++ ^^^
    34 fd913cf6 - print >> sys.stderr, "Cannot import xpa: %s" % e
    41 bde0ab27 + raise ImportError("Unable to import lsst.display.ds9: %s" % e)
    43 bde0ab27 + loaded = True
    36 7c7e5c6d - import displayLib
    37 88177a06 - import lsst.afw.geom as afwGeom
    38 23ef9f32 - import lsst.afw.image as afwImage
    39 2bd72d8b - import lsst.afw.math as afwMath
    40 03b53c5c -
    41 c00feea9 - try:
    42 c00feea9 - needShow
    43 c00feea9 - except NameError:
    44 c00feea9 - needShow = True; # Used to avoid a bug in ds9 5.4
    45 2ebad60d -
    46 f8edfe90 - ## An error talking to ds9
    47 03b53c5c - class Ds9Error(IOError):
    48 03b53c5c - """Some problem talking to ds9"""
    49 03b53c5c -
    50 032a990a - try:
    51 097d37d8 - type(_frame0)
    52 097d37d8 - except NameError:
    53 9f42c862 - _currentFrame = None
    54 9f42c862 -
    55 097d37d8 - def selectFrame(frame):
    56 9f42c862 - global _currentFrame
    57 9f42c862 - if frame != _currentFrame:
    58 9f42c862 - ds9Cmd(flush=True)
    59 9f42c862 - _currentFrame = frame
    60 9f42c862 -
    61 097d37d8 - return "frame %d" % (frame + _frame0)
    62 097d37d8 -
    63 097d37d8 - def setFrame0(frame0):
    64 097d37d8 - """Add frame0 to all frame specifications"""
    65 097d37d8 - global _frame0
    66 097d37d8 - _frame0 = frame0
    67 097d37d8 -
    68 097d37d8 - setFrame0(0)
    69 097d37d8 -
    70 097d37d8 - try:
    71 032a990a - type(_defaultFrame)
    72 032a990a - except NameError:
    73 993791af - def setDefaultFrame(frame=0):
    74 032a990a - """Set the default frame for ds9"""
    75 032a990a - global _defaultFrame
    76 032a990a - _defaultFrame = frame
    77 032a990a -
    78 032a990a - def getDefaultFrame():
    79 032a990a - """Get the default frame for ds9"""
    80 032a990a - return _defaultFrame
    81 032a990a -
    82 4b6acf34 - def incrDefaultFrame():
    83 4b6acf34 - """Increment the default frame for ds9"""
    84 4b6acf34 - global _defaultFrame
    85 4b6acf34 - _defaultFrame += 1
    86 4b6acf34 - return _defaultFrame
    87 4b6acf34 -
    88 032a990a - setDefaultFrame(0)
    89 757abc24 - #
    90 032a990a - # Symbolic names for mask/line colours. N.b. ds9 5.3+ supports any X11 colour for masks
    91 757abc24 - #
    92 fde07015 - WHITE = "white"
    93 fde07015 - BLACK = "black"
    94 fde07015 - RED = "red"
    95 fde07015 - GREEN = "green"
    96 fde07015 - BLUE = "blue"
    97 fde07015 - CYAN = "cyan"
    98 fde07015 - MAGENTA = "magenta"
    99 fde07015 - YELLOW = "yellow"
    100 030251bb - ORANGE = "orange"
    101 030251bb - _maskColors = [WHITE, BLACK, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, ORANGE]
    102 dd48cbc1 -
    103 dd48cbc1 - def setMaskPlaneColor(name, color=None):
    104 dd48cbc1 - """Request that mask plane name be displayed as color; name may be a dictionary
    105 dd48cbc1 - (in which case color should be omitted"""
    106 dd48cbc1 -
    107 dd48cbc1 - if isinstance(name, dict):
    108 dd48cbc1 - assert color == None
    109 dd48cbc1 - for k in name.keys():
    110 dd48cbc1 - setMaskPlaneColor(k, name[k])
    111 dd48cbc1 - return
    112 dd48cbc1 -
    113 7df3a916 - global _maskPlaneColors
    114 7df3a916 - try:
    115 7df3a916 - type(_maskPlaneColors)
    116 7df3a916 - except:
    117 7df3a916 - _maskPlaneColors = {}
    118 7df3a916 -
    119 032a990a - _maskPlaneColors[name] = color
    #
    122 7df3a916 - # Default mapping from mask plane names to colours
    46 bde0ab27 + # Backwards compatibility. Downstream code should be converted to use display.RED etc.
    #
    48 bde0ab27 + from lsst.afw.display import BLACK, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, WHITE
    124 7df3a916 - setMaskPlaneColor({
    125 7df3a916 - "BAD": RED,
    126 7df3a916 - "CR" : MAGENTA,
    127 7df3a916 - "EDGE": YELLOW,
    128 2bd72d8b - "INTERPOLATED" : GREEN,
    129 2bd72d8b - "SATURATED" : GREEN,
    130 2bd72d8b - "DETECTED" : BLUE,
    131 2bd72d8b - "DETECTED_NEGATIVE" : CYAN,
    132 91ec01a4 - "SUSPECT" : YELLOW,
    133 030251bb - "NO_DATA": ORANGE,
    134 a5a0c314 - "CROSSTALK": RED,
    135 a5a0c314 - "CLIPPED": RED,
    136 2bd72d8b - # deprecated names
    137 7df3a916 - "INTRP" : GREEN,
    138 7df3a916 - "SAT" : GREEN,
    139 7df3a916 - })
    50 bde0ab27 + Buffering = lsst.afw.display.Display.Buffering
    141 dd48cbc1 - def getMaskPlaneColor(name):
    142 dd48cbc1 - """Return the colour associated with the specified mask plane name"""
    143 dd48cbc1 -
    144 dd48cbc1 - if _maskPlaneColors.has_key(name):
    145 dd48cbc1 - return _maskPlaneColors[name]
    146 dd48cbc1 - else:
    147 dd48cbc1 - return None
    148 757abc24 -
    149 7df3a916 - def setMaskPlaneVisibility(name, show=True):
    150 a7aa0c91 - """Specify the visibility of a given mask plane;
    151 a7aa0c91 - name may be a dictionary (in which case show will be ignored)"""
    152 7df3a916 -
    153 7df3a916 - global _maskPlaneVisibility
    154 7df3a916 - try:
    155 7df3a916 - type(_maskPlaneVisibility)
    156 7df3a916 - except NameError, e:
    157 7df3a916 - _maskPlaneVisibility = {}
    158 7df3a916 -
    159 7df3a916 - if isinstance(name, dict):
    160 7df3a916 - for k in name.keys():
    161 7df3a916 - setMaskPlaneVisibility(k, name[k])
    162 7df3a916 - return
    163 7df3a916 -
    164 7df3a916 - _maskPlaneVisibility[name] = show
    165 7df3a916 -
    166 7df3a916 - setMaskPlaneVisibility({})
    167 7df3a916 -
    168 7df3a916 - def getMaskPlaneVisibility(name):
    169 7df3a916 - """Should we display the specified mask plane name?"""
    170 7df3a916 -
    171 7df3a916 - if _maskPlaneVisibility.has_key(name):
    172 7df3a916 - return _maskPlaneVisibility[name]
    173 7df3a916 - else:
    174 7df3a916 - return True
    175 7df3a916 -
    176 4c800cc0 - try:
    177 4c800cc0 - _maskTransparency
    178 4c800cc0 - except NameError:
    179 4c800cc0 - _maskTransparency = None
    180 4c800cc0 -
    181 73b30db0 - def setMaskTransparency(transparency=None, frame=None):
    182 eb37ae8a - """Specify ds9's mask transparency (percent); or None to not set it when loading masks"""
    183 eb37ae8a -
    184 eb37ae8a - global _maskTransparency
    185 ff5aab1b - if transparency is not None and (transparency < 0 or transparency > 100):
    186 eb37ae8a - print >> sys.stderr, "Mask transparency should be in the range [0, 100]; clipping"
    187 eb37ae8a - if transparency < 0:
    188 eb37ae8a - transparency = 0
    189 eb37ae8a - else:
    190 eb37ae8a - transparency = 100
    191 eb37ae8a -
    192 eb37ae8a - _maskTransparency = transparency
    193 eb37ae8a -
    194 c4cebd54 - if transparency is not None:
    195 b43efd84 - ds9Cmd("mask transparency %d" % transparency, frame=frame)
    196 c4cebd54 -
    197 b28bcf63 - def getDesiredMaskTransparency():
    198 b28bcf63 - """Return requested ds9's mask transparency"""
    199 eb37ae8a -
    200 eb37ae8a - return _maskTransparency
    201 eb37ae8a -
    202 b28bcf63 - def getMaskTransparency(frame=None):
    203 b28bcf63 - """Return the current ds9's mask transparency"""
    204 b28bcf63 -
    205 b28bcf63 - return float(ds9Cmd("mask transparency", get=True))
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    53 7df3a916 + #
    54 bde0ab27 + # Functions provided for backwards compatibility
    55 7df3a916 + #
    56 bde0ab27 + def setMaskPlaneColor(name, color=None, frame=None):
    57 bde0ab27 + return getDisplay(frame, create=True).setMaskPlaneColor(name, color)
    59 bde0ab27 + def getMaskPlaneColor(name, frame=None):
    60 bde0ab27 + return getDisplay(frame, create=True).getMaskPlaneColor(name)
    209 ae6e4fbe - def getXpaAccessPoint():
    210 ae6e4fbe - """Parse XPA_PORT and send return an identifier to send ds9 commands there, instead of "ds9"
    211 ae6e4fbe - If you don't have XPA_PORT set, the usual xpans tricks will be played when we return "ds9".
    212 ae6e4fbe - """
    213 5054239e - xpa_port = os.environ.get("XPA_ACCESS_POINT")
    214 5054239e - if xpa_port:
    215 5054239e - return xpa_port
    62 bde0ab27 + def setMaskTransparency(name, frame=None):
    63 bde0ab27 + return getDisplay(frame, create=True).setMaskTransparency(name)
    217 ae6e4fbe - xpa_port = os.environ.get("XPA_PORT")
    218 ae6e4fbe - if xpa_port:
    219 ae6e4fbe - mat = re.search(r"^DS9:ds9\s+(\d+)\s+(\d+)", xpa_port)
    220 ae6e4fbe - if mat:
    221 ae6e4fbe - port1, port2 = mat.groups()
    65 bde0ab27 + def getMaskTransparency(name, frame=None):
    66 bde0ab27 + return getDisplay(frame, create=True).getMaskTransparency(name)
    223 a2be114f - return "127.0.0.1:%s" % (port1)
    224 ae6e4fbe - else:
    225 ae6e4fbe - print >> sys.stderr, "Failed to parse XPA_PORT=%s" % xpa_port
    226 6ca80c53 -
    227 ae6e4fbe - return "ds9"
    228 ae6e4fbe -
    229 7fdf5d77 - def ds9Version():
    230 7fdf5d77 - """Return the version of ds9 in use, as a string"""
    231 6edafcfa - try:
    232 5054239e - v = "?"
    233 b28bcf63 - v = ds9Cmd("about", get=True)
    234 77940d02 - return v.splitlines()[1].split()[1]
    235 6edafcfa - except Exception, e:
    236 77940d02 - print >> sys.stderr, "Error reading version: %s (%s)" % (v, e)
    237 6edafcfa - return "0.0.0"
    238 7fdf5d77 -
    239 9f42c862 - try:
    240 9f42c862 - cmdBuffer
    241 9f42c862 - except NameError:
    242 236e2ff4 - XPA_SZ_LINE = 4096 - 100 # internal buffersize in xpa. Sigh; esp. as the 100 is some needed slop
    243 9f42c862 -
    244 9f42c862 - class Buffer(object):
    245 9f42c862 - """Control buffering the sending of commands to ds9;
    246 9f42c862 - annoying but necessary for anything resembling performance
    247 9f42c862 -
    248 5af71dcc - The usual usage pattern (from a module importing this file, ds9.py) is probably:
    249 5af71dcc -
    250 43549001 - with ds9.Buffering():
    251 43549001 - # bunches of ds9.{dot,line} commands
    252 43549001 - ds9.flush()
    253 43549001 - # bunches more ds9.{dot,line} commands
    254 43549001 -
    255 43549001 - or (if you don't like "with")
    256 5af71dcc - ds9.buffer()
    257 5af71dcc - # bunches of ds9.{dot,line} commands
    258 5af71dcc - ds9.flush()
    259 5af71dcc - # bunches more ds9.{dot,line} commands
    260 5af71dcc - ds9.buffer(False)
    261 4402095d -
    262 43549001 - or (the old idiom):
    263 4402095d -
    264 43549001 - ds9.cmdBuffer.pushSize()
    265 43549001 - # bunches of ds9.{dot,line} commands
    266 43549001 - ds9.cmdBuffer.flush()
    267 43549001 - # bunches more ds9.{dot,line} commands
    268 43549001 - ds9.cmdBuffer.popSize()
    269 9f42c862 - """
    270 9f42c862 -
    271 9f42c862 - def __init__(self, size=0):
    272 9f42c862 - """Create a command buffer, with a maximum depth of size"""
    273 9f42c862 - self._commands = "" # list of pending commands
    274 9f42c862 - self._lenCommands = len(self._commands)
    275 9f42c862 - self._bufsize = [] # stack of bufsizes
    276 9f42c862 -
    277 9f42c862 - self._bufsize.append(size) # don't call self.size() as ds9Cmd isn't defined yet
    278 9f42c862 -
    279 7009758d - def set(self, size, silent=True):
    280 9f42c862 - """Set the ds9 buffer size to size"""
    281 9f42c862 - if size < 0:
    282 9f42c862 - size = XPA_SZ_LINE - 5
    283 9f42c862 -
    284 9f42c862 - if size > XPA_SZ_LINE:
    285 9f42c862 - print >> sys.stderr, \
    286 9f42c862 - "xpa silently hardcodes a limit of %d for buffer sizes (you asked for %d) " % \
    287 9f42c862 - (XPA_SZ_LINE, size)
    288 9f42c862 - self.set(-1) # use max buffersize
    289 9f42c862 - return
    290 9f42c862 -
    291 9f42c862 - if self._bufsize:
    292 9f42c862 - self._bufsize[-1] = size # change current value
    293 9f42c862 - else:
    294 9f42c862 - self._bufsize.append(size) # there is no current value; set one
    295 9f42c862 -
    296 81f206cb - self.flush(silent=silent)
    297 9f42c862 -
    298 9f42c862 - def _getSize(self):
    299 9f42c862 - """Get the current ds9 buffer size"""
    300 9f42c862 - return self._bufsize[-1]
    301 9f42c862 -
    302 9f42c862 - def pushSize(self, size=-1):
    303 9f42c862 - """Replace current ds9 command buffer size with size (see also popSize)
    304 9f42c862 - @param: Size of buffer (-1: largest possible given bugs in xpa)"""
    305 81f206cb - self.flush(silent=True)
    306 9f42c862 - self._bufsize.append(0)
    307 81f206cb - self.set(size, silent=True)
    308 9f42c862 -
    309 9f42c862 - def popSize(self):
    310 9f42c862 - """Switch back to the previous command buffer size (see also pushSize)"""
    311 81f206cb - self.flush(silent=True)
    312 236e2ff4 -
    313 9f42c862 - if len(self._bufsize) > 1:
    314 9f42c862 - self._bufsize.pop()
    315 9f42c862 -
    316 7009758d - def flush(self, silent=True):
    317 9f42c862 - """Flush the pending commands"""
    318 379e1add - ds9Cmd(flush=True, silent=silent)
    319 9f42c862 -
    320 9f42c862 - cmdBuffer = Buffer(0)
    321 9f42c862 -
    322 7009758d - def ds9Cmd(cmd=None, trap=True, flush=False, silent=True, frame=None, get=False):
    323 a7aa0c91 - """Issue a ds9 command, raising errors as appropriate"""
    324 6ca80c53 -
    325 a7aa0c91 - if getDefaultFrame() is None:
    326 a7aa0c91 - return
    327 032a990a -
    328 9f42c862 - global cmdBuffer
    329 9f42c862 - if cmd:
    330 b43efd84 - if frame is not None:
    331 b43efd84 - cmd = "%s;" % selectFrame(frame) + cmd
    332 b43efd84 -
    333 b28bcf63 - if get:
    334 b28bcf63 - return xpa.get(None, getXpaAccessPoint(), cmd, "").strip()
    335 b28bcf63 -
    336 9f42c862 - # Work around xpa's habit of silently truncating long lines
    337 9f42c862 - if cmdBuffer._lenCommands + len(cmd) > XPA_SZ_LINE - 5: # 5 to handle newlines and such like
    338 7009758d - ds9Cmd(flush=True, silent=silent)
    339 9f42c862 -
    340 9f42c862 - cmdBuffer._commands += ";" + cmd
    341 9f42c862 - cmdBuffer._lenCommands += 1 + len(cmd)
    342 9f42c862 -
    343 9f42c862 - if flush or cmdBuffer._lenCommands >= cmdBuffer._getSize():
    344 9f42c862 - cmd = cmdBuffer._commands + "\n"
    345 9f42c862 - cmdBuffer._commands = ""
    346 9f42c862 - cmdBuffer._lenCommands = 0
    347 9f42c862 - else:
    348 9f42c862 - return
    349 9f42c862 -
    350 4d7bf935 - cmd = cmd.rstrip()
    351 4d7bf935 - if not cmd:
    352 4d7bf935 - return
    353 4d7bf935 -
    354 a7aa0c91 - try:
    355 4d7bf935 - ret = xpa.set(None, getXpaAccessPoint(), cmd, "", "", 0)
    356 4d7bf935 - if ret:
    357 4d7bf935 - raise IOError(ret)
    358 a7aa0c91 - except IOError, e:
    359 a7aa0c91 - if not trap:
    360 a7aa0c91 - raise Ds9Error, "XPA: %s, (%s)" % (e, cmd)
    361 379e1add - elif not silent:
    362 a7aa0c91 - print >> sys.stderr, "Caught ds9 exception processing command \"%s\": %s" % (cmd, e)
    363 03b53c5c -
    364 14f8e3a7 - def initDS9(execDs9=True):
    365 a7aa0c91 - try:
    366 a7aa0c91 - xpa.reset()
    367 a7aa0c91 - ds9Cmd("iconify no; raise", False)
    368 a7aa0c91 - ds9Cmd("wcs wcsa", False) # include the pixel coordinates WCS (WCSA)
    369 6ca80c53 -
    370 ae549cd8 - v0, v1 = ds9Version().split('.')[0:2]
    371 51522cfe - global needShow
    372 ae549cd8 - needShow = False
    373 ae549cd8 - try:
    374 ae549cd8 - if int(v0) == 5:
    375 ae549cd8 - needShow = (int(v1) <= 4)
    376 ae549cd8 - except:
    377 ae549cd8 - pass
    378 a7aa0c91 - except Ds9Error, e:
    379 a7aa0c91 - if execDs9:
    380 a7aa0c91 - print "ds9 doesn't appear to be running (%s), I'll exec it for you" % e
    381 a7aa0c91 - if not re.search('xpa', os.environ['PATH']):
    382 03b53c5c - raise Ds9Error, 'You need the xpa binaries in your path to use ds9 with python'
    383 03b53c5c -
    384 a7aa0c91 - os.system('ds9 &')
    385 a7aa0c91 - for i in range(10):
    386 03b53c5c - try:
    387 6ca80c53 - ds9Cmd(selectFrame(1), False)
    388 a7aa0c91 - break
    389 14f8e3a7 - except Ds9Error:
    390 a7aa0c91 - print "waiting for ds9...\r",
    391 a7aa0c91 - sys.stdout.flush()
    392 a7aa0c91 - time.sleep(0.5)
    393 03b53c5c - else:
    394 a7aa0c91 - print " \r",
    395 a7aa0c91 - break
    396 03b53c5c -
    397 a7aa0c91 - sys.stdout.flush()
    398 6ca80c53 -
    399 a7aa0c91 - raise Ds9Error
    def show(frame=None):
    69 bde0ab27 + return getDisplay(frame, create=True).show()
    402 0b6b1b7f - """Uniconify and Raise ds9. N.b. throws an exception if frame doesn't exit"""
    403 4b6acf34 - if frame is None:
    404 032a990a - frame = getDefaultFrame()
    71 bde0ab27 + def mtv(data, frame=None, title="", wcs=None, *args, **kwargs):
    72 bde0ab27 + return getDisplay(frame, create=True).mtv(data, title, wcs, *args, **kwargs)
    406 032a990a - if frame is None:
    407 032a990a - return
    408 6ca80c53 -
    409 b43efd84 - ds9Cmd("raise", trap=False, frame=frame)
    410 0b6b1b7f -
    411 032a990a - def setMaskColor(color=GREEN):
    412 8864f403 - """Set the ds9 mask colour to; eg. setMaskColor(RED)"""
    413 dd48cbc1 - ds9Cmd("mask color %s" % color)
    414 757abc24 -
    415 6b67b592 -
    416 4b6acf34 - def mtv(data, frame=None, init=True, wcs=None, isMask=False, lowOrderBits=False, title=None, settings=None):
    417 a7aa0c91 - """Display an Image or Mask on a DS9 display
    418 dd48cbc1 -
    419 a7aa0c91 - If lowOrderBits is True, give low-order-bits priority in display (i.e.
    420 a7aa0c91 - overlay them last)
    421 7daa7d7a -
    422 a7aa0c91 - Historical note: the name "mtv" comes from Jim Gunn's forth imageprocessing
    423 a7aa0c91 - system, Mirella (named after Mirella Freni); The "m" stands for Mirella.
    424 a7aa0c91 - """
    425 6b67b592 -
    426 51522cfe - if frame is None:
    427 032a990a - frame = getDefaultFrame()
    428 032a990a -
    429 a7aa0c91 - if frame is None:
    430 a7aa0c91 - return
    431 6ca80c53 -
    432 a7aa0c91 - if init:
    433 a7aa0c91 - for i in range(3):
    434 a7aa0c91 - try:
    435 a7aa0c91 - initDS9(i == 0)
    436 a7aa0c91 - except Ds9Error:
    437 a7aa0c91 - print "waiting for ds9...\r",
    438 a7aa0c91 - sys.stdout.flush()
    439 a7aa0c91 - time.sleep(0.5)
    440 a7aa0c91 - else:
    441 df3b085f - if i > 0:
    442 df3b085f - print " \r",
    443 df3b085f - sys.stdout.flush()
    444 a7aa0c91 - break
    445 6ca80c53 -
    446 097d37d8 - ds9Cmd(selectFrame(frame))
    447 f7baf984 - ds9Cmd("smooth no")
    448 9f42c862 - erase(frame)
    449 a7aa0c91 -
    450 a7aa0c91 - if settings:
    451 a7aa0c91 - for setting in settings:
    452 a7aa0c91 - ds9Cmd("%s %s" % (setting, settings[setting]))
    453 a7aa0c91 -
    454 23ef9f32 - if re.search("::DecoratedImage<", repr(data)): # it's a DecorateImage; display it
    455 a7aa0c91 - _mtv(data.getImage(), wcs, title, False)
    456 23ef9f32 - elif re.search("::MaskedImage<", repr(data)): # it's a MaskedImage; display Image and overlay Mask
    457 a7aa0c91 - _mtv(data.getImage(), wcs, title, False)
    458 a7aa0c91 - mask = data.getMask(True)
    459 a7aa0c91 - if mask:
    460 9e3f07ed - mtv(mask, frame, False, wcs, True, lowOrderBits=lowOrderBits, title=title, settings=settings)
    461 b28bcf63 - if getDesiredMaskTransparency() is not None:
    462 b28bcf63 - ds9Cmd("mask transparency %d" % getDesiredMaskTransparency())
    463 a7aa0c91 -
    464 23ef9f32 - elif re.search("::Exposure<", repr(data)): # it's an Exposure; display the MaskedImage with the WCS
    465 a7aa0c91 - if wcs:
    466 a7aa0c91 - raise RuntimeError, "You may not specify a wcs with an Exposure"
    467 a7aa0c91 -
    468 a7aa0c91 - mtv(data.getMaskedImage(), frame, False, data.getWcs(),
    469 a7aa0c91 - False, lowOrderBits=lowOrderBits, title=title, settings=settings)
    470 a7aa0c91 -
    471 23ef9f32 - elif re.search("::Mask<", repr(data)): # it's a Mask; display it, bitplane by bitplane
    472 a7aa0c91 - maskPlanes = data.getMaskPlaneDict()
    473 d0e42b4a - nMaskPlanes = max(maskPlanes.values()) + 1
    474 a7aa0c91 -
    475 a7aa0c91 - planes = {} # build inverse dictionary
    476 a7aa0c91 - for key in maskPlanes.keys():
    477 a7aa0c91 - planes[maskPlanes[key]] = key
    478 a7aa0c91 -
    479 a7aa0c91 - colorIndex = 0 # index into maskColors
    480 a7aa0c91 -
    481 a7aa0c91 - if lowOrderBits:
    482 a7aa0c91 - planeList = range(nMaskPlanes - 1, -1, -1)
    483 a7aa0c91 - else:
    484 a7aa0c91 - planeList = range(nMaskPlanes)
    485 6ca80c53 -
    486 a7aa0c91 - usedPlanes = long(afwMath.makeStatistics(data, afwMath.SUM).getValue())
    487 a7aa0c91 - mask = data.Factory(data.getDimensions())
    488 23ef9f32 - #
    489 23ef9f32 - # ds9 can't display a Mask without an image; so display an Image first
    490 23ef9f32 - #
    491 9e3f07ed - if not isMask:
    492 9e3f07ed - im = afwImage.ImageU(data.getDimensions())
    493 9e3f07ed - mtv(im, frame=frame)
    494 23ef9f32 -
    495 a7aa0c91 - for p in planeList:
    496 0d90bfa0 - if planes.get(p):
    497 50978a4e - pname = planes[p]
    498 50978a4e - if not getMaskPlaneVisibility(pname):
    499 a7aa0c91 - continue
    500 50978a4e - else:
    501 50978a4e - pname = "unknown"
    502 7df3a916 -
    503 5de5a4e0 - if not getMaskPlaneVisibility(pname):
    504 5de5a4e0 - continue
    505 2bd72d8b -
    506 5de5a4e0 - if not ((1 << p) & usedPlanes): # no pixels have this bitplane set
    507 5de5a4e0 - continue
    508 2bd72d8b -
    509 5de5a4e0 - mask <<= data
    510 5de5a4e0 - mask &= (1 << p)
    511 dd48cbc1 -
    512 5de5a4e0 - color = getMaskPlaneColor(pname)
    513 dd48cbc1 -
    514 5de5a4e0 - if not color: # none was specified
    515 5de5a4e0 - while True:
    516 5de5a4e0 - color = _maskColors[colorIndex % len(_maskColors)]
    517 5de5a4e0 - colorIndex += 1
    518 5de5a4e0 - if color != WHITE and color != BLACK:
    519 5de5a4e0 - break
    520 dd48cbc1 -
    521 a5a0c314 - print "Assigning %s to mask plane %s" % (color, pname)
    522 a5a0c314 - setMaskPlaneColor(pname, color) # remember our choice
    523 a5a0c314 -
    524 5de5a4e0 - setMaskColor(color)
    525 5de5a4e0 - _mtv(mask, wcs, title, True)
    526 a7aa0c91 - return
    527 23ef9f32 - elif re.search("::Image<", repr(data)): # it's an Image; display it
    528 a7aa0c91 - _mtv(data, wcs, title, False)
    529 a7aa0c91 - else:
    530 23ef9f32 - raise RuntimeError, "Unsupported type %s" % repr(data)
    531 dd48cbc1 -
    532 c4cebd54 - try:
    533 c4cebd54 - haveGzip
    534 c4cebd54 - except NameError:
    535 c4cebd54 - haveGzip = not os.system("gzip < /dev/null > /dev/null 2>&1") # does gzip work?
    536 c4cebd54 -
    537 da44d414 - def _mtv(data, wcs, title, isMask):
    538 a7aa0c91 - """Internal routine to display an Image or Mask on a DS9 display"""
    539 a7aa0c91 -
    540 0d90bfa0 - title = str(title) if title else ""
    541 0d90bfa0 -
    542 a7aa0c91 - if True:
    543 a7aa0c91 - if isMask:
    544 a7aa0c91 - xpa_cmd = "xpaset %s fits mask" % getXpaAccessPoint()
    545 a7aa0c91 - if re.search(r"unsigned short|boost::uint16_t", data.__str__()):
    546 a7aa0c91 - data |= 0x8000 # Hack. ds9 mis-handles BZERO/BSCALE in masks. This is a copy we're modifying
    547 a7aa0c91 - else:
    548 a7aa0c91 - xpa_cmd = "xpaset %s fits" % getXpaAccessPoint()
    549 6ca80c53 -
    550 c4cebd54 - if haveGzip:
    551 c4cebd54 - xpa_cmd = "gzip | " + xpa_cmd
    552 4d3c8e52 -
    553 4d3c8e52 - pfd = os.popen(xpa_cmd, "w")
    554 a7aa0c91 - else:
    555 a7aa0c91 - pfd = file("foo.fits", "w")
    556 a7aa0c91 -
    557 a7aa0c91 - try:
    558 a7aa0c91 - displayLib.writeFitsImage(pfd.fileno(), data, wcs, title)
    559 a7aa0c91 - except Exception, e:
    560 a7aa0c91 - try:
    561 a7aa0c91 - pfd.close()
    562 a7aa0c91 - except:
    563 a7aa0c91 - pass
    564 6ca80c53 -
    565 a7aa0c91 - raise e
    566 03b53c5c -
    567 a7aa0c91 - try:
    568 a7aa0c91 - pfd.close()
    569 a7aa0c91 - except:
    570 a7aa0c91 - pass
    571 03b53c5c - #
    572 03b53c5c - # Graphics commands
    573 03b53c5c - #
    574 5af71dcc - def buffer(enable=True):
    575 5af71dcc - if enable:
    576 5af71dcc - cmdBuffer.pushSize()
    577 5af71dcc - else:
    578 8864f403 - cmdBuffer.popSize()
    579 5af71dcc -
    580 4d6d44fa - flush = lambda : cmdBuffer.flush(silent=True)
    581 5af71dcc -
    582 4402095d - class Buffering(object):
    583 4402095d - """A class intended to be used with python's with statement:
    584 54657932 - E.g.
    585 54657932 - with ds9.Buffering():
    586 54657932 - ds9.dot("+", xc, yc)
    587 4402095d - """
    588 4402095d - def __enter__(self):
    589 4402095d - buffer(True)
    590 4402095d - def __exit__(self, *args):
    591 4402095d - buffer(False)
    def erase(frame=None):
    75 bde0ab27 + return getDisplay(frame, create=True).erase()
    594 a7aa0c91 - """Erase the specified DS9 frame"""
    595 51522cfe - if frame is None:
    596 032a990a - frame = getDefaultFrame()
    598 a7aa0c91 - if frame is None:
    599 a7aa0c91 - return
    77 bde0ab27 + def dot(symb, c, r, frame=None, size=2, ctype=None, origin=afwImage.PARENT, *args, **kwargs):
    78 bde0ab27 + return getDisplay(frame, create=True).dot(symb, c, r, size, ctype, origin, *args, **kwargs)
    601 b43efd84 - ds9Cmd("regions delete all", flush=True, frame=frame)
    80 bde0ab27 + def line(points, frame=None, origin=afwImage.PARENT, symbs=False, ctype=None, size=0.5):
    81 bde0ab27 + return getDisplay(frame, create=True).line(points, origin, symbs, ctype, size)
    83 bde0ab27 + def scaleLimits(min, max=None, frame=None):
    84 bde0ab27 + return getDisplay(frame, create=True).scaleLimits(min, max)
    603 7009758d - def dot(symb, c, r, frame=None, size=2, ctype=None, fontFamily="helvetica", silent=True):
    604 a7aa0c91 - """Draw a symbol onto the specified DS9 frame at (col,row) = (c,r) [0-based coordinates]
    605 03b53c5c - Possible values are:
    606 2eb9dac3 - + Draw a +
    607 2eb9dac3 - x Draw an x
    608 8d74933b - * Draw a *
    609 2eb9dac3 - o Draw a circle
    610 88177a06 - @:Mxx,Mxy,Myy Draw an ellipse with moments (Mxx, Mxy, Myy) (argument size is ignored)
    611 88177a06 - An object derived from afwGeom.ellipses.BaseCore Draw the ellipse (argument size is ignored)
    612 bbef7fe4 - Any other value is interpreted as a string to be drawn. Strings obey the fontFamily (which may be extended
    613 bbef7fe4 - with other characteristics, e.g. "times bold italic".
    86 bde0ab27 + def scaleType(name, frame=None, params=None):
    87 bde0ab27 + return getDisplay(frame, create=True).scaleType(name, params)
    615 88177a06 - N.b. objects derived from BaseCore include Axes and Quadrupole.
    616 03b53c5c - """
    617 51522cfe - if frame is None:
    618 032a990a - frame = getDefaultFrame()
    620 a7aa0c91 - if frame is None:
    621 a7aa0c91 - return
    89 bde0ab27 + def pan(colc=None, rowc=None, frame=None, origin=afwImage.PARENT):
    90 bde0ab27 + disp = getDisplay(frame, create=True)
    92 bde0ab27 + disp.pan(colc, rowc, origin)
    623 a7aa0c91 - if isinstance(symb, int):
    624 a7aa0c91 - symb = "%d" % (symb)
    94 bde0ab27 + def zoom(zoomfac=None, colc=None, rowc=None, frame=None, origin=afwImage.PARENT):
    95 bde0ab27 + disp = getDisplay(frame, create=True)
    626 a7aa0c91 - if ctype == None:
    627 a7aa0c91 - color = "" # the default
    628 a7aa0c91 - else:
    629 a7aa0c91 - color = ' # color=%s' % ctype
    97 bde0ab27 + disp.zoom(zoomfac)
    98 bde0ab27 + disp.pan(colc, rowc, origin)
    631 097d37d8 - cmd = selectFrame(frame) + "; "
    632 a7aa0c91 - r += 1
    633 a7aa0c91 - c += 1 # ds9 uses 1-based coordinates
    634 88177a06 - if isinstance(symb, afwGeom.ellipses.BaseCore) or re.search(r"^@:", symb):
    635 88177a06 - try:
    636 88177a06 - mat = re.search(r"^@:([^,]+),([^,]+),([^,]+)", symb)
    637 88177a06 - except TypeError:
    638 88177a06 - pass
    639 88177a06 - else:
    640 88177a06 - if mat:
    641 88177a06 - mxx, mxy, myy = [float(_) for _ in mat.groups()]
    642 88177a06 - symb = afwGeom.ellipses.Quadrupole(mxx, myy, mxy)
    100 bde0ab27 + def interact(frame=None):
    101 bde0ab27 + return getDisplay(frame, create=True).interact()
    644 88177a06 - symb = afwGeom.ellipses.Axes(symb)
    645 88177a06 - cmd += 'regions command {ellipse %g %g %g %g %g%s}; ' % (c, r, symb.getA(), symb.getB(),
    646 88177a06 - math.degrees(symb.getTheta()), color)
    647 88177a06 - elif symb == '+':
    648 a7aa0c91 - cmd += 'regions command {line %g %g %g %g%s}; ' % (c, r+size, c, r-size, color)
    649 a7aa0c91 - cmd += 'regions command {line %g %g %g %g%s}; ' % (c-size, r, c+size, r, color)
    650 a7aa0c91 - elif symb == 'x':
    651 a7aa0c91 - size = size/math.sqrt(2)
    652 a7aa0c91 - cmd += 'regions command {line %g %g %g %g%s}; ' % (c+size, r+size, c-size, r-size, color)
    653 a7aa0c91 - cmd += 'regions command {line %g %g %g %g%s}; ' % (c-size, r+size, c+size, r-size, color)
    654 8d74933b - elif symb == '*':
    655 8d74933b - size30 = 0.5*size
    656 8d74933b - size60 = 0.5*math.sqrt(3)*size
    657 8d74933b - cmd += 'regions command {line %g %g %g %g%s}; ' % (c+size, r, c-size, r, color)
    658 8d74933b - cmd += 'regions command {line %g %g %g %g%s}; ' % (c-size30, r+size60, c+size30, r-size60, color)
    659 8d74933b - cmd += 'regions command {line %g %g %g %g%s}; ' % (c+size30, r+size60, c-size30, r-size60, color)
    660 a7aa0c91 - elif symb == 'o':
    661 a7aa0c91 - cmd += 'regions command {circle %g %g %g%s}; ' % (c, r, size, color)
    662 a7aa0c91 - else:
    663 a7aa0c91 - try:
    664 a7aa0c91 - # We have to check for the frame's existance with show() as the text command crashed ds9 5.4
    665 a7aa0c91 - # if it doesn't
    666 51522cfe - if needShow:
    667 51522cfe - show(frame)
    103 bde0ab27 + def setCallback(k, func=lsst.afw.display.noop_callback, noRaise=False, frame=None):
    104 bde0ab27 + return getDisplay(frame, create=True).setCallback(k, noRaise=False)
    669 bbef7fe4 - font = ""
    670 bbef7fe4 - if size != 2 or fontFamily != "helvetica":
    671 bbef7fe4 - if not color:
    672 bbef7fe4 - font += " #"
    673 bbef7fe4 - fontFamily = fontFamily.split()
    674 bbef7fe4 - font += ' font="%s %d' % (fontFamily.pop(0), int(10*size/2.0 + 0.5))
    675 bbef7fe4 - if fontFamily:
    676 bbef7fe4 - font += " %s" % " ".join(fontFamily)
    677 bbef7fe4 - font += '"'
    106 bde0ab27 + def getActiveCallbackKeys(onlyActive=True, frame=None):
    107 bde0ab27 + return getDisplay(frame, create=True).getActiveCallbackKeys(onlyActive)
    679 bbef7fe4 - cmd += 'regions command {text %g %g \"%s\"%s%s };' % (c, r, symb, color, font)
    680 51522cfe - except Exception, e:
    681 097d37d8 - print >> sys.stderr, ("Ds9 frame %d doesn't exist" % frame), e
    682 a7aa0c91 -
    683 7009758d - ds9Cmd(cmd, silent=silent)
    684 03b53c5c -
    685 4b6acf34 - def line(points, frame=None, symbs=False, ctype=None):
    686 a7aa0c91 - """Draw a set of symbols or connect the points, a list of (col,row)
    687 03b53c5c - If symbs is True, draw points at the specified points using the desired symbol,
    688 03b53c5c - otherwise connect the dots. Ctype is the name of a colour (e.g. 'red')"""
    689 6ca80c53 -
    690 51522cfe - if frame is None:
    691 032a990a - frame = getDefaultFrame()
    692 032a990a -
    693 a7aa0c91 - if frame is None:
    694 a7aa0c91 - return
    695 a7aa0c91 -
    696 a7aa0c91 - if symbs:
    697 a7aa0c91 - for (c, r) in points:
    698 097d37d8 - dot(symbs, r, c, frame=frame, size=0.5, ctype=ctype)
    699 a7aa0c91 - else:
    700 a7aa0c91 - if ctype == None: # default
    701 a7aa0c91 - color = ""
    702 a7aa0c91 - else:
    703 a7aa0c91 - color = "# color=%s" % ctype
    704 a7aa0c91 -
    705 a7aa0c91 - if len(points) > 0:
    706 097d37d8 - cmd = selectFrame(frame) + "; "
    707 a7aa0c91 -
    708 a7aa0c91 - c0, r0 = points[0]
    709 a7aa0c91 - r0 += 1
    710 a7aa0c91 - c0 += 1 # ds9 uses 1-based coordinates
    711 a7aa0c91 - for (c, r) in points[1:]:
    712 a7aa0c91 - r += 1
    713 a7aa0c91 - c += 1 # ds9 uses 1-based coordinates
    714 a7aa0c91 - cmd += 'regions command { line %g %g %g %g %s};' % (c0, r0, c, r, color)
    715 a7aa0c91 - c0, r0 = c, r
    716 a7aa0c91 -
    717 a7aa0c91 - ds9Cmd(cmd)
    718 03b53c5c - #
    719 03b53c5c - # Zoom and Pan
    720 03b53c5c - #
    721 4b6acf34 - def zoom(zoomfac=None, colc=None, rowc=None, frame=None):
    722 a7aa0c91 - """Zoom frame by specified amount, optionally panning also"""
    723 6ca80c53 -
    724 a7aa0c91 - if frame < 0:
    725 a7aa0c91 - frame = getDefaultFrame()
    726 6ca80c53 -
    727 a7aa0c91 - if frame is None:
    728 a7aa0c91 - return
    729 03b53c5c -
    730 51522cfe - if frame is None:
    731 51522cfe - frame = getDefaultFrame()
    732 032a990a -
    733 51522cfe - if frame is None:
    734 51522cfe - return
    735 03b53c5c -
    736 a7aa0c91 - if (rowc and colc is None) or (colc and rowc is None):
    737 a7aa0c91 - raise Ds9Error, "Please specify row and column center to pan about"
    738 6ca80c53 -
    739 a7aa0c91 - if zoomfac == None and rowc == None:
    740 a7aa0c91 - zoomfac = 2
    741 03b53c5c -
    742 097d37d8 - cmd = selectFrame(frame) + "; "
    743 a7aa0c91 - if zoomfac != None:
    744 a7aa0c91 - cmd += "zoom to %d; " % zoomfac
    745 03b53c5c -
    746 a7aa0c91 - if rowc != None:
    747 a7aa0c91 - cmd += "pan to %g %g physical; " % (colc + 1, rowc + 1) # ds9 is 1-indexed. Grrr
    748 03b53c5c -
    749 48d5e5b7 - ds9Cmd(cmd, flush=True)
    750 03b53c5c -
    751 4b6acf34 - def pan(colc=None, rowc=None, frame=None):
    752 a7aa0c91 - """Pan to (rowc, colc); see also zoom"""
    753 032a990a -
    754 51522cfe - if frame is None:
    755 032a990a - frame = getDefaultFrame()
    756 032a990a -
    757 a7aa0c91 - if frame is None:
    758 a7aa0c91 - return
    759 032a990a -
    760 a7aa0c91 - zoom(None, colc, rowc, frame)
    761 f4c8e339 -
    762 f4c8e339 - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    763 0fd56195 -
    764 0fd56195 - def interact():
    765 0fd56195 - """Enter an interactive loop, listening for key presses in ds9 and firing callbacks.
    766 0fd56195 -
    767 0fd56195 - Exit with q, , or
    768 0fd56195 - """
    769 0fd56195 -
    770 0fd56195 - while True:
    771 0fd56195 - vals = ds9Cmd("imexam key coordinate", get=True).split()
    772 0fd56195 -
    773 0fd56195 - k = vals.pop(0)
    774 96ea07d5 - try:
    775 0fd56195 - x = float(vals[0]); y = float(vals[1])
    776 96ea07d5 - except:
    777 0fd56195 - x = float("NaN"); y = float("NaN")
    778 0fd56195 -
    779 0fd56195 - try:
    780 0fd56195 - if callbacks[k](k, x, y):
    781 0fd56195 - break
    782 0fd56195 - except KeyError:
    783 0fd56195 - print >> sys.stderr, "No callback is registered for %s" % k
    784 0fd56195 - except Exception, e:
    785 0fd56195 - print >> sys.stderr, "ds9.callbacks[%s](%s, %s, %s) failed: %s" % \
    786 0fd56195 - (k, k, x, y, e)
    787 0fd56195 -
    788 f4c8e339 - #
    789 0fd56195 - # Default fallback function
    790 f4c8e339 - #
    791 0fd56195 - def noop_callback(k, x, y):
    792 0fd56195 - """Callback function: arguments key, x, y"""
    793 0fd56195 - return False
    794 0fd56195 -
    795 0fd56195 - def setCallback(k, func=noop_callback):
    796 0fd56195 - """Set the callback for key k to be func, returning the old callback
    797 0fd56195 - """
    798 0fd56195 -
    799 0fd56195 - ofunc = callbacks.get(k)
    800 0fd56195 - callbacks[k] = func
    801 0fd56195 -
    802 0fd56195 - return ofunc
    803 0fd56195 -
    804 0fd56195 - #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    805 0fd56195 -
    806 f4c8e339 - try:
    807 0fd56195 - callbacks
    808 f4c8e339 - except NameError:
    809 0fd56195 - callbacks = {}
    810 0fd56195 -
    811 0fd56195 - for ik in range(ord('a'), ord('z') + 1):
    812 0fd56195 - k = "%c" % ik
    813 0fd56195 - setCallback(k)
    814 0fd56195 - setCallback(k.upper())
    815 0fd56195 -
    816 96ea07d5 - for k in ('Return', 'XPA$ERROR'):
    817 0fd56195 - setCallback(k)
    818 0fd56195 -
    819 0fd56195 - for k in ('q', 'Escape'):
    820 0fd56195 - setCallback(k, lambda k, x, y: True)
    821 0fd56195 -
    822 0fd56195 - def _h_callback(k, x, y):
    823 0fd56195 - print "Enter q or to leave interactive mode, h for this help, or a letter to fire a callback"
    824 0fd56195 - return False
    825 0fd56195 -
    826 0fd56195 - setCallback('h', _h_callback)
    827 0fd56195 -
    828 0fd56195 -

    Return to list

    Commits in /Users/nate/repos_hsc/afw/

    da44d414

    commit da44d414498c54b55e86b5751cff9fc242f309dd
    Author: rhl 
    Date:   Wed Apr 29 17:44:07 2009 +0000
    
        Added support for e.g. ds9.mtv(im, title="Robert the Good"); make Fergal happy #0
    

    5054239e

    commit 5054239eea96cf957f83bd17eb2edc1ae8d594e5
    Author: Robert Lupton the Good 
    Date:   Mon Feb 18 22:20:21 2013 +0900
    
        Provide back-door incase ds9 gets confused about its access point (which it just did on my laptop)
    

    ae6e4fbe

    commit ae6e4fbe3783c06fdc9051bf9857944cf236d350
    Author: rhl 
    Date:   Wed Mar 25 19:14:09 2009 +0000
    
        Teach ds9.py about XPA_PORT to allow remote display by tunelling the two XPA_PORTs (no need to tunnel the xpans ports too)
    

    48d5e5b7

    commit 48d5e5b73d9ee59544ff7547e2c50ff077bf6a10
    Author: Robert Lupton the Good 
    Date:   Wed Jan 16 11:25:31 2013 -0500
    
        We want pan/zoom to take place Now, no need to buffer
        
        Usually important when debugging in a with ds9.Buffering() block
    

    4402095d

    commit 4402095d4b48c21dc2c039fdd808f1455eb30aa2
    Author: rhl 
    Date:   Fri Sep 16 18:49:46 2011 +0000
    
        Allow users to use "with" when buffering dot/line
    

    96ea07d5

    commit 96ea07d58026dcc160626e59384d168f027eaabc
    Author: Robert Lupton the Good 
    Date:   Fri Aug 3 08:04:10 2012 +0900
    
        Toughened callback mechanism
    

    032a990a

    commit 032a990ad36c14ed0a667381a01051907379759c
    Author: rhl 
    Date:   Fri Mar 20 19:03:18 2009 +0000
    
        Allow any colour to be passed through to ds9.  Add setDefaultFrame().  Make zoom() obey frame
    

    a5a0c314

    commit a5a0c3143aec9488b715e08a58e2d20e3a2ee85b
    Author: Robert Lupton the Good 
    Date:   Fri Apr 24 12:09:01 2015 -0400
    
        Remember the choice of colour for mask planes; add CROSSTALK and CLIPPED
    

    88177a06

    commit 88177a064794919e42e1f98b713b0a8ea40b26c2
    Author: Robert Lupton the Good 
    Date:   Wed Jan 16 10:17:15 2013 -0500
    
        Resolved docstring conflict
    

    0fd56195

    commit 0fd56195bfb3b2bed68a42b49e3b47d1f3be2ce4
    Author: Robert Lupton the Good 
    Date:   Thu Aug 2 07:00:07 2012 -0400
    
        Rewrote in a much simpler way as ds9.interact().  N.b. analysis-based approach wasn't implemented to work over a network
    

    236e2ff4

    commit 236e2ff484e912b44a08ed9c08728c52364d1359
    Author: rhl 
    Date:   Mon Jun 27 20:18:23 2011 +0000
    
        Fixed some flush issues (in particular, xpa doesn't seem to use its full 4096 bytes)
    

    4d3c8e52

    commit 4d3c8e528e6aa341be4279b4892602a419a48194
    Author: rhl 
    Date:   Thu Jan 20 20:00:22 2011 +0000
    
        Oops, removed wrong line when cleaning up for commit
    

    4b6acf34

    commit 4b6acf347c723a61081eb7211584ce7712372ddb
    Author: rhl 
    Date:   Wed Jan 13 06:32:59 2010 +0000
    
        Got rotation of detectors by 90n degrees (and non-square dataSecs) working
    

    9e3f07ed

    commit 9e3f07ede97c361b9f3bf34773a3b4c9f968dd0b
    Author: price 
    Date:   Tue Apr 26 22:37:47 2011 +0000
    
        Using mtv's isMask parameter to indicate whether we've already displayed the image.
    

    fde07015

    commit fde07015099a66011a1b0a59943168376885b552
    Author: rhl 
    Date:   Wed Feb 18 23:25:48 2009 +0000
    
        Add WCSB allowing for Image's [XY]0; make all colours visible to doxygen; #0
    

    757abc24

    commit 757abc24786c1b927fd1678020780f76873662d8
    Author: rhl 
    Date:   Thu Dec 6 20:38:04 2007 +0000
    
        Provide support for MaskedImage
    

    f7baf984

    commit f7baf9842b617e7cac53d209cefe7d51a6b62fb9
    Author: Robert Lupton the Good 
    Date:   Thu Oct 3 14:21:47 2013 -0400
    
        Turn off smoothing when displaying on ds9.
        
        Displaying a smoothed MaskedImage smears the mask all over the image, and
        there doesn't seem to be a way to ask ds9 if it's smoothed.  We could leave
        Images smoothed, but for consistency I always turn it off.
    

    d0e42b4a

    commit d0e42b4a20a9d976a0bc19fbd45c4c9cefa3dee6
    Author: Robert Lupton the Good 
    Date:   Tue Mar 20 09:54:51 2012 -1000
    
        Display Masks with missing planes (e.g. 0, 1, 2, 4, 5)
    

    4d7bf935

    commit 4d7bf9351ff03b8c70bf05e8c505a5a81c7c9548
    Author: Robert Lupton the Good 
    Date:   Sun Jul 29 15:43:11 2012 +0900
    
        ds9 7 (and maybe older ds9s?) return an error string, not an exception [it is possible that this is in my xpa wrappers]
        
        N.b. this is usually silently lost.
    

    6ca80c53

    commit 6ca80c535ef82875c17f156d736a796d3e37c996
    Author: price 
    Date:   Thu Nov 4 21:37:08 2010 +0000
    
        Fix creation of (generally) unused frame 0.  ds9 usually starts with frame 1.
    

    9f42c862

    commit 9f42c86204433cdae86a9af3f2817b2be992b5c4
    Author: rhl 
    Date:   Tue Feb 22 09:55:11 2011 +0000
    
        Provide a way to cache writes to ds9
    

    2bd72d8b

    commit 2bd72d8b92635996f5a8dcb3a8ec60dacdbd7e44
    Author: rhl 
    Date:   Sun Mar 29 14:12:25 2009 +0000
    
        Use SUM of Mask to minimise the number of bitplanes sent to ds9
    

    c4cebd54

    commit c4cebd54335a7c0b5bb7f14868bbc23a339d2894
    Author: rhl 
    Date:   Thu Jan 20 19:56:59 2011 +0000
    
        Try to gzip images/masks when sending them to ds9
    

    fd913cf6

    commit fd913cf6690ab7b5a0da4c855b141c1943bc82b6
    Author: rhl 
    Date:   Fri Dec 11 21:17:13 2009 +0000
    
        Fixed ancient mystery as to why you had to import lsst.afw.image before lsst.afw.display.ds9
    

    6b67b592

    commit 6b67b592c35dd859b6c4bfc99e11277731574b39
    Author: bick 
    Date:   Wed Aug 19 21:12:47 2009 +0000
    
        Added a few comments and proper exceptions.  wrapped anonymous material in details namespace.
    

    81f206cb

    commit 81f206cbef85bda2808925dbcaa2e3adf6d973a5
    Author: Robert Lupton the Good 
    Date:   Tue Feb 14 15:27:33 2012 -0500
    
        Don't complain about "with ds9.Buffering()" when ds9 is unavailable
    

    4d6d44fa

    commit 4d6d44fa50557dd94e2e9e619c4293d11e7d0c53
    Author: Robert Lupton the Good 
    Date:   Mon Feb 27 12:15:08 2012 -0500
    
        Fix broken ds9.flush()
    

    0b6b1b7f

    commit 0b6b1b7fa7ae92d7bd2c84e2747300bb20fc029c
    Author: rhl 
    Date:   Mon Mar 2 19:21:49 2009 +0000
    
        Fix ds9.py's text command, and workaround a ds9 5.4 SEGV
    

    7fdf5d77

    commit 7fdf5d77eac6b518ba196a7f77590c763f1fe413
    Author: rhl 
    Date:   Fri Jan 8 13:37:07 2010 +0000
    
        Only do a raise-per-command if using ds9 <= 5.4
    

    b43efd84

    commit b43efd84ee87829e0a017dc232351877ff7249cb
    Author: Robert Lupton the Good 
    Date:   Thu May 24 14:39:04 2012 -0400
    
        Added frame argument to ds9Cmd; convenient for ad hoc commands
    

    4c800cc0

    commit 4c800cc0478f2095041ac1393767e837ddeda294
    Author: Robert Lupton the Good 
    Date:   Sat Aug 4 21:40:33 2012 -0400
    
        Need to initialise all variables
    

    5af71dcc

    commit 5af71dcc09962e9f24d7065b312137e50dbb0ccf
    Author: rhl 
    Date:   Tue May 17 18:39:56 2011 +0000
    
        Cleaned up buffering API
    

    bbef7fe4

    commit bbef7fe429f0d59c584826e866f179945e48e840
    Author: Robert Lupton the Good 
    Date:   Sun Jul 29 15:45:03 2012 +0900
    
        Added support for setting the font size (indirectly, via size=XXX), and
        added e.g. "times bold italic" support at the same time.
    

    c00feea9

    commit c00feea98b0d628ae280348da1a110a5d80fa4e2
    Author: Robert Lupton the Good 
    Date:   Sun Jul 29 15:41:41 2012 +0900
    
        Don't reset needShow on reload
    

    5de5a4e0

    commit 5de5a4e0b4d3989ebb02c6bcd03ec94918e41600
    Author: Robert Lupton the Good 
    Date:   Sun Mar 18 14:00:47 2012 -0400
    
        Handle non-contiguous sets of defined mask planes
    

    77940d02

    commit 77940d024d2f931af8a03390e2bdee2d745a9eff
    Author: rhl 
    Date:   Wed Aug 18 20:54:52 2010 +0000
    
        Handle bad/dead ds9 connections better
    

    df3b085f

    commit df3b085f7827b27f106eb90ad0480f03059f037c
    Author: Robert Lupton the Good 
    Date:   Mon Jan 21 15:00:16 2013 -0500
    
        Fix informative message
    

    030251bb

    commit 030251bb61a39150a34f6e1da54f14da90509329
    Author: Paul Price 
    Date:   Fri May 23 15:16:03 2014 -0400
    
        ds9: display new NO_DATA mask bit as orange
    

    43549001

    commit 43549001a7442d37ac1b32fe0c6178ce023d2387
    Author: rhl 
    Date:   Thu Sep 29 05:00:47 2011 +0000
    
        Improved comment
    

    a2be114f

    commit a2be114ff2a4a21adc98f9214a2a37254d526203
    Author: rhl 
    Date:   Mon Jan 18 03:10:25 2010 +0000
    
        Use numeric IP not localhost to try to help xpa with gethostbyname when not on network
    

    7daa7d7a

    commit 7daa7d7aa453cba88a5bd8a130d6e5fa49db8fb1
    Author: rhl 
    Date:   Mon Feb 23 16:27:06 2009 +0000
    
        Committed multiple files in error.  Log messages should read:
        image.i        Wcs needs to be declared as SWIG_SHARED_PTR_DERIVED to give us access to its Citizen
        simpleFits.cc  Handle invalid but non-NULL Wcs
        MaskedImage.h  boost::shared_ptr initialised pointer to NULL;  setXY0 can set a -ve origin, so get[XY]0 must return signed
        ds9.py         Figured out how ds9 does colour nowadays;  added dot("@:...", ...) to plot ellipses
        MaskedImage.cc Keep identity of Image/Mask/Variance when shallow-copying a MaskedImage
    

    50978a4e

    commit 50978a4ed4e3617b82877c791f66ad4fde7d1022
    Author: Robert Lupton the Good 
    Date:   Fri Apr 13 07:51:09 2012 -0400
    
        Fix botched merge
    

    91ec01a4

    commit 91ec01a4df7bfd88f5db5baac2b2c3fa4255cecf
    Author: Robert Lupton the Good 
    Date:   Wed Apr 24 12:00:15 2013 -0400
    
        Added SUSPECT bit to record untrustworthy pixels (#2838)
    

    a6d55f08

    commit a6d55f08ce9ce259b19b9b8a0c62cc5ecc5b4683
    Author: dgehrig 
    Date:   Mon Jul 12 00:24:33 2010 +0000
    
        adding copyright notices
    

    ae549cd8

    commit ae549cd842d2137adaa4884c303cb62fed556c0a
    Author: rhl 
    Date:   Tue Mar 16 13:53:45 2010 +0000
    
        Survive ds9 versions such as 4.09b
    

    b28bcf63

    commit b28bcf6374ed8df5e85c3307c9a2bfcaddd07208
    Author: Robert Lupton the Good 
    Date:   Wed Aug 1 22:09:08 2012 +0900
    
        Added get argument to ds9Cmd; used it to implement getMaskTransparency
    

    14f8e3a7

    commit 14f8e3a74d096a4018de085884196fb8f79cab85
    Author: rhl 
    Date:   Mon Apr 20 18:01:51 2009 +0000
    
        Keep XPA connection open; important for remote drawing; #0
    

    993791af

    commit 993791aff43a00ff81518138edbf2939ad2a19ea
    Author: rhl 
    Date:   Fri Jan 15 06:36:22 2010 +0000
    
        Misc changes, mostly to do with displaying detectors/mosaics of real data not just synthesized
    

    7c7e5c6d

    commit 7c7e5c6d5384cc9d5c9c2b316b0f523d21dbcb13
    Author: rowen 
    Date:   Thu Mar 27 17:39:11 2008 +0000
    
        afw reorg:
        - lsst.afw will not import sub-packages; thus you need not import all of afw
        - added "orphans.txt": a list of files that belong elsewhere
    

    379e1add

    commit 379e1add3b6ffddad0b78f6e34a9072d65a9b93f
    Author: price 
    Date:   Wed May 18 21:03:36 2011 +0000
    
        Suppress report of caught exception for initial flush (we may not be using ds9 at all).
    

    23ef9f32

    commit 23ef9f32d73edc33cdb3423fbef690ecf20ac26d
    Author: rhl 
    Date:   Tue Apr 26 15:39:36 2011 +0000
    
        Fix display of Mask
    

    54657932

    commit 546579326d3e183e22277db3af3e30b8115a3d57
    Author: Robert Lupton the Good 
    Date:   Wed Oct 17 10:34:04 2012 -0400
    
        Improved a docstring
    

    7009758d

    commit 7009758d8d4a3922440510b5e628d4b969240459
    Author: Robert Lupton the Good 
    Date:   Wed Jan 16 10:18:50 2013 -0500
    
        We need fontFamily and silent
    

    f8edfe90

    commit f8edfe90d99d004aca1819ef00099ce827e44343
    Author: rhl 
    Date:   Sat Nov 15 15:18:25 2008 +0000
    
        Merged from new-image-api branch at [6341]
    

    f4c8e339

    commit f4c8e339bc13c689fe2878ca2a706ca499555bd7
    Author: Robert Lupton the Good 
    Date:   Wed Aug 1 21:28:03 2012 +0900
    
        Added the ability to fire python code when certain keys are hit in ds9.  What a hack, but it works
    

    51522cfe

    commit 51522cfea9e3f71f229781d1c21be6c3ce09c88a
    Merge: 8dc1268 53959da
    Author: rhl 
    Date:   Mon Jan 18 06:10:32 2010 +0000
    
        Merged from #995
    

    73b30db0

    commit 73b30db0cf2faf04672ed19de19bf451d8230745
    Author: rhl 
    Date:   Tue Mar 1 11:56:11 2011 +0000
    
        Allow setMaskTransparency to take a frame
    

    2ebad60d

    commit 2ebad60ddfd2a217aa139655a0e6e7e578da48d2
    Author: rhl 
    Date:   Fri Jan 15 07:57:27 2010 +0000
    
        Started adding Defect support;  make Amp inherit from Detector
    

    0d90bfa0

    commit 0d90bfa0c0701a1466fac5031fa193d7eeaab5d9
    Author: Robert Lupton the Good 
    Date:   Thu Dec 29 10:26:39 2011 -0500
    
        Survive non-contiguous mask planes;  don't write "None" when the title is None
    

    a7aa0c91

    commit a7aa0c91c5a341ec300073538314acbed51946d4
    Author: bick 
    Date:   Tue Jan 5 23:26:49 2010 +0000
    
        Checking-in python changes on #1113.
    

    eb37ae8a

    commit eb37ae8a4a510afdfed8a5373ce1237ef2c7e38f
    Author: rhl 
    Date:   Wed May 20 22:06:40 2009 +0000
    
        Initial version
    

    8864f403

    commit 8864f403eb72675a154579284538d179b7ee251a
    Author: rhl 
    Date:   Thu Aug 25 17:46:09 2011 +0000
    
        Can't refer to function as ds9.XXX from within ds9.py
    

    2eb9dac3

    commit 2eb9dac33eec6f13a73c03cc2827aa9884ff06cc
    Author: rowen 
    Date:   Mon Sep 28 22:55:55 2009 +0000
    
        Removed all tabs.
    

    8d74933b

    commit 8d74933bcf4dccfbb599d4faaf6e1ff8a8f199f4
    Author: Robert Lupton the Good 
    Date:   Sat Jul 28 14:08:48 2012 +0900
    
        Support draw('*', ...)
    

    03b53c5c

    commit 03b53c5cbf9483d089dd48cfabfedaf953ad2a68
    Author: rhl 
    Date:   Mon Feb 12 23:12:54 2007 +0000
    
        Initial swigged-up VW to talk to ds9
    

    7df3a916

    commit 7df3a9168d3966aa398729106474b70b2df74f74
    Author: rhl 
    Date:   Thu Mar 20 14:03:51 2008 +0000
    
        Rework setMaskPlaneColor to accept a dictionary; add setMaskPlaneVisibility
    

    6edafcfa

    commit 6edafcfa53e1cd4b204a1fea8b312a4cef9b7dc4
    Author: rhl 
    Date:   Sat Mar 20 18:52:05 2010 +0000
    
        Return more useful error message when ds9 fails to return a version
    

    097d37d8

    commit 097d37d8c1d4c15f25048faee48813a86f24e6dc
    Author: rhl 
    Date:   Mon May 3 06:51:42 2010 +0000
    
        Added support for the lowest frame to use in ds9
    

    dd48cbc1

    commit dd48cbc1869b65a2bbd0885412e9bf0f0fe963eb
    Author: rhl 
    Date:   Sun Feb 10 15:23:35 2008 +0000
    
        Support for Masks and MaskedImage
    

    ff5aab1b

    commit ff5aab1b1b5613cd72634a484c690e234097391a
    Author: rhl 
    Date:   Tue Jul 7 16:00:40 2009 +0000
    
        Changes in response to Russell's review
    

    Commits in /Users/nate/repos_lsst/afw/

    097d37d8

    commit 097d37d8c1d4c15f25048faee48813a86f24e6dc
    Author: rhl 
    Date:   Mon May 3 06:51:42 2010 +0000
    
        Added support for the lowest frame to use in ds9
    

    bde0ab27

    commit bde0ab27a9add858f810563213c1424f9e63ddde
    Author: Robert Lupton the Good 
    Date:   Sun Apr 12 16:00:47 2015 -0300
    
        Implement RFC-42
        
        N.b. that you need display_ds9 to use the ds9 backend
        N.b. support frame only in cameraGeom.utils top-level routine, showCamera
    

    23ef9f32

    commit 23ef9f32d73edc33cdb3423fbef690ecf20ac26d
    Author: rhl 
    Date:   Tue Apr 26 15:39:36 2011 +0000
    
        Fix display of Mask
    

    7df3a916

    commit 7df3a9168d3966aa398729106474b70b2df74f74
    Author: rhl 
    Date:   Thu Mar 20 14:03:51 2008 +0000
    
        Rework setMaskPlaneColor to accept a dictionary; add setMaskPlaneVisibility
    

    Return to list